Нет заголовка ответа в DelegatingHandler
Я пытаюсь зарегистрировать HTTP-заголовки ответа моего проекта Web 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?
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
}
}
Должен быть в состоянии получить доступ к необходимым деталям из ответа до его возвращения.
Попробуйте приведенный ниже код.
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;
}
);
Вы должны посмотреть в нужном месте:
request.Content.Headers.ContentType
Предполагая, что есть Content-Type: application/json
заголовок запроса, тогда вышеупомянутый вернет "application/json"
,
Так что в основном некоторые заголовки связаны с контентом, и именно здесь вы должны их читать.
То же самое верно для заголовков ответа. В зависимости от их типа вам может потребоваться извлечь их из содержимого ответа (для запросов, возвращающих тело)
response.Content.Headers.ContentType