Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Response Header in DelegatingHandler

I'm trying to log the HTTP Response Headers of my Web API project.

The project is developed by VS2012, .NET 4.5 and ASP.NET MVC 4.

I've wrote a DelegatingHandler subclass like this:

public class LoggingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {

        // Execute the request
        return base.SendAsync(request, cancellationToken).ContinueWith(task =>
        {
            var response = task.Result;
            return response;
        });
    }
}

However, the problem is, I can't get the header values from the response. response.Headers is an empty collection, response.Content.Headers contains nothing but a key named Content-Type, and HttpContext.Current is null.

I've seen the code of WebAPIContrib which use the same logic to log the headers, but their code does not seem to work either.

So how should I trace the HTTP Response Headers in Web API project?

like image 673
Zhao Xiang Avatar asked Aug 22 '13 07:08

Zhao Xiang


2 Answers

Message handlers are called in the same order that they appear in MessageHandlers collection. Because they are nested, the response message travels in the other direction. That is, the last handler is the first to get the response message.

Make sure that the logging handler is registered early in the pipeline. Preferably first.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        config.MessageHandlers.Add(new LoggingHandler(...));

        //...add other handlers
        config.MessageHandlers.Add(new MessageHandler1());
        config.MessageHandlers.Add(new MessageHandler2());

        // Other code not shown...
    }
}

That way any other handlers would have their chance to populate the response and have that info logged.

You can also simplify the class using async/await syntax to make accessing the response cleaner.

public class LoggingHandler : DelegatingHandler {
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {

        //...Extract and log request
        LogRequest(request);

        // Send the request on to the inner handler(s) and get the response
        var response = await base.SendAsync(request, cancellationToken);

        //...Extract details from response for logging
        LogResponse(response);

        return response;
    }

    private void LogRequest(HttpRequestMessage request) {
        //... code removed for brevity
    }

    private void LogResponse(HttpResponseMessage response) {
        //... code removed for brevity
    }
}

Should be able to access the necessary details from the response before returning it.

Reference : HTTP Message Handlers in ASP.NET Web API

like image 52
Nkosi Avatar answered Nov 16 '22 09:11

Nkosi


Try out the below code.

return base.SendAsync(request, cancellationToken).ContinueWith(
                        task =>
                        {

                            var headers = task.Result.ToString();
                            var body = task.Result.Content.ReadAsStringAsync().Result;

                            // RETURN THE ORIGINAL RESULT
                            var response = task.Result;
                            return response;
                        }
            );
like image 26
Kalyan Avatar answered Nov 16 '22 10:11

Kalyan