ASP.NET Web API 中的 HttpClient 消息处理程序HttpClient Message Handlers in ASP.NET Web API

作者: Mike Wassonby Mike Wasson

消息处理程序是接收 http 请求并返回 http 响应的类。A message handler is a class that receives an HTTP request and returns an HTTP response.

通常,一系列消息处理程序链接在一起。Typically, a series of message handlers are chained together. 第一个处理程序接收 HTTP 请求,进行一些处理,并向下一个处理程序提供请求。The first handler receives an HTTP request, does some processing, and gives the request to the next handler. 在某个时间点,将创建响应,并在链中返回。At some point, the response is created and goes back up the chain. 此模式称为委托处理程序。This pattern is called a delegating handler.

在客户端, HttpClient类使用消息处理程序来处理请求。On the client side, the HttpClient class uses a message handler to process requests. 默认处理程序是HttpClientHandler,它通过网络发送请求并从服务器获取响应。The default handler is HttpClientHandler, which sends the request over the network and gets the response from the server. 可以将自定义消息处理程序插入客户端管道:You can insert custom message handlers into the client pipeline:

Note

ASP.NET Web API 还会在服务器端使用消息处理程序。ASP.NET Web API also uses message handlers on the server side. 有关详细信息,请参阅HTTP 消息处理程序For more information, see HTTP Message Handlers.

自定义消息处理程序Custom Message Handlers

若要编写自定义消息处理程序,请从DelegatingHandler派生并重写SendAsync方法。To write a custom message handler, derive from System.Net.Http.DelegatingHandler and override the SendAsync method. 下面是方法签名:Here is the method signature:

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

方法采用HttpRequestMessage作为输入,并以异步方式返回HttpResponseMessageThe method takes an HttpRequestMessage as input and asynchronously returns an HttpResponseMessage. 典型的实现会执行以下操作:A typical implementation does the following:

  1. 处理请求消息。Process the request message.
  2. 调用 base.SendAsync 将请求发送到内部处理程序。Call base.SendAsync to send the request to the inner handler.
  3. 内部处理程序返回响应消息。The inner handler returns a response message. (此步骤是异步的。)(This step is asynchronous.)
  4. 处理响应并将其返回给调用方。Process the response and return it to the caller.

下面的示例演示将自定义标头添加到传出请求的消息处理程序:The following example shows a message handler that adds a custom header to the outgoing request:

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 的调用是异步的。The call to base.SendAsync is asynchronous. 如果处理程序在此调用后执行任何操作,请使用await关键字在方法完成后继续执行。If the handler does any work after this call, use the await keyword to resume execution after the method completes. 下面的示例演示了记录错误代码的处理程序。The following example shows a handler that logs error codes. 日志记录本身并不是很有趣,但此示例演示如何获取处理程序内的响应。The logging itself is not very interesting, but the example shows how to get at the response inside the handler.

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

向客户端管道添加消息处理程序Adding Message Handlers to the Client Pipeline

若要将自定义处理程序添加到HttpClient,请使用HttpClientFactory方法:To add custom handlers to HttpClient, use the HttpClientFactory.Create method:

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

消息处理程序按您将其传递到Create方法的顺序进行调用。Message handlers are called in the order that you pass them into the Create method. 由于处理程序是嵌套的,因此响应消息以其他方向传输。Because handlers are nested, the response message travels in the other direction. 也就是说,最后一个处理程序是获取响应消息的第一个处理程序。That is, the last handler is the first to get the response message.