获取控制器名称。

11
在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;

它不起作用。

然后我通过调试阅读源代码,找到了 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;

这个方法可以工作,但是有没有更简单的方式呢?

更新

@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
我相信目前我所知道的没有其他更简单的方法。顺便说一下,你可以使用request.GetRouteData().GetSubRoutes()来获取列表属性路由的一个小改进... - Kiran
顺便问一下,你能描述一下你的场景吗?我很好奇你打算如何使用带有属性路由的自定义控制器选择器。 - Kiran
@KiranChalla 谢谢您的建议。我已经解释了我的情况并添加了剩余的代码,请看一下,如果我做错了什么,请纠正我。 - Matija Grcic
@KiranChalla你能否看一下https://dev59.com/r2Ij5IYBdhLWcg3w04bd? - Matija Grcic
有趣的是,DefaultHttpControllerSelector有一个GetControllerName方法,它在子路由上也会失败。 - Jamie Ide
2个回答

14

根据@KiranChalla的确认,除了使用GetSubRoutes()这一小建议之外,我已经实现的方法是最简单的。

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

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

1
@ainteger 不是的,这只是从管道中获取所需数据(控制器名称)的不同方法。 - Matija Grcic
使用“GetSubRoutes()”的建议是非常棒的。这也是我的做法,因为使用“MS_SubRoutes”依赖于一个未经记录的字符串文字,将来可能会很容易地发生变化而没有警告。 - BitMask777

0

这是一个旧的票据,但我可以通过这种方式获取控制器名称。

 var ControllerName = context.Request.RouteValues.Keys.FirstOrDefault();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接