2017-06-21 2 views
0

Lors de l'utilisation du routage basé sur les conventions, je peux utiliser DelegatingHandler pour créer un encapsuleur de réponse en remplaçant la méthode SendAsync.Comment créer un wrapper de réponse pour le routage d'attributs?

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

Toutefois, cette méthode ne fonctionne pas pour les méthodes qui dépendent du routage d'attributs. Dans mon cas, le routage basé sur les conventions ne fonctionnera pas pour tous les scénarios et routeHandler ne s'applique pas aux routes basées sur les attributs. Comment puis-je appliquer un wrapper de réponse à toutes les réponses de route basées sur des attributs?

+1

Le routage basé sur les conventions ne fonctionnera pas pour tous les scénarios? Comment cela est-il possible que le routage d'attribut soit un sous-ensemble de la fonctionnalité de routage basée sur les conventions? – NightOwl888

+1

Dans votre cas, routeHandler n'est que l'encapsuleur d'action du contrôleur. Pourquoi n'utilisez-vous pas ActionFilter qui fait la même chose, mais beaucoup plus simple et fonctionne avec n'importe quel mécanisme de route. –

+0

@ NightOwl888 UsersController GET opérations api/utilisateurs api/users/{userId} api/users/{userId}/inscriptions api/users/{userId}/inscriptions/{enrollmentId} Peut-être que je suis juste être ignorant ... est-il un moyen d'atteindre le routage basé sur les conventions ci-dessus? Cela ne me dérange pas de créer plusieurs conventions, mais s'il devait y avoir une route conventionnelle pour chaque contrôleur, il semblerait que le routage d'attribut soit préféré. – Zoop

Répondre

0

J'ai été en mesure d'ajouter un gestionnaire de message global qui s'applique à toutes les demandes. Depuis que j'utilise swagger, j'ai également dû ignorer l'URI demande de swagger. Voici le code de la classe ResponseWrapper dans l'éventualité où cela aiderait quelqu'un. Je n'ai pas eu la chance d'y revenir, donc il y aura certainement des améliorations ...

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