2012-08-15 44 views
21

Actualmente estoy usando varios manejadores de delegación (clases derivadas de DelegatingHandler) para trabajar en la solicitud antes de enviarla, para cosas como validar una firma, etc. Todo esto es muy bueno, porque no tiene que duplicar la validación de la firma en todas las llamadas (por ejemplo).DelegatingHandler para respuesta en WebApi

Me gustaría utilizar el mismo principio en la respuesta de la misma solicitud web. ¿Hay algo similar a DelegatingHandler para la respuesta? ¿Una forma de detectar la respuesta antes de que haya regresado al método, de alguna manera?

Información adicional: que llamo una API web utilizando HttpClient.PutAsync(...)

Respuesta

37

Sí. Puedes hacer eso en la tarea de continuación.

Lo explico here.

Por ejemplo, este código (del blog anterior) rastrea el URI de solicitud y agrega un encabezado falso a la respuesta.

public class DummyHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     // work on the request 
     Trace.WriteLine(request.RequestUri.ToString()); 

     return base.SendAsync(request, cancellationToken) 
      .ContinueWith(task => 
      { 
       // work on the response 
       var response = task.Result; 
       response.Headers.Add("X-Dummy-Header", Guid.NewGuid().ToString()); 
       return response; 
      }); 
    } 
} 
+0

Ah, ahora entiendo los ejemplos usando ContinueWith. Esto funciona genial Gracias (y perdón por la respuesta lenta) – Halvard

+0

¿Qué le parece leer aquí el contenido de la respuesta? Intento leerlo pero arroja una excepción de objeto eliminado. –

+0

@RossJones Eso es extraño ... ¿puedes enviar un repro? – Aliostad

13

Aquí hay un ejemplo para interceptar la solicitud y la respuesta. el método reemplazado SendAsync se utiliza para capturar la solicitud original, mientras que el método denominado ResponseHandler se utiliza para capturar la respuesta.

Ejemplo para capturar solicitud original y la respuesta

using System.Net.Http; 
using System.Threading.Tasks; 
namespace webAPI_Test 
{ 
    public class MessageInterceptor : DelegatingHandler 
    { 
     protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
     { 
      // CATCH THE REQUEST BEFORE SENDING TO THE ROUTING HANDLER 
      var headers = request.ToString(); 
      var body = request.Content.ReadAsStringAsync().Result; 
      var fullRequest = headers + "\n" + body; 

      // SETUP A CALLBACK FOR CATCHING THE RESPONSE - AFTER ROUTING HANDLER, AND AFTER CONTROLLER ACTIVITY 
      return base.SendAsync(request, cancellationToken).ContinueWith(
         task => 
         { 
          // GET THE COPY OF THE TASK, AND PASS TO A CUSTOM ROUTINE 
          ResponseHandler(task); 

          // RETURN THE ORIGINAL RESULT 
          var response = task.Result; 
          return response; 
         } 
      ); 
     } 

     public void ResponseHandler(Task<HttpResponseMessage> task) 
     { 
      var headers = task.Result.ToString(); 
      var body = task.Result.Content.ReadAsStringAsync().Result; 

      var fullResponse = headers + "\n" + body; 
     } 
    } 
} 

Para utilizar este método, la clase necesita ser identificados y registrados como un MessageHandler. He añadido la siguiente línea al archivo Global.asax ...

Ejemplo de cómo registrar la nueva clase MessageInterceptor

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

Aquí está mi archivo Global.asax completa. Observe cómo se hace referencia a la MessageInterceptor ...

La versión completa de Global.asax muestra la integración MessageInterceptor

using System.Web.Http; 
using System.Web.Mvc; 
using System.Web.Optimization; 
using System.Web.Routing; 
namespace webAPI_Test 
{ 
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801 

    public class WebApiApplication : System.Web.HttpApplication 
    { 
     protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 

      WebApiConfig.Register(GlobalConfiguration.Configuration); 
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 

      GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageInterceptor()); 
     } 
    } 
} 
Cuestiones relacionadas