2017-06-21 1 views
0

Bei Verwendung von Convention-based Routing kann ich einen DelegatingHandler verwenden, um einen Antwortwrapper durch Überschreiben der SendAsync-Methode zu erstellen.Wie erstellt man einen Antwort-Wrapper für das Attribut-Routing?

 DelegatingHandler[] handler = new DelegatingHandler[] { 
      new ResponseWrapper() 
     }; 
     var routeHandler = HttpClientFactory.CreatePipeline(new HttpControllerDispatcher(config), handler); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}", 
      defaults: null, 
      constraints: null, 
      handler: routeHandler 
     ); 

Dieser Ansatz funktioniert jedoch nicht für Methoden, die auf Attribut-Routing angewiesen sind. In meinem Fall funktioniert Convention-basiertes Routing nicht für alle Szenarien und der routeHandler gilt nicht für die attributbasierten Routen.

Wie kann ich einen Antwortwrapper auf alle attributbasierten Routenantworten anwenden?

+1

Convention-based Routing wird nicht für alle Szenarien funktionieren? Wie ist das möglich, dass das Attribut-Routing eine Untermenge der konventionsbasierten Routing-Funktionalität ist? – NightOwl888

+1

In Ihrem Fall ist routeHandler nur Controller-Aktionswrapper. Warum verwenden Sie nicht ActionFilter, der dasselbe tut, aber viel einfacher ist und mit jedem Routenmechanismus funktioniert. –

+0

@ NightOwl888 Userscontroller GET-Operationen api/Benutzer api/users/{userId} api/users/{userId}/Einschreibungen api/users/{userId}/Einschreibungen/{enrollmentId} Vielleicht bin ich nur unwissend ... gibt es eine Möglichkeit, das oben genannte mithilfe von Convention-based Routing zu erreichen? Es macht mir nichts aus, mehrere Konventionen zu erstellen, aber wenn es für jeden Controller eine Convention-basierte Route geben müsste, scheint das Attribut-Routing vorzuziehen. – Zoop

Antwort

0

Ich konnte einen globalen Nachrichtenhandler hinzufügen, der für alle Anfragen gilt.

config.MessageHandlers.Add(new ResponseWrapper()); 

Da ich Swagger benutze, musste ich auch die Swagger Request URI ignorieren. Hier ist der Code für die ResponseWrapper-Klasse in dem Fall, dass es jemandem hilft. Ich hatte keine Chance, es wieder durchzugehen, also gibt es sicher einige Verbesserungen ...

public class ResponseWrapper : DelegatingHandler 
    { 
     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
      var response = await base.SendAsync(request, cancellationToken); 

      if (request.RequestUri.ToString().Contains("swagger")) 
      { 
       return response; 
      } 

      return BuildApiResponse(request, response); 
     } 

     private static HttpResponseMessage BuildApiResponse(HttpRequestMessage request, HttpResponseMessage response) 
     { 
      object content = null; 
      string errorMessage = null; 
      response.TryGetContentValue(out content); 

      if (!response.IsSuccessStatusCode) 
      { 
       content = null; 
       var error = new HttpError(response.Content.ReadAsStringAsync().Result);    
       var data = (JObject)JsonConvert.DeserializeObject(error.Message); 
       errorMessage = data["message"].Value<string>(); 

       if (!string.IsNullOrEmpty(error.ExceptionMessage) && string.IsNullOrEmpty(errorMessage)) 
       { 
        errorMessage = error.ExceptionMessage; 
       } 
      } 

      var newResponse = request.CreateResponse(response.StatusCode, new ApiResponse(response.StatusCode, content, errorMessage)); 

      foreach (var header in response.Headers) 
      { 
       newResponse.Headers.Add(header.Key, header.Value); 
      } 

      return newResponse; 
     } 
    } 
Verwandte Themen