Monthly Archives: January 2012

The new System.Net.Http classes: message content

The 4.5 version of the .NET platform introduces the new System.Net.Http namespace with several HTTP related classes. These classes are also available for .NET 4.0, via the Web API Preview 6 distribution (both source code and NuGet package).

A previous post introduced the HTTP core classes (HttpRequestMessage, HttpResponseMessage and HttpMessageHandler) and described the HttpClient class in detail.

This post addresses HTTP message’s content manipulation , and is based on the Web API Preview 6 distribution. Some links point to the MSDN preliminary 4.5 documentation, while others point to the Web API Preview 6 source code; so expect discrepancies. Notice that this post is based on preview code and documentation; the final .NET 4.5 classes may be different of what is described here.

The HttpContent class

The content of both request and response messages is access via the Content property, of type HttpContent.
HttpContent.2

The HttpContent class contains a Headers property, with the content related HTTP headers (e.g. Content-Language, Content-Type, Last-Modified).

It also contains a set of ReadAsXxx methods for asynchronously accessing the content body:

  • Task<Stream> ReadAsStreamAsync()
  • Task<byte[]> ReadAsByteArrayAsync()
  • Task<string> ReadAsStringAsync()

 

Creating new content

Reading the message raw content, as a byte sequence or as a string, is accomplished using one of the above methods. However, creating new content involves a hierarchy of concrete classes, rooted at the abstract HttpContent class.

 

HttpContent.untyped.hierarchy

Each one of those classes support a specific type of content or content source. For instance, producing a string based content is accomplished by creating a StringContent instance, parameterized with the string content, the character encoding, and the media type.

Typed Content

The System.Net.Http namespace also contains a ObjectContent class for representing strongly typed content, i.e., content based on a strongly typed object.

As depicted in the following diagram, the ObjectContent derives from HttpContent.  There is also a ObjectContent<T> deriving from ObjectContent, which uses a generic parameter instead of a Type instance to represent the content’s type.

TypedContent

 

The ObjectContent is used differently when reading content or producing content.

Reading strongly typed content

When reading strongly typed content, an ObjectContent instance is created from a HttpContent and a MediaTypeFormatter is used to convert the HttpContent’s stream into the ObjectContent’s object.

Stream.formatter.T

The HttpContentExtensionMethods class contains extension methods to do this

ContentExtensions

For instance, the ReadAsAsync method performs the following

public static Task ReadAsAsync(this HttpContent content)
{
    if (content == null)
    {
        throw new ArgumentNullException("content");
    }
    return BuildObjectContent(content).ReadAsAsync();
}

private static ObjectContent BuildObjectContent(HttpContent content)
{
    ObjectContent objectContent = content as ObjectContent;
    if (objectContent == null)
    {
        objectContent = new ObjectContent(content);
    }
    return objectContent;
}

Note that reading strongly typed content involves two contents:

  • The original message content, exposed as a byte stream.
  • The object content, containing an object obtained from the above stream.

 

Producing strongly typed content

Producing strongly typed content is simpler: just create a ObjectContent (or ObjectContent<T>) instance, passing in the object. Since, ObjectContent derives from HttpContent, this new instance can be directly used as a message content. Internally, a MediaTypeFormatter is used to convert from the typed object into a stream (e.g. when a request message is serialized “to the wire”).

 

T.Formatter.stream

Notice that the MediaTypeFormatter class is used for bidirectional conversion:

  • From a byte stream into a typed object.
  • From a typed object into a byte stream.

This class will be the subject of a future post.

Final remarks

  • Abstract HttpContent base class for representing HTTP message content. Contains a set of methods for reading the content’s body as a byte sequence or a string.
  • Concrete HttpContent-derived classes for creating content.
  • ObjectContent and ObjectContent<T> classes for reading and creating HTTP message body content from strongly typed objects.

The new .NET HttpClient class

A recent post by Darrel Miller, entitled “HttpClient, it lives, and it is glorious.” motivated me to investigate more about the HttpClient class underlying architecture.
This post is the result of that study, and focus mainly on design and organization aspects, namely extensibility.
For code examples, refer to Darrel’s excellent post.

Introduction

The HttpClient class is the .NET (yet another) new client for the HTTP protocol, similar in purpose to HttpWebRequest and WebClient. It is being introduced with .NET 4.5, however there is also an implementation for .NET 4.0 associated with Web API (both source code and NuGet package).

The HttpClient class should not be viewed in isolation or as just a replacement for WebClient. It is part and takes advantage of a set of new classes for the HTTP protocol, present in the System.Net.Http namespace, which are the subject of the next section.

Core HTTP Abstractions

The HTTP protocol is an application level request-response protocol that operates by exchanging messages. The new HttpRequestMessage and HttpResponseMessages framework classes are used to represent these messages. A previous post described these classes on the Web API context. However, they are used outside of that context, namely on the client side.

The computation that produces response messages, given request messages, is represented by the abstract HttpMessageHandler class. To avoid blocking the calling thread, this computation signature is asynchronous, that is, a Task<HttpResponseMessage> is returned instead of a HttpResponseMessage. The “WCF Web API–Message Handlers” post described this new class in the Web API context. However this new class is not used exclusively by the Web API. Namely, similarly to HttpRequestMessage and HttpResponseMessage, this new class is in the System.Net.Http and not on a Web API namespace.

request.handler.response

Frequently, messages handlers delegate the response computation to other handlers. Consider, for example, a caching intermediary. If a response to a request can be produced from cached information, then the caching intermediary produces the response directly. Otherwise, the caching component forwards the request message to another handler and caches the response information.

delegating.handler

The class DelegatingHandler is used to represent this particular kind of response computation, where the forwarding handler reference is stored on an InnerHandler property.

HttpClient Architecture

The HttpClient class is used to create HTTP request messages, manage the request-response process and extract the response’s content. However, it delegates the actual sending of the request and the asynchronous response reception to a message handler.

HttpClientAndInnerHandler

Given the usage of a message handler, the HttpClient class may seem redundant. Namely, it is possible to explicitly create a request and use a message handler to obtain a response. However, the HttpClient class adds some relevant functionality:

  • Set of helper methods that create requests and also process the responses (e.g. public Task<string> GetStringAsync(string requestUri)).
  • Definition of a default header set, that is applied to all sent messages (DefaultRequestHeaders property).
  • Timeout and cancellation management (e.g. Timeout property and CancelPendingRequests() method).

The .NET framwork provides two message handlers classes, that can be used with the HttpClient for sending requests: the HttpClientHandler class and the WebRequestHandler class. They both use the old HttpWebRequest internally. The major difference is that WebRequestHandler exposes HttpWebRequest functionality that isn’t available in all platforms (e.g. the Pipelined property is not available on Silverlight). On the other hand, HttpClientHandler should be usable on all platforms.

The handler used by a HttpClient instance is defined in its constructor. If  absent, a HttpClientHandler instance is used by default.
A common technique is to explicitly create a client handler (e.g. HttpWebRequest), then explicitly set some of its properties and finally use it to create a HttpClient instance. Darrel’s  Windows authentication example  is an example of this technique.

The following diagram presents the relation between these classes.

HttpClient

Note that this architecture allows the composition of intermediary delegating handlers (e.g. client side caching), resulting in a handler pipeline.

HttpClientAndHandlerPipeline

Conclusions

In conclusion,