Tag Archives: WCF Web API

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.

WCF Web API–building an Authorize attribute

This is the thirteenth post on a series about the WCF Web API Preview 4 and 5.  Last post focused on custom operation parameter conversion. This post shows how to also use operation handlers to build something similar to ASP.NET MVC’s AuthorizeAttribute.

The goal is to have an attribute to annotate operations with authorization requirements, such as the illustrated by the following excerpt.

[ServiceContract]
class TheService
{
    [Authorize("Alice")]
    [WebGet(UriTemplate="")]
    HttpResponseMessage Get(...)
    {
		...
    }
}

Notice the [Authorize(“Alice”)] requiring the request’s user to have the “Alice” identity name.

WCF Web API doesn’t have MVC’s filters. However, it is possible to have a similar behavior using operation handlers. The following figure shows the overall idea.

Authorize

 

  • The EnableAuthorizeAttribute configuration extension method checks if the operation’s description contains any AuthorizeAttribute. If so, it adds a AuthorizeOperationHandler instance to the operation handler pipeline. This instance receives the user identity extracted from the AuthorizeAttribute.
  • The AuthorizeOperationHandler declares one input parameter, of type IPrincipal. During the request processing, this handler checks if the input principal has the same identity as the one extracted from the AuthorizeAttribute. If not, it terminates the request before it reaches the operation, by throwing an HttpResponseException.
  • Notice that the AuthorizeOperationHandler is completely decoupled from the authentication process. The authorization’s only dependency is on a principal injected as a parameter.
  • If the operation doesn’t have a AuthorizeAttribute, then no AuthorizationOperationHandler is added to its pipeline.
  • Notice that the end developer only has to annotate the operations with the AuthorizeAttribute and call the EnableAuthorizeAttribute over the configuration, to enable this behavior.

Finally, the (draft) code is available at https://github.com/pmhsfelix/WcfWebApi.Preview5.Explorations.

WCF Web API–Custom parameter conversion

This is the twelfth post on a series about the WCF Web API Preview 4 and 5 releases. Last post focused on operation handlers. The present post shows how to use this handler type to perform custom operation parameter conversion.

 

Operation parameters

On a WCF Web API operation, the URI template variables can be injected as operation’s parameters. The following code excerpt shows a typical example, where the resource identifier (an integer) is obtained from the URI and used as a parameter.

[WebGet(UriTemplate = "{id}")]
public HttpResponseMessage<Contact> Get(int id){...}

 

As stated in a previous post, these parameters are retrieved from the URI template match result and added into the operation parameter collection by the UriTemplateHandler handler. However, this handlers outputs these parameters as strings. What if the operation expects a different type, such as the integer id used in the above example? Web API runtime knows how to convert these strings into other types, such as integers. However it doesn’t support user-defined types. For instance, consider the following example, using the user-defined AComplexType and AnotherComplexType types.

class AComplexType
{
    public string Value { get; set; }
}
class AnotherComplexType
{
    public int Value { get; set; }
}

[WebGet(UriTemplate = "{prm1}/{prm2}")]
HttpResponseMessage Get(AComplexType prm1, AnotherComplexType prm2)
{
...
}

How is it possible to define the conversion from string into AComplexType and AnotherComplexType, and have it done before the operation is called?

One way of doing this is by using custom operation handlers that:

  • receives prm1 and prm2 as strings;
  • outputs them as AComplexType and AnotherComplexType.

The following handler does exactly this for a generic T type:

public class ParameterConversionOperationHandler<T> : HttpOperationHandler
{
    private readonly HttpOperationDescription _desc;
    private readonly Func<string, T> _conv;

    public ParameterConversionOperationHandler(HttpOperationDescription desc, Func<string, T> conv)
    {
        _desc = desc;
        _conv = conv;
    }

