Поделиться через


Обработчики сообщений HttpClient в веб-API ASP.NET

Обработчик сообщений — это класс, который получает HTTP-запрос и возвращает HTTP-ответ.

Как правило, ряд обработчиков сообщений объединяются в цепочку. Первый обработчик получает HTTP-запрос, выполняет некоторую обработку и передает запрос следующему обработчику. В какой-то момент создается ответ и возвращается вверх по цепочке. Этот шаблон называется делегированным обработчиком.

Схема связанных обработчиков сообщений, иллюстрирующая процесс получения запроса H T T P и возврата ответа H T T P.

На стороне клиента класс HttpClient использует обработчик сообщений для обработки запросов. Обработчик по умолчанию — HttpClientHandler, который отправляет запрос по сети и получает ответ от сервера. Вы можете вставить пользовательские обработчики сообщений в клиентский конвейер:

Схема процесса вставки пользовательских обработчиков сообщений в клиентский конвейер. Показывает класс клиента h t t p, который использует обработчик сообщений для обработки запросов.

Примечание

веб-API ASP.NET также использует обработчики сообщений на стороне сервера. Дополнительные сведения см. в разделе Обработчики сообщений HTTP.

Пользовательские обработчики сообщений

Чтобы написать пользовательский обработчик сообщений, наследуйте от System.Net.Http.DelegatingHandler и переопределите метод SendAsync . Вот так выглядит подпись метода.

Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken);

Метод принимает HttpRequestMessage в качестве входных данных и асинхронно возвращает httpResponseMessage. Типичная реализация выполняет следующие действия:

  1. Обработайте сообщение запроса.
  2. Вызовите base.SendAsync , чтобы отправить запрос внутреннему обработчику.
  3. Внутренний обработчик возвращает ответное сообщение. (Этот шаг является асинхронным.)
  4. Обработайте ответ и верните его вызывающему объекту.

В следующем примере показан обработчик сообщений, который добавляет настраиваемый заголовок в исходящий запрос:

class MessageHandler1 : DelegatingHandler
{
    private int _count = 0;

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        System.Threading.Interlocked.Increment(ref _count);
        request.Headers.Add("X-Custom-Header", _count.ToString());
        return base.SendAsync(request, cancellationToken);
    }
}

Вызов к base.SendAsync выполняется асинхронно. Если обработчик выполняет какую-либо работу после этого вызова, используйте ключевое слово await, чтобы возобновить выполнение после завершения метода. В следующем примере показан обработчик, который регистрирует коды ошибок. Само ведение журнала не очень интересно, но в примере показано, как получить ответ внутри обработчика.

class LoggingHandler : DelegatingHandler
{
    StreamWriter _writer;

    public LoggingHandler(Stream stream)
    {
        _writer = new StreamWriter(stream);
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        if (!response.IsSuccessStatusCode)
        {
            _writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri, 
                (int)response.StatusCode, response.Headers.Date);
        }
        return response;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _writer.Dispose();
        }
        base.Dispose(disposing);
    }
}

Добавление обработчиков сообщений в клиентский конвейер

Чтобы добавить пользовательские обработчики в HttpClient, используйте метод HttpClientFactory.Create :

HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());

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