2012-08-15 12 views
21

Ich verwende derzeit mehrere Delegation Handler (Klassen von DelegatingHandler abgeleitet), um die Anfrage zu bearbeiten, bevor es gesendet wird, für Dinge wie die Validierung einer Unterschrift usw. Das ist alles sehr nett, weil ich nicht müssen bei allen Aufrufen die Signaturprüfung duplizieren (z. B.).DelegierenHandler für die Antwort in WebApi

Ich möchte das gleiche Prinzip auf die Antwort von der gleichen Web-Anfrage verwenden. Gibt es etwas Ähnliches wie den DelegatingHandler für die Antwort? Eine Möglichkeit, die Antwort zu erfassen, bevor sie in gewisser Weise zur Methode zurückgekehrt ist?

Zusätzliche Informationen: Ich rufe einen Web-api mit HttpClient.PutAsync(...)

Antwort

37

Ja. Sie können das in der Fortsetzungsaufgabe tun.

Ich erkläre es here.

Zum Beispiel verfolgt dieser Code (aus dem obigen Blog) Anfrage-URI und fügt einen Dummy-Header zur Antwort hinzu.

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, jetzt verstehe ich die Beispiele mit ContinueWith. Das funktioniert großartig. Danke (und Entschuldigung für langsame Antwort) – Halvard

+0

Wie würdest du den Antwortinhalt hier lesen? Ich versuche es zu lesen, aber es wirft eine Objekt-Ausnahme ab. –

+0

@RossJones Das ist bizarr ... kannst du eine Repro schicken? – Aliostad

13

Hier ist ein Beispiel zum Abfangen der Anfrage und der Antwort. Die überschriebene Methode SendAsync wird zum Erfassen der ursprünglichen Anforderung verwendet, während die Methode ResponseHandler zum Erfassen der Antwort verwendet wird.

Beispiel ursprünglichen Anfrage und Antwort

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

diese Methode erfassen verwenden zu können, muss die Klasse identifiziert und als Message registriert sein. Ich fügte hinzu, die folgende Zeile in meiner Datei Global.asax ...

Beispiel, wie die neue MessageInterceptor Klasse

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

Hier ist meine komplette Global.asax-Datei zu registrieren. Beachten Sie, wie die MessageInterceptor referenziert ...

Vollversion von Global.asax zeigt MessageInterceptor Integration

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()); 
     } 
    } 
} 
Verwandte Themen