    protected override IEnumerable<HttpParameter> OnGetInputParameters()
    {
        return _desc.InputParameters
            .Where(prm => prm.ParameterType == typeof(T))
            .Select(prm => new HttpParameter(prm.Name, typeof(string)));
    }

    protected override IEnumerable<HttpParameter> OnGetOutputParameters()
    {
        return _desc.InputParameters
            .Where(prm => prm.ParameterType == typeof(T));
    }

    protected override object[] OnHandle(object[] input)
    {
        var res = new object[input.Length];
        for (var i = 0; i < input.Length; ++i)
        {
            res[i] = _conv(input[i] as string);
        }
        return res;
    }
 }

 

  • The constructor receives a Func<string, T>, i.e. a function that converts a string into a T.
  • The OnGetInputParameters finds all the operation’s parameters that have type T and returns them as string input parameters. This means that the Web API runtime will input string parameters into the handler, when processing a request.
  • Finally, the OnHandle method uses the conversion function (Func<string,T>) to convert all the input string values into T output values.

 

Handler registration

The final step is to add an instance of this handler, into the request handlers collection, for each custom type T that we want to be converted. One way of achieving this is by extending  the new Preview 5 configuration model. The following code fragment shows its usage

var config = new HttpConfiguration()
                .UseParameterConverterFor<AComplexType>(
                    s => new AComplexType {Value = s.ToUpper()})
                .UseParameterConverterFor<AnotherComplexType>(
                    s => new AnotherComplexType {Value = Int32.Parse(s)+1});

using (var host = new HttpServiceHost(typeof(TheService), config, "http://localhost:8080/"))
{
    ...
}

 

The UseParameterConverterFor is a HttpConfiguration extension method, receiving the target type T and the conversion function,  which registers the required operation handler.

public static class ParameterConversionExtensions
{
    public static HttpConfiguration UseParameterConverterFor<T>(
	    this HttpConfiguration cfg, Func<string, T> conv)
    {
        cfg.AddRequestHandlers((coll, ep, desc) =>
            {
                if (desc.InputParameters.Any(p => p.ParameterType == typeof (T)))
                {
                    coll.Add(new ParameterConversionOperationHandler<T>(desc, conv));
                }
            });
        return cfg;
    }
}

Note the conditional addition to the handlers collections: the handler is only added if the operation has at least one parameter of type T.

This extension method uses another HttpConfiguration extension method: AddRequestHandlers.

public static class HttpConfigurationExtensions
{
    public static HttpConfiguration AddRequestHandlers(
	    this HttpConfiguration conf, 
        Action<Collection<HttpOperationHandler>, ServiceEndpoint, HttpOperationDescription> requestHandlerDelegate)
    {
        var old = conf.RequestHandlers;
        conf.RequestHandlers = old == null ? requestHandlerDelegate :
                                        (coll, ep, desc) =>
                                        {
                                            old(coll, ep, desc);
                                            requestHandlerDelegate(coll, ep, desc);
                                        };
        return conf;
    }
}

This new method adds the registration of a new configuration action without removing the ones that may already be defined, i.e., allows for the composition of multiple actions by independent extensions.

Concluding remarks

Some concluding remarks:

WCF Web API–Operation Handlers

This is the eleventh post on a series about the Preview 4 of WCF Web API. The sixth post, entitled WCF Web API–Processing Architecture, presented Web API’s runtime architecture, introducing several key architectural elements, namely message handlers and operation handlers. The last post described message handlers in more detail. In this post, the focus goes to operation handlers.

Operation handlers

Operation handlers are a WCF Web API extensibility point located after an operation is selected by the dispatcher, but before the operation’s method is called, as shown in the following diagram.

Pipelines

There is only one message handler pipeline, where each handler can execute before and after the operation’s invocation. However, there are two operation handler pipelines. The first, called the request pipeline, is composed by the operation handlers executed before the operation’s invocation. The second, called the response pipeline, is constituted by the operation handlers executed after the operation’s call. This characteristic is also visible in the above diagram.

