2013-10-23 121 views
8

在WebApiConfig.cs我有以下获取控制器名称

public static void Register(HttpConfiguration config) 
{ 

    config.MapHttpAttributeRoutes(); 

    config.Services.Replace(typeof(IHttpControllerSelector), 
       new MyApiControllerSelector(config)); 

    //code omitted for brevity 
} 

然后在MyApiControllerSelector.cs我想控制器

public override HttpControllerDescriptor SelectController(HttpRequestMessage request) 
     {   
      var routeData = request.GetRouteData();   

      var controllerName = (string)routeData.Values["controller"]; 

      //code omitted for brevity 
     } 

非常简单,它的工作很好,但现在使用属性路由我认为它需要一个不同的方法? - 因为我似乎无法找到一个简单的方法

我已经试过

var controllerName = request.GetActionDescriptor().ControllerDescriptor.ControllerName; 

不工作。

然后读取source调试导致我request.GetRouteData().Values["MS_SubRoutes"]

所以现在我有

string subRoutesKey = "MS_SubRoutes"; 

var attributedRoutesData = routeData.Values[subRoutesKey] as IEnumerable<IHttpRouteData>; 
var subRouteData = attributedRoutesData.FirstOrDefault(); 

var actions = (ReflectedHttpActionDescriptor[])subRouteData.Route.DataTokens["actions"]; 
var controllerName = actions[0].ControllerDescriptor.ControllerName; 

其作品,但它必须是一个简单的方法?

UPDATE

@KiranChalla问什么是我的使用情况,以便我张贴的其余代码。 基本上我解析版本媒体类型Accept: application/vnd.app.{resource}.v{version}+json从请求和返回HttpControllerDescriptor取决于版本。

  HttpControllerDescriptor oldControllerDescriptor; 
      if (controllers.TryGetValue(controllerName, out oldControllerDescriptor)) 
      { 
       var apiVersion = GetVersionFromMediaType(request); 

       var newControllerName = String.Concat(controllerName, "V", apiVersion); 

       HttpControllerDescriptor newControllerDescriptor; 
       if (controllers.TryGetValue(newControllerName, out newControllerDescriptor)) 
       {      
        return newControllerDescriptor; 
       }    
       return oldControllerDescriptor; 
      } 
      return null; 
+2

我相信没有其他的,我简单的方法意识到。只是fyi ...一个小小的改进,你可以通过request.GetRouteData()。GetSubRoutes()来获取列表属性路由... –

+0

顺便说一下,你能描述一下你的场景是什么吗?我很想知道你打算如何使用自定义控制器选择器和属性路由。 –

+0

@KiranChalla感谢您的建议。我已经解释了我的情况并添加了剩余的代码,所以如果我做错了任何事,请看看并纠正我。 –

回答

11

证实由@KiranChalla有没有更简单的方法再一个我已经实现,除了轻微的建议,使用GetSubRoutes()

var attributedRoutesData = request.GetRouteData().GetSubRoutes(); 
var subRouteData = attributedRoutesData.FirstOrDefault(); 

var actions = (ReflectedHttpActionDescriptor[])subRouteData.Route.DataTokens["actions"]; 
var controllerName = actions[0].ControllerDescriptor.ControllerName; 
+0

该解决方案是否存在更大的性能问题? – ainteger

+1

@ainteger不,它只是一种从管道获取必要数据(控制器名称)的不同方法。 –

+0

使用'GetSubRoutes()'的建议是一个很好的建议。这是我采取的方法,因为使用'MS_SubRoutes'是依赖于未公开的字符串文字,将来可以轻松更改而不会有任何警告。 – BitMask777