Нет заголовка ответа в DelegatingHandler

Я пытаюсь зарегистрировать заголовки ответов 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 в проекте веб-API?


person Zhao Xiang    schedule 22.08.2013    source источник
comment
Та же проблема здесь. У тебя есть решение?   -  person erwineberhard    schedule 19.06.2015
comment
Нет, так и не узнал   -  person Zhao Xiang    schedule 23.06.2015
comment
Я решил проблему, отправив заголовки ответа клиенту вместо изменения сообщения ответа в обработчике делегирования. В моем фреймворке javascript тоже намного проще!   -  person erwineberhard    schedule 23.06.2015


Ответы (3)


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

person Nkosi    schedule 24.02.2017

Попробуйте приведенный ниже код.

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;
                        }
            );
person Kalyan    schedule 23.02.2017
comment
Это похоже на второй пример здесь: docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/ - person Josh; 18.01.2019

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

request.Content.Headers.ContentType

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

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

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

response.Content.Headers.ContentType
person Darin Dimitrov    schedule 21.02.2017
comment
Разве это не получит заголовок request? Мне нужно регистрировать все заголовки ответов, а не только ContentType, но и response.Headers пуст. - person Giorgi; 21.02.2017
comment
То же самое: response.Content.Headers - person Darin Dimitrov; 21.02.2017
comment
response.Content.Headers содержит только ContentType. Добавляются ли другие заголовки (длина содержимого, кеш и т. д.) iis express, и поэтому их невозможно получить? - person Giorgi; 21.02.2017