Request pipeline

As described in the first post of this series, each operation has a set of input parameters, such as the request’s HttpRequestMessage, URI template variables and others. In the description model, these parameters are represented by the HttpParameter class (see this post for more information)

The main role of the request pipeline, located between the operation dispatcher and the operation’s method call, is to provide all the parameters required for this invocation. Despite the name similarity, there are significant differences between operation handlers and message handlers:

  • A message handler receives a HttpRequestMessage. An operation handler receives a set of HttpParameters, dynamically defined at startup.
  • A message handler asynchronously produces an HttpResponseMessage, by returning a Task<HttpResponseMessage>, which is typically completed after the operation was invoked. A request operation handler synchronously returns a set of HttpParameterbefore the operation is invoked. This HttpParameter set is also dynamically defined at startup.
  • A message handler can completely ignore the inner message handler, short-circuiting the operation’s invocation, and producing an HttpResponseMessage directly. The only way for an operation handler to short-circuit the call to the operation is by throwing an exception.

Defining operation handlers

An operation handler is defined by a class derived from HttpOperationHandler, as shown in the following code excerpt

class LoggingOperationHandler : HttpOperationHandler
{
    protected override IEnumerable<HttpParameter> OnGetInputParameters()
    {
		...
    }

    protected override IEnumerable<HttpParameter> OnGetOutputParameters()
    {
		...
    }

    protected override object[] OnHandle(object[] input)
    {
		...
    }
}

The OnGetInputParameters method returns a sequence of HttpParameter, defining the parameters that must be provided to the handler, i.e., the parameter names and types.

The OnGetOutputParameters method returns a sequence of HttpParameter, defining the parameters that are provided by the handler.

The above two methods are called only once, at startup. The third method, OnHandle, is called per request. It receives the input parameter values, declared by OnGetInputParameters, and returns the output parameter values, declared by OnGetOutputParameters.

Since the operation handler’s contract is dynamically defined by the two first methods, and not defined at compile time, the input and output type is object. However, WCF Web API contains a set of generic classes, such as HttpOperationHandler<T, TOutput>, where the input and output types are statically defined and the OnGetXxxxParameters methods are already implemented.

GenericHttpOperationHandler

Built-in operation handlers

WCF Web API uses the operation handler extensibility point to provide the parameters typically used by an operation. This is done by a set of built-in operation handlers, namely:

Example: tracing the parameter values

The following code excerpt shows a demo operation handler that inserts all the input parameters into the trace output.

class LoggingOperationHandler : HttpOperationHandler
{
    private readonly HttpParameter[] _prms;
    public LoggingOperationHandler(HttpOperationDescription desc)
    {
        _prms = desc.InputParameters.ToArray();
    }

    protected override IEnumerable<HttpParameter> OnGetInputParameters()
    {
        return _prms;
    }

    protected override IEnumerable<HttpParameter> OnGetOutputParameters()
    {
        yield break;
    }

    protected override object[] OnHandle(object[] input)
    {
        TraceInputs(input);
        return new object[0];
    }

    private void TraceInputs(object[] input)
    {
        var sb = new StringBuilder("# begin inputs trace #\n");
        for (int i = 0; i < _prms.Length; ++i)
        {
            sb.AppendFormat("  {0} : {1}\n", _prms[i].Name, input[i]);
        }
        sb.AppendLine("\n# end inputs trace #");
        Trace.Write(sb.ToString());
    }
}

Notice the following:

  • This handler receives exactly the same parameters as the operation’s method. This is accomplished by using the HttpOperationDescription to  obtain this information and return it on the OnGetInputParameters.
  • This handler has no output parameters.
  • The OnHandle method receives the operation’s input parameter values and writes them into the trace output.
  • Since the input parameter collection is not known in compile time, this operation handler derives directly from HttpOperationHandler and not from one of the generic overloads.

Example: extracting the user’s identity and add it as a parameter

