Нет заголовка ответа в деле делегирования

Я пытаюсь зарегистрировать заголовки ответов HTTP в проекте моего веб-API.

Проект разработан 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.Current - null.

Я видел код WebAPIContrib, который использует ту же логику для записи заголовков, но их код, похоже, не работает либо.

Итак, как мне отслеживать заголовки HTTP-ответов в проекте Web API?

Ответы

Ответ 1

Обработчики сообщений вызываются в том же порядке, в котором они отображаются в 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
    }
}

Должен иметь доступ к необходимым данным из ответа перед его возвратом.

Ссылка: Обработчики HTTP-сообщений в веб-интерфейсе ASP.NET

Ответ 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;
                        }
            );

Ответ 3

Вы должны посмотреть в нужное место:

request.Content.Headers.ContentType

Предполагая, что заголовок запроса Content-Type: application/json, тогда вышесказанное вернет "application/json".

Таким образом, в основном некоторые заголовки связаны с Контентом и что вы должны их читать.

То же самое верно для заголовков ответов. В зависимости от их типа вам может потребоваться извлечь их из содержимого ответа (для запросов, возвращающих тело)

response.Content.Headers.ContentType