2017-06-21 39 views
0

使用基于约定的路由时,我可以通过重写SendAsync方法来使用DelegatingHandler来创建响应包装。如何为属性路由创建响应包装?

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

但是,这种方法不适用于依赖于属性路由的方法。在我的情况下,基于约定的路由不适用于所有场景,并且routeHandler不适用于基于属性的路由。

如何将响应包装应用于所有基于属性的路由响应?

+1

基于约定的路由不适用于所有情况?属性路由是基于约定的路由功能的一个子集,这怎么可能? – NightOwl888

+1

在你的情况,routeHandler只是控制器动作包装。你为什么不使用ActionFilter,但它更简单,并且适用于任何路由机制。 –

+0

@ NightOwl888 UsersController GET操作 API /用户 API /用户/ {用户id} API /用户/ {用户id} /入学 API /用户/ {用户id} /入学/ {enrollmentId} 也许我只是无知...有没有办法实现上述使用基于约定的路由?我不介意创建多个约定,但如果需要为每个控制器构建一个基于约定的路由,那么似乎属性路由将是首选。 – Zoop

回答

0

我能够添加适用于所有请求的全局消息处理程序。

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

由于我使用了招摇,我也不得不忽略了招摇的请求URI。这是ResponseWrapper类的代码,以帮助某人。我没有机会通过它,所以肯定会有一些改进...

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