The following code excerpt shows another example of an operation handler. This one extracts the user’s identity from the request’s headers, creates an IPrincipal and adds it as an parameter.

class PrincipalFromBasicAuthenticationOperationHandler : HttpOperationHandler<HttpRequestMessage,IPrincipal>
{
    public PrincipalFromBasicAuthenticationOperationHandler() : base("Principal")
    {
    }

    public override IPrincipal OnHandle(HttpRequestMessage input)
    {
        Console.WriteLine("PrincipalFromBasicAuthenticationOperationHandler.OnHandle");
        if (input.Headers.Authorization == null || input.Headers.Authorization.Scheme != "Basic")
        {
            // If properly configured, this should never happen:
            // this OperationHandler should only be used when 
            // Basic authorization is required
            throw new HttpResponseException(HttpStatusCode.InternalServerError);
        }
        var encoded = input.Headers.Authorization.Parameter;
        var encoding = Encoding.GetEncoding("iso-8859-1");
        var userPass = encoding.GetString(Convert.FromBase64String(encoded));
        int sep = userPass.IndexOf(':');
        var username = userPass.Substring(0, sep);
        var identity = new GenericIdentity(username, "Basic");
        return new GenericPrincipal(identity, new string[] { });
    }
}

This class derives from the genericHttpOperationHandler<HttpRequestMessage,IPrincipal>, since the input and output are known at compile time. The constructor calls the base constructor defining the output parameter’s name. The OnHandle method uses the Authorization header to extract the user’s identity, assuming that it was already validated (by the WCF runtime or by a message handler, see this post).

Since this handler adds an IPrincipal as a parameter, now any operation can use this interface as an input parameter

[ServiceContract]
class TheResourceClass
{
    [WebGet(UriTemplate="resources/{id}")]
    HttpResponseMessage GetSomething(HttpRequestMessage req, int id, IPrincipal principal)
    {
        ...
    }
}

Operation handler order

With message handlers, the execution order equals the configuration order. However, with operation handlers things are different. Since there could be handlers that need the output of other handlers, the execution order must satisfy this parameter dependency.

For example, consider an handler that receives an IPrincipal and uses it to evaluate an authorization policy. This handler must be executed after the above PrincipalFromBasicAuthenticationOperationHandler, in order to receive the user’s identity.

On startup, the WCF runtime uses the input and output handler information (via the OnGetInputParameters/OnGetOutputParameters methods) to compute a permutation of the configuration order that satisfies the input-output dependencies. If such an order doesn’t exists, an exception is throwed when the service starts.

The following diagram illustrates these dependencies.

OperationHandlers2

Configuration

The operation handlers can be configured via an operation handler factory, as the one showed in the next code excerpt

class MyOperationHandlerFactory : HttpOperationHandlerFactory
{
    protected override Collection<HttpOperationHandler> OnCreateRequestHandlers(ServiceEndpoint endpoint, HttpOperationDescription operation)
    {
        var coll = base.OnCreateRequestHandlers(endpoint, operation);
        if (operation.InputParameters.Any(p => p.Type.Equals(typeof(IPrincipal))))
        {
            var binding = endpoint.Binding as HttpBinding;
            if (binding != null && binding.Security.Transport.ClientCredentialType == HttpClientCredentialType.Basic)
            {
                coll.Add(new PrincipalFromBasicAuthenticationOperationHandler());
            }
        }
        return coll;
    }
}

Notice the following:

  • The call to the base.OnCreateRequestHandlers, so that the built-in handlers are also included in the collection.
  • The conditional addition logic, using service description information from the ServiceEndpoint and from HttpOperationDescription: the PrincipalFromBasicAuthenticationOperationHandler is only added if the operation requires an IPrincipal and the binding is using HttpClientCredentialType.Basic.

External resources

Finally, here are some interesting references about message handlers:

WCF Web API–Message Handlers

