17

我正在尝试记录我的 Web API 项目的 HTTP 响应标头。

该项目由 VS2012、.NET 4.5 和 ASP.NET MVC 4 开发。

我写了一个这样的DelegatingHandler子类:

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;
        });
    }
}

但是,问题是,我无法从response. response.Headers是一个空集合,response.Content.Headers只包含一个名为 的键Content-Type,并且HttpContext.Currentnull

我看过WebAPIContrib的代码,它使用相同的逻辑来记录标题,但它们的代码似乎也不起作用。

那么我应该如何跟踪 Web API 项目中的 HTTP 响应标头呢?

4

3 回答 3

4

消息处理程序的调用顺序与它们在 MessageHandlers集合中出现的顺序相同。因为它们是嵌套的,所以响应消息会朝另一个方向传播。也就是说,最后一个处理程序是第一个获得响应消息的。

确保日志处理程序在管道的早期注册。最好是先。

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...
    }
}

这样,任何其他处理程序都将有机会填充响应并记录该信息。

您还可以使用 async/await 语法简化类,以使访问响应更清晰。

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
    }
}

应该能够在返回之前从响应中访问必要的详细信息。

参考:ASP.NET Web API 中的 HTTP 消息处理程序

于 2017-02-24T16:03:06.577 回答
2

试试下面的代码。

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;
                        }
            );
于 2017-02-23T23:19:58.217 回答
0

你必须看看正确的地方:

request.Content.Headers.ContentType

假设有一个Content-Type: application/json请求头,那么前面提到的将返回"application/json".

所以基本上一些标题与内容相关联,这就是你应该从中读取它们的地方。

响应标头也是如此。根据它们的类型,您可能需要从响应内容中提取它们(对于返回正文的请求)

response.Content.Headers.ContentType
于 2017-02-21T08:56:53.283 回答