Controladores de mensajes HttpClient en ASP.NET Web API

por Mike Wasson

Un controlador de mensajes es una clase que recibe una solicitud HTTP y devuelve una respuesta http.

Normalmente, una serie de controladores de mensajes se encadenan entre sí. El primer controlador recibe una solicitud HTTP, realiza algún procesamiento y proporciona la solicitud al siguiente controlador. En algún momento, se crea la respuesta y se realiza una copia de seguridad de la cadena. Este patrón se denomina controlador de delegación .

En el lado del cliente, la clase HttpClient usa un controlador de mensajes para procesar solicitudes. El controlador predeterminado es HttpClientHandler, que envía la solicitud a través de la red y obtiene la respuesta del servidor. Puede insertar controladores de mensajes personalizados en la canalización de cliente:

Note

ASP.NET Web API también utiliza controladores de mensajes en el lado servidor. Para obtener más información, consulte controladores de mensajes http.

Controladores de mensajes personalizados

Para escribir un controlador de mensajes personalizado, derive de System .net. http. DelegatingHandler e invalide el método SendAsync . Esta es la firma del método:

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

El método toma un HttpRequestMessage como entrada y devuelve de forma asincrónica un HttpResponseMessage. Una implementación típica hace lo siguiente:

  1. Procesar el mensaje de solicitud.
  2. Llame a base.SendAsync para enviar la solicitud al controlador interno.
  3. El controlador interno devuelve un mensaje de respuesta. (Este paso es asincrónico).
  4. Procesa la respuesta y la devuelve al autor de la llamada.

En el ejemplo siguiente se muestra un controlador de mensajes que agrega un encabezado personalizado a la solicitud saliente:

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

La llamada a base.SendAsync es asincrónica. Si el controlador realiza cualquier trabajo después de esta llamada, use la palabra clave Await para reanudar la ejecución después de que se complete el método. En el ejemplo siguiente se muestra un controlador que registra códigos de error. El registro en sí no es muy interesante, pero en el ejemplo se muestra cómo obtener la respuesta dentro del controlador.

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

Agregar controladores de mensajes a la canalización de cliente

Para agregar controladores personalizados a HttpClient, use el método HttpClientFactory. Create :

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

Se llama a los controladores de mensajes en el orden en que se pasan al método Create . Dado que los controladores están anidados, el mensaje de respuesta se desplaza en la otra dirección. Es decir, el último controlador es el primero en obtener el mensaje de respuesta.