This is the tenth post on a series about the Preview 4 of WCF Web API. The sixth post, entitled WCF Web API–Processing Architecture, presented Web API’s runtime architecture, introducing several key architectural elements, namely message handlers and operation handlers.

In this post, I describe message handlers in more detail, presenting some examples and a set of external resources on this subject.

Message handlers

Message handlers are a WCF Web API extensibility point located after a HttpRequestMessage is retrieved from the transport channel but before this message is dispatched to an operation, as shown in the following diagram

Message handlers are also located before the operation handlers. This has several consequences:

  • The same message handler instance is used for all the operations, i.e., all request URIs and HTTP methods. Namely, the handler doesn’t have access to the dispatching result – the final operation. However, there are different message handler instances per endpoint.
  • The message handler only has access to the request message and not to the operation’s parameters.

Message handlers use a “russian-doll” model, also used by other frameworks:

  • On initialization, each message handler receives a reference to a inner handler.
  • On request processing, each message handler receives the request and is responsible to produce a response, eventually delegating that task to the inner handler (in Preview 4 message handlers are still called delegating handlers).

However, message handlers don’t use a synchronous model. Instead, they use an asynchronous model, based on the Task<T> class: instead of returning a HttpResponseMessage, a message handler must return a Task<HttpResponseMessage>. This means that message handlers are an adequate extension point to insert lengthy I/O requests.

On Preview 4, a message handler is a class that must derive from DelegatingChannel and overrides the SendAsync method.

Example: Adding an header with the elapsed time

The following code excerpt show a simple message channel that records the request’s processing time and adds an header to the response with it. Note how, after creating the Stopwatch, the request is simply delegated to the inner handler (base.SendAsync)

class ElapsedTimeMessageHandler : DelegatingChannel
{
    public ElapsedTimeMessageHandler(HttpMessageChannel innerChannel)
        : base(innerChannel)
    {
    }

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var sw = new Stopwatch();
        sw.Start();
        return
            base.SendAsync(request, cancellationToken)
                .ContinueWith(task =>
                    {
                        sw.Stop();
                        task.Result.Headers.Add("X-Elapsed-Time", 
						    sw.ElapsedMilliseconds.ToString());
                        return task.Result;
                    },TaskContinuationOptions.ExecuteSynchronously);
    }
}

 

Example: HTTP intermediary

A message handler doesn’t even need to call the inner handler. Namely, it can completely bypass the upper WCF runtime stack.

The following code excerpt shows a message handler prototype that simply forwards all the HTTP requests to the origin server, using an HttpClient object. It illustrates a simplistic way of implementing HTTP  intermediaries (e.g. proxies).

class ProxyMessageHandler : DelegatingChannel
{
    private readonly HttpClient _client = new HttpClient();
    public ProxyMessageHandler(HttpMessageChannel innerChannel)
        : base(innerChannel)
    {
    }

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            var req = new HttpRequestMessage
                    {
                        RequestUri =
                            new Uri("http://" + request.Headers.Host + request.RequestUri.PathAndQuery),
                        Method = request.Method
                    };
            if (req.Method == HttpMethod.Post || req.Method == HttpMethod.Put)
            {
                req.Content = request.Content;
            }
            foreach (var h in request.Headers.Where(h => !h.Key.StartsWith("Proxy-")))
            {
                req.Headers.Add(h.Key, h.Value);
            }
            var resp = _client.SendAsync(req,HttpCompletionOption.ResponseHeadersRead);
            resp.ContinueWith(t => TraceResponse(req,t));
            return resp.ContinueWith(t =>
                {
                    t.Result.Headers.Remove("Transfer-Encoding");
                    return t.Result;
                });
        }
        catch (Exception e)
        {
           TraceException(e);
            throw;
        }
    }
}

 

Configuration

Message handlers can be configured via a HttpHostConfiguration class and the AddMessageHandlers method. This is illustrated in the following code excerpt. Notice that ProxyMessage handler is the inner handler of ElapseTimeMessageHandlers.

