DelegatingHandler - Send Vs SendAsync

Topics: Web Api
Sep 20, 2011 at 1:53 PM

We have a DelegatingHandler which is being wired up like this:
public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For<ProductImageResource>()
               .ImplementedBy<ProductImageResource>());

            var webApiConfig = new WebApiConfiguration()
            {
                MessageHandlerFactory = () => getMessageHandlers(container),
                CreateInstance = (serviceType, context, request) => container.Resolve(serviceType)
            };

            RouteTable.Routes.MapServiceRoute<ProductImageResource>("product", webApiConfig);
         }

private static IEnumerable<DelegatingHandler> getMessageHandlers(IWindsorContainer container)
        {
            yield return container.Resolve<EntityTagResponseHandler<ProductImage>>();
        }

And we are wondering why the "Send" method override (below) is never called:

protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
       {
           if (request.Method == HttpMethod.Get && request.Headers.IfNoneMatch.Any())
           {
               var entityTagHeaderValue = request.Headers.IfNoneMatch.FirstOrDefault();
               if (entityTagHeaderValue != null)
               {
                   var productImageId = new Guid(entityTagHeaderValue.ToString().Replace("\"", String.Empty));
                   return _repository.Any(x => x.Id == productImageId)
                              ? createANotModifiedResponse()
                              : base.Send(request, cancellationToken);
               }
           }
           return base.Send(request, cancellationToken);
       }

Instead, we have to override the "SendAsync" method shown below:

       protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            if (request.Method == HttpMethod.Get && request.Headers.IfNoneMatch.Any())
            {

                var entityTagHeaderValue = request.Headers.IfNoneMatch.FirstOrDefault();
                if (entityTagHeaderValue != null)
                {
                    var productImageId = new Guid(entityTagHeaderValue.ToString().Replace("\"", string.Empty));
                    return _repository.Any(x => x.Id == productImageId)
                        ? Task.Factory.StartNew(() => createANotModifiedResponse(), cancellationToken)
                        : base.SendAsync(request, cancellationToken);
                }
            }

            return base.SendAsync(request, cancellationToken);
        }

 

Could anyone please explain why the async method is successfully called but the non-async method is not called? Is there some setting which we can manipulate to change this so that our handlers execute synchronously? Otherwise, why does the abstract "Send" method even exist in the base class?

Coordinator
Sep 20, 2011 at 8:51 PM

Synchronous message handlers are not supported on the server to avoid blocking threads. We are looking at removing the synchronous Send method completely to avoid further confusion.

Daniel Roth

From: Pollo [email removed]
Sent: Tuesday, September 20, 2011 6:53 AM
To: Daniel Roth
Subject: DelegatingHandler - Send Vs SendAsync [wcf:273193]

From: Pollo

We have a DelegatingHandler which is being wired up like this:
public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For<ProductImageResource>()
               .ImplementedBy<ProductImageResource>());
 
            var webApiConfig = new WebApiConfiguration()
            {
                MessageHandlerFactory = () => getMessageHandlers(container),
                CreateInstance = (serviceType, context, request) => container.Resolve(serviceType)
            };
 
            RouteTable.Routes.MapServiceRoute<ProductImageResource>("product", webApiConfig);
         }
 
private static IEnumerable<DelegatingHandler> getMessageHandlers(IWindsorContainer container)
        {
            yield return container.Resolve<EntityTagResponseHandler<ProductImage>>();
        }
 
 
 
And we are wondering why the "Send" method override (below) is never called:
 
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
       {
           if (request.Method == HttpMethod.Get && request.Headers.IfNoneMatch.Any())
           {
               var entityTagHeaderValue = request.Headers.IfNoneMatch.FirstOrDefault();
               if (entityTagHeaderValue != null)
               {
                   var productImageId = new Guid(entityTagHeaderValue.ToString().Replace("\"", String.Empty));
                   return _repository.Any(x => x.Id == productImageId)
                              ? createANotModifiedResponse()
                              : base.Send(request, cancellationToken);
               }
           }
           return base.Send(request, cancellationToken);
       }
 
 
 
Instead, we have to override the "SendAsync" method shown below:
 
       protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            if (request.Method == HttpMethod.Get && request.Headers.IfNoneMatch.Any())
            {
 
                var entityTagHeaderValue = request.Headers.IfNoneMatch.FirstOrDefault();
                if (entityTagHeaderValue != null)
                {
                    var productImageId = new Guid(entityTagHeaderValue.ToString().Replace("\"", string.Empty));
                    return _repository.Any(x => x.Id == productImageId)
                        ? Task.Factory.StartNew(() => createANotModifiedResponse(), cancellationToken)
                        : base.SendAsync(request, cancellationToken);
                }
            }
 
            return base.SendAsync(request, cancellationToken);
        }

Could anyone please explain why the async method is successfully called but the non-async method is not called? Is there some setting which we can manipulate to change this so that our handlers execute synchronously? Otherwise, why does the abstract "Send" method even exist in the base class?