HttpContent.ReadAsString() in WCF WebAPI 0.6?

Topics: Web Api
Jan 11, 2012 at 12:39 AM

Sorry if this is a FAQ :-)  but I just upgraded from 0.5 to 0.6 and I can't find System.Net.Http.HttpRequestMessage.HttpContent.ReadAsString().  What should I use instead?

I'm use this in a logging behavior which logs every incoming / outgoing message from my service.  My code:

    public class LoggingMessageTracer : IDispatchMessageInspector,
        IClientMessageInspector
    {
        private Message TraceHttpRequestMessage(HttpRequestMessage msg)
        {
            string tracemsg = String.Format(
                "Web Request on URL: {0}\n" +
                "Header: {1}\n" +
                "Body: {2}",
                msg.RequestUri.AbsoluteUri,
                msg,
                msg.Content != null ? msg.Content.ReadAsString() : "(empty)");

            LoggingHelper.TraceLine(tracemsg, LoggingHelper.LogLevel.Info);

            return msg.ToMessage();
        }

 


Thanks!

Omri.

 

Jan 11, 2012 at 12:53 AM

Googled around, eventually found this.  (it's really the only resource I could find on this issue :-( )

http://www.bizcoder.com/index.php/2012/01/09/httpclient-it-lives-and-it-is-glorious/

I get that you'd want to encourage / require an async prog model on the client.. but the HttpContent class is used on the server as well, and I think it's quite reasonable for a developer to get the request as a string... or, more importantly, to get the request stream using HttpContent.ContentReadStream, which is also missing!

I don't want to learn/take a cognitive dependency on the Task programming model in order to use WCF WebAPI. 

Is there any other way to do what I'm trying to do?

Thanks,

Omri.

 

Jan 11, 2012 at 6:19 AM

After some messing around in the TPL docs and realizing that .ContinueWith() won't work for me (because my method expects to return a value), I found Task<T>.Result, which seems to do the trick (in spite of warnings to the contrary on this thread which recommended using ContinueWith). 

So my code looks like this:

            string tracemsg = String.Format(
                "Web Request on URL: {0}\n" +
                "Header: {1}\n" +
                "Body: {2}",
                msg.RequestUri.AbsoluteUri,
                msg,
                msg.Content != null ? msg.Content.ReadAsStringAsync().Result : "(empty)");

As good as I could have hoped for as far as syntax.

FWIW, I still think it's weird that on the server I have to do msg.Content.ReadAsStreamAsync() just to get the content stream (which presumably simply returns me a reference to an existing stream, and isn't an operation I would expect that I'd need to do asynchronously).

 

Jan 11, 2012 at 6:43 AM

If you create a DelegatingHandler, the you can do something like this:

 

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            foreach (var header in request.Content.Headers)
            {
                logger.DebugFormat("{0}:\t{1}", header.Key, header.Value);
            } 
            logger.Debug(request.Content.ReadAsStringAsync().Result);
            return base.SendAsync(request, cancellationToken);
        }

Søren