var cfg = HttpHostConfiguration.Create()
			.AddMessageHandlers(typeof(ProxyMessageHandler), typeof(ElapsedTimeMessageHandler));
	
using (var host = new HttpConfigurableServiceHost(typeof(TheService), cfg, new Uri(...)))
...

External resources

Finally, here are some interesting references about message handlers:

WCF Web API– Handling requests asynchronously

This is the ninth post on a series about the Preview 4 of WCF Web API. The previous posts were:

In this post, I show how to handle HTTP requests asynchronously.

.NET’s Asynchronous Programming Model (APM)

The first version of the .NET platform introduced the Asynchronous Programming Model (APM) to represent asynchronous operations. It is characterized by the following:

  • Each asynchronous operation is divided into two methods, the Begin method and the End method;
  • The Begin method receives the operation’s inputs and two extra parameters – an AsyncCallback and an object state. This method must return an IAsyncResult, representing the asynchronous operation.
  • The End method receives the above IAsyncResult and returns the operation result, waiting if it is not yet available

The APM model is used in several places of the .NET platform. Some examples are stream reading and writing; and asynchronous delegate invocation.

Currently, WCF also uses the APM model both on the client side and on the service side:

  • On the client-side, the generated proxies can expose each WCF operation as a Begin/End method pair.
  • On the service-side, the implementing class may expose a Begin/End method pair that will be called asynchronously by the WCF runtime.

The Preview 4 release of WCF Web API also supports this model. The following code excerpt shows an example of decomposing an Web API operation into a Begin and End methods

[OperationContract(AsyncPattern = true)]
[WebGet(UriTemplate = "image?uri={uri}")]
private IAsyncResult BeginGetImage(HttpRequestMessage req, string uri,
                                                 AsyncCallback ac, object state)
{
	...
}

private HttpResponseMessage EndGetImage(IAsyncResult ar)
{
	...
}

The usage of the asynchronous model is defined by the AsyncPattern property assigned with true on the OperationContract attribute.

More details about the AsyncPattern in “classical” WCF can be found in the following post series: WCF and the AsyncPattern property.

The Task-based model

The version 4.0 of .NET introduced a new asynchronous model based on the Task<T> class and TPL library. A Task<T> represents an asynchronous operation that returns a value of type T. On a first look, this class may seem similar to IAsyncResult, however there are significant differences:

  • No need to call an End operation to retrieve the result. Instead, this value can be obtained from the task itself.
  • Better support for cancellation, through cancellation tokens.
  • Better support for exception handling.
  • Native support for asynchronous operation composition, via the ContinueWith and the ContinueWhenAll/ContinueWhenAny methods.

The announced C#async support is also based on the Task<T> model and will provide a language integrated way of building and composing asynchronous operations.

In the .NET framework, this new Task<T> model is slowly replacing the APM model. For instance:

  • The new .NET’s HTTP client (HttpClient class) provides a set of XxxAsync methods, returning Task<HttpResponseMessage>, for performing asynchronous HTTP requests.
  • The WCF Web API message handlers, briefly described in the sixth post of this series, also use the new Task<T> model.

Using both asynchronous models

Unfortunately, the Preview 4 of WCF Web API doesn’t yet support the Task<T> model for the operation implementation. However, it is not hard to implement a APM based interface using Task<T>, as described in the following reference: TPL and Traditional .NET Asynchronous Programming. The key fact is that the Task<T> class also implements the IAsyncResult interface.

An example

To exemplify these concepts, the following example shows a service for image transcoding. It has one operation, that handles GET requests on the following URI template “image?uri={uri}”, and performs the following actions:

  • GETs the representation of the resource (an image) identified by the {uri}
  • Tries to build a bitmap with this resource’s representation
  • Encodes and returns the bitmap using the JPEG format

