DelegatingHandler - changed behaviour with preview 5

Topics: Web Api
Sep 16, 2011 at 8:04 PM

Help!

we've upgraded our preview 4 DelegatingChannel to a preview 5 DelegatingHandler.
I am using the default constructor to instantiate the DelegatingChannel.

With our previous implmentation we could:


protected override Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,  CancellationToken cancellationToken)
{
  // do some processing on the message
 // ...

        var result = base.SendAsync(request, cancellationToken);

 // now do some post processing on the message before exiting.
 // ...
 // with Preview5 result.Result is now null. The actual service contract is not called until after this function exists.
// I need to however be able to manipulate the request and the response from within the SAME MessageHandler.

 // exit out
 return result;
}

This is how the message handler is registered:

            //////////////////////////////////////////////////////////////////////////
            // api
            webApiConfig = new WebApiConfiguration()
            {
                EnableTestClient = false,
                MessageHandlerFactory = () => new DelegatingHandler[] { IocFactory.GetInstance<AuthenticationMessageHandler>()},
                CreateInstance = (serviceType, context, request) => IocFactory.GetInstance(serviceType)
            };
            webApiConfig.UseJsonNet();

 Thank you!

Sep 16, 2011 at 10:02 PM

You have to use the concept of a continuation task to make this work reliably. In .Net 4 this means you use the ContinueWith pattern and return the task provided by the continuation. For example:

public class SampleMessageHandler : DelegatingHandler

{

private static int offset;

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

{

/// Here you can inspect/ modify request and either push it up

/// the chain or short-circuit by sending back a response directly.

/// In this case we send it up the chain using ContinueWith.

/// This returns a task which is run *after* the base.SendAsync(…) has completed.

return base.SendAsync(request, cancellationToken).ContinueWith(

(task) =>

{

/// Here you can inspect/modify the response coming from the service

var headerValue = Interlocked.Increment(ref offset);

HttpResponseMessage response = task.Result;

response.Headers.Add("SampleHeader", headerValue.ToString());

return response;

});

}

}

Hope this helps,

Henrik

From: santiagoIT [email removed]
Sent: Friday, September 16, 2011 1:05 PM
To: Henrik Frystyk Nielsen
Subject: DelegatingHandler - changed behaviour with preview 5 [wcf:272880]

From: santiagoIT

Help!

we've upgraded our preview 4 DelegatingChannel to a preview 5 DelegatingHandler.
I am using the default constructor to instantiate the DelegatingChannel.

With our previous implmentation we could:


protected override Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// do some processing on the message
// ...

var result = base.SendAsync(request, cancellationToken);

// now do some post processing on the message before exiting.
// ...
// with Preview5 result.Result is now null. The actual service contract is not called until after this function exists.
// I need to however be able to manipulate the request and the response from within the SAME MessageHandler.

// exit out
return result;
}

This is how the message handler is registered:

            //////////////////////////////////////////////////////////////////////////
            // api
            webApiConfig = new WebApiConfiguration()
            {
                EnableTestClient = false,
                MessageHandlerFactory = () => new DelegatingHandler[] { IocFactory.GetInstance<AuthenticationMessageHandler>()},
                CreateInstance = (serviceType, context, request) => IocFactory.GetInstance(serviceType)
            };
            webApiConfig.UseJsonNet();
 

Thank you!

Sep 17, 2011 at 9:49 AM

Henrik!
thanks we got it working using ContinueWith as you suggested!