Cómo implementar un DelegatingHandler para X-HTTP-Method-Override en Web API

Al implementar su API web REST en un dominio público, a veces encontrará problemas relacionados con la compatibilidad con verbos HTTP. Los dos desafíos a este respecto son el soporte limitado para verbos HTTP en navegadores web antiguos (es decir, solo admiten HTTP GET y HTTP POST) y cortafuegos agresivos que bloquean el tráfico que no es HTTP GET o HTTP POST. ¿Cómo admitirá su aplicación un PUT o DELETE en estos casos? Aquí es exactamente donde el encabezado HTTP X-HTTP-Method-Override viene al rescate.

El encabezado HTTP X-HTTP-Method-Override funciona de manera similar a un truco. Puede agregar el encabezado con un valor de PUT o DELETE al invocar su API web a través de JavaScript o mediante un XMLHttpRequestobjeto desde un navegador web mediante una llamada HTTP POST. Luego, puede hacer que un controlador delegante intercepte el método HTTP que se invocará y tomará las acciones adecuadas.

En este artículo, discutiré cómo podemos usar un controlador de delegación frente a la canalización de solicitud-respuesta para modificar la solicitud para enviar un mensaje válido a nuestra aplicación, o alterar la respuesta para enviar una respuesta válida al cliente.

Verbos HTTP y controladores de delegación

Si nos vemos obligados a usar solo los verbos HTTP GET y POST debido a las limitaciones impuestas por su cliente, el navegador web o el firewall al frente de su aplicación web, tendremos que implementar una solución alternativa para admitir PUT y DELETE. Esta solución temporal generalmente implica agregar el encabezado HTTP X-HTTP-Method-Override a la solicitud que especifica el verbo que queremos usar dentro de la llamada HTTP POST. Además, necesitamos un controlador de delegación en nuestra aplicación que verifique el encabezado y, si existe, realice la llamada al método HTTP que desea invocar.

Antes de sumergirnos en la implementación, echemos un vistazo rápido a qué son los controladores delegados y por qué usaríamos uno aquí. Un controlador de delegación y otros controladores de mensajes se ejecutan al principio de la canalización de procesamiento de solicitudes. Estas son clases que aceptan solicitudes HTTP y devuelven una respuesta HTTP. La delegación de controladores es similar a HttpModulesASP.Net. Pero HttpModules, a diferencia de los manejadores delegados, se pueden encadenar: un manejador delegador puede hacer referencia a otro manejador delegante. Puede obtener más información sobre la delegación de controladores en mi artículo anterior, "Cómo trabajar con controladores de mensajes en la API web".

Crea un controlador de API web

Suponga que tiene un controlador de API web similar a este:

AuthorsController de clase pública: ApiController

    {

        // OBTENER: api / autores

        public IEnumerable Get ()

        {

            devolver nueva cadena [] {"Joydip", "Kanjilal"};

        }

        // OBTENER: api / author / 1

        cadena pública Get (int id)

        {

            devuelve "Joydip Kanjilal";

        }

        // POST api / autor

        Publicación vacía pública ([FromBody] Valor del autor) {}

        // PUT api / author / 1

        public void Put (int id, [FromBody] Author value) {}

        // ELIMINAR api / author / 1

        public void Delete (int id) {}

    }

Crear un DelegatingHandler para X-HTTP-Method-Override

Ahora implementemos un controlador X-HTTP-Method-Override. Este es un controlador de mensajes, por lo que, como de costumbre, debería extender la DelegatingHandlerclase.

clase pública CustomMessageHandler: DelegatingHandler

    {

        cadena de solo lectura [] httpMethodsList = {“BORRAR”, “CABEZAL”, “PONER”};

        const string httpMethodOverrideheader;

        Tarea de anulación protegida SendAsync (solicitud HttpRequestMessage, CancellationToken cancellationToken)

        {

            if (request.Method == HttpMethod.Post && request.Headers.Contains (httpMethodOverrideheader))

            {               

                var httpMethod = request.Headers.GetValues ​​(httpMethodOverrideheader) .FirstOrDefault ();

                si (httpMethodsList.Contains (httpMethod, StringComparer.InvariantCultureIgnoreCase))

                {                  

                    request.Method = new HttpMethod (httpMethod);

                }

            }

            return base.SendAsync (solicitud, cancelaciónToken);

        }

    }

El código es bastante autoexplicativo. Comprueba si un HTTP POST tiene el encabezado X-HTTP-Method-Override. Si el encabezado está en la lista de métodos, se cambia el método de solicitud.

Registre el DelegatingHandler

El siguiente paso es registrar el controlador. Puede hacer esto agregando este nuevo controlador a la colección MessageHandlers en la clase WebApiConfig como se muestra en el fragmento de código a continuación.

Registro vacío estático público (configuración de HttpConfiguration)

{

    config.MessageHandlers.Add (nuevo CustomMessageHandler ());

     // Rutas de API web

    config.MapHttpAttributeRoutes ();

     config.Routes.MapHttpRoute (

        nombre: "DefaultApi",

        routeTemplate: "api / {controller} / {id}",

        valores predeterminados: nuevo {id = RouteParameter.Optional}

    );

}

Alternativamente, puede registrar el controlador de delegación utilizando el Application_Startcontrolador de eventos en el archivo Global.asax.cs como se muestra a continuación.

Application_Start vacío protegido (remitente del objeto, EventArgs e)

        {

            RegisterRoutes (RouteTable.Routes);

            GlobalConfiguration.Configuration.MessageHandlers.Add (new CustomMessageHandler ());

        }

Eso es todo lo que tiene que hacer en el lado del servidor. En el lado del cliente, es decir, desde el navegador web, debe asegurarse de agregar el encabezado de anulación como se muestra en el fragmento de código a continuación.

$ .ajax ({

  url: "// localhost: 9820 / api / Authors / 1",

  tipo: "POST",

  datos: JSON.stringify (authorData),

  encabezados: {

      "Tipo de contenido": "aplicación / json",

      "X-HTTP-Method-Override": "PUT"},

})

Como puede ver en el fragmento de código anterior, todo lo que necesita hacer es especificar el método HTTP que desea invocar en el encabezado de la solicitud, X-HTTP-Method-Override : DELETEo bien X-HTTP-Method-Override : PUT, y luego realizar una llamada POST a su recurso.