Obtaining the response to the GET request and all the associated representation bytes may take a significant time. In order to avoid keeping a thread blocked during this time, this operation’s implementation will be asynchronous.

private HttpResponseMessage _response;
private HttpResponseException _exception;

[OperationContract(AsyncPattern = true)]
[WebGet(UriTemplate = "image?uri={uri}")]
private IAsyncResult BeginGetImage(string uri, AsyncCallback ac, object state)
{
    Trace("BeginGet...");
    var task = Task.Factory.Iterate(GetImageAndConvertItToJpeg(uri), state);
    task.ContinueWith(t =>
        {
         Trace("Main task completed, calling callback");
         if (ac != null) ac(task);
        }, TaskContinuationOptions.ExecuteSynchronously);
     return task;
}

private HttpResponseMessage EndGetImage(IAsyncResult ar)
{
    Trace("...EndGet");
    var task = ar as Task;
    if (task == null || task.IsFaulted)
    {
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
    }
    if (_exception != null) throw _exception;
    return _response;
}

The previous code excerpt presents the BeginGetImage and EndGetImage methods.

Regarding the Begin method:

  • The operation core processing is started on line 9, using a iterator based technique described in the following section, and is represented by a task.
  • On line 10, a continuation is added to the above task, so that the WCF callback is called when the task completes. This will trigger the call, by the WCF runtime, of the EndGetImage method.
  • On line 15, the task created on line 9 is returned. Notice that the operation’s return type is IAsyncResult. However, as stated in the beginning of this post, the Task class implements IAsyncResult interface. This is the key aspect to translate from the Task model into the APM model. The other aspect is the use of the state parameter when creating the task.

Regarding the End method:

  • On line 21, the IAsyncResult is casted to a task. Notice that, according to the APM, the IAsyncResult passed into the End method is the one returned by the Begin method.
  • Finally, the _exception and _response instance fields are consulted to produce an exception or response. These fields are assigned by the asynchronous process started on line 9 of the Begin method, as described in the following section.

Notice that the above code is rather generic. It could be used to implement other operations, just by changing line 9.

Using iterators to define asynchronous behavior

The typical way of defining asynchronous behavior with the Task<T> model is by chaining tasks with actions, producing other tasks. This breaks the code into multiple methods/anonymous methods/lambdas, reducing the readability.

In this post, we use an iterator based technique proposed by J. Richter for the APM and adapted to the Task<T> model by the ParallelExtensionExtras. The following code excerpt shows the asynchronous processing of the GetImageAndConvertItToJpeg method, implemented as a C# iterator.

 

private IEnumerable<Task> GetImageAndConvertItToJpeg(string uri)
{
    using (var client = new HttpClient
        {
            MaxResponseContentBufferSize = 1024*1024
        })
    {
        uri = Uri.UnescapeDataString(uri);
        Task<HttpResponseMessage> readTask = null;
        try
        {
            readTask = client.GetAsync(uri);
        }
        catch (Exception)
        {
            _exception = new HttpResponseException(HttpStatusCode.NotFound);
            yield break;
        }
        Trace("yielding for HTTP response...");
        yield return readTask;

        Trace("...resuming after HTTP response completed");
        if (readTask.IsFaulted || readTask.Result.StatusCode != HttpStatusCode.OK)
        {
            _exception = new HttpResponseException(HttpStatusCode.NotFound);
            yield break;
        }
        var httpContent = readTask.Result.Content;
        using (var ms = new MemoryStream())
        {
            var copyTask = httpContent.ContentReadStream.CopyStreamToStreamAsync(ms);
            Trace("yielding for stream copy...");
            yield return copyTask;

            Trace("...resuming after copy completed");
            if (copyTask.IsFaulted)
            {
                _exception = new HttpResponseException(HttpStatusCode.NotFound);
                yield break;
            }
            Bitmap bitmap = null;
            try
            {
                bitmap = new Bitmap(ms);
            }
            catch (Exception)
            {
                _exception = new HttpResponseException(HttpStatusCode.NotFound);
                yield break;
            }
            var output = new MemoryStream();
            bitmap.Save(output, ImageFormat.Jpeg);
            output.Seek(0, SeekOrigin.Begin);
            var content = new StreamContent(output);
            content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
            _response = new HttpResponseMessage
                {
                    Content = content
                };
        }
    }
}

 

