Monthly Archives: August 2011

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.