This code performs the following:

  • An HttpClient is created to retrieve the upstream image. If any exception occurs while creating and starting the request, then the _exception instance field is assigned with an HttpResponseException and the iterator stops (yield break). If not, the result of the client.GetAsync(uri) statement is a Task<HttpResponseMessage>, representing the HTTP request. This task is then returned by the iterator, without blocking the hosting thread.
  • The iterator is resumed only when this Task<HttpResponseMessage> completes. Then it checks for errors, and if everything is ok, creates a task to copy the HttpResponseMessage’s stream into a memory stream. This is done to ensure that all the image’s content are in memory when the bitmap is created. If the bitmap was created directly from the  HttpResponseMessage’s stream, then the Bitmapconstructor would block the hosting thread while waiting for all the bytes (and we don’t want to block threads!).The stream copy uses the CopyStreamToStreamAsync extension method, also available on the ParallelExtensionExtras. The task returned by this method is then returned by the iterator, so that the stream copy is performed asynchronously.
  • The iterator is resumed again when the stream copy completes. After some error checking, the Bitmap is finally created and saved into another memory stream used in the response message. Notice that this can be done synchronously, since it doesn’t require any I/O.

Unfortunately, the above code is slightly cluttered by the error handling and by the fact that a yield statement cannot be inside a try-catch block.

The chaining of the tasks returned by the above iterator is done by the ParallelExtensionExtras Iterate method, that wraps the overall resulting asynchronous processing in a Task (remember line 9 of the second code excerpt).

This chaining is performed by the following:

  • When initially called, the Iterate method schedules a task, using StartNew, that will call the iterator to retrieve the first task. It also creates a TaskCompletionSource to represent the  overall task.
  • The first task retrieved from the iterator (representing the HTTP request) is then chained with another call to the iterator, using a ContinueWith.
  • The second task retrieved from the iterator (representing the stream copy) is also chained with another call to the iterator.
  • The final call to the iterator doesn’t return any element (MoveNext returns false), so Iterate signals the TaskCompletionSource that all the work is completed. This results in the call of the WCF callback.

The following diagram presents a sequence diagram, with the interaction between the different components.

async

The following color scheme is used:

  • Red – WCF runtime components;
  • Green – user code (Iterator represents the enumerable returned by the GetImageAndConvertItToJpeg method);
  • Light blue – TPL scheduler;
  • Dark blue – Iterate extension method (from the ParallelExtensionExtras)

The tracing output one of execution is (the first number is the managed thread id)

3: BeginGet…

6: yielding for HTTP response…

9: …resuming after HTTP response completed

9: yielding for stream copy…

6: …resuming after copy completed

6: Main task completed, calling callback

8: …EndGet

Conclusions and final remarks

  • Currently, WCF Web API only allows asynchronous operation implementations exposing the APM model.
  • However, it is not difficult to use a Task<T> based model with an APM interface, using the fact that Task implements IAsyncResult.
  • While the future C# 5 asynchronous support is not available, the use of iterators and the ParallelExtensionExtras’s Iterate method provides for a similar experience.
  • In this post I was not concerned with measuring the scalability improvements due to the use of asynchronous operation implementation. Namely, asynchronous processing may be disadvantageous if the blocking time is very small. My main goal here was the how and not the why of using asynchronous processing.
  • The ParallelExtensionExtras library is full of interesting utilities, of which the Iterate and the CopyStreamToStreamAsync are just examples.

Finally, feedback is greatly welcomed.