如何从 url 或路由数据获取控制器类型和操作信息?

发布于 2024-08-30 01:14:12 字数 964 浏览 12 评论 0原文

在给定 System.Web.Routing.RouteData 的情况下,如何获取将被调用的控制器操作(方法)和控制器类型?

我的场景是这样的 - 我希望能够在某个操作的 OnActionExecuting 方法中执行(或不执行)某些操作。

然而,我经常想知道的不是当前的操作,而是被调用的“根”操作;我的意思是我可能有一个名为“登录”的视图,这是我的登录页面。该视图可能包括 另一个部分视图“LeftNav”。当为 LeftNav 调用 OnActionExecuting 时,我希望能够确定它确实是为 Login 的“root”操作而调用的。

我意识到通过调用 RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext),我可以获取“root”请求的路由,但如何将其变成 方法和类型信息?

到目前为止,我唯一的解决方案是这样的:

 var routeData = RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext)
 var routeController = (string)routeData.Values["controller"]; 
 var routeAction = (string)routeData.Values["action"];

问题是“routeController”是删除了“Controller”后缀的控制器名称,并且不是完全限定的;即它是“登录”,而不是“MyCode.Website.LoginController”。

如果可能的话,我宁愿获得实际的 TypeMethodInfo,或者至少获得完全限定的类型名称。

有什么想法或替代方法吗?

[编辑 - 这是 ASP.Net MVC 1.0]

How can I get the controller action (method) and controller type that will be called, given the System.Web.Routing.RouteData?

My scenario is this - I want to be able to do perform certain actions (or not) in the OnActionExecuting method for an action.

However, I will often want to know not the current action, but the "root" action being called; by this I mean I may have a view called "Login", which is my login page. This view may include
another partial view "LeftNav". When OnActionExecuting is called for LeftNav, I want to be able to determine that it is really being called for the "root" aciton of Login.

I realise that by calling RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext), I can get the route for the "root" request, but how to turn this into
method and type info?

The only solution I have so far, is something like:

 var routeData = RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext)
 var routeController = (string)routeData.Values["controller"]; 
 var routeAction = (string)routeData.Values["action"];

The problem with this is that "routeController" is the controller name with the "Controller" suffix removed, and is not fully qualified; ie it is "Login", rather than "MyCode.Website.LoginController".

I would far rather get an actual Type and MethodInfo if possible, or at least a fully qualified type name.

Any thoughts, or alternative approaches?

[EDIT - this is ASP.Net MVC 1.0]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

温馨耳语 2024-09-06 01:14:12
  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     var type1 = filterContext.Controller.GetType();
     var type2 = filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

好吧,抱歉,我错过了“根”部分。

然后,另一种方法是,您可以将控制器类型保存到线程存储中。伪代码:

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     if (!Thread.LocalStorage.Contains("root_controller"))
        Thread.LocalStorage["root_controller"] = 
            filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

只是一个想法。我确信 C# 中可以使用线程本地存储。这里的关键思想是仅在第一次请求时保存它,因此它始终是根控制器。

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     var type1 = filterContext.Controller.GetType();
     var type2 = filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

OK, sorry, I missed the "root" part.

Then, another way, you can save controller type to thread storage. Pseudocode:

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     if (!Thread.LocalStorage.Contains("root_controller"))
        Thread.LocalStorage["root_controller"] = 
            filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

Just an idea. I'm sure thread local storage is available in C#. The key idea here is that you save it only for first request, thus it's always root controller.

此刻的回忆 2024-09-06 01:14:12

这是我从各种来源编译的解决方案。 url 变量应包含操作的 URL:

        url = "YOUR URL";
        // Original path is stored and will be rewritten in the end
        var httpContext = new HttpContextWrapper(HttpContext.Current);
        string originalPath = httpContext.Request.Path;

        try
        {
            // Fake a request to the supplied URL into the routing system
            httpContext.RewritePath(url);
            RouteData urlRouteData = RouteTable.Routes.GetRouteData(httpContext);

            // If the route data was not found (e.g url leads to another site) then authorization is denied.
            // If you want to have a navigation to a different site, don't use AuthorizationMenu
            if(urlRouteData != null)
            {
                string controllerName = urlRouteData.Values["controller"].ToString();
                string actionName = urlRouteData.Values["action"].ToString();

                // Get an instance of the controller that would handle this route
                var requestContext = new RequestContext(httpContext, urlRouteData);
                var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
                var controller = (ControllerBase) controllerFactory.CreateController(requestContext, controllerName);

                // Find the action descriptor
                var controllerContext = new ControllerContext(httpContext, new RouteData(), controller);
                var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
                var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
            }
        }
        finally
        {
            // Reset our request path.
            httpContext.RewritePath(originalPath);
        }

Here is the solution I compiled from various sources. The url variable should contain the URL of the action:

        url = "YOUR URL";
        // Original path is stored and will be rewritten in the end
        var httpContext = new HttpContextWrapper(HttpContext.Current);
        string originalPath = httpContext.Request.Path;

        try
        {
            // Fake a request to the supplied URL into the routing system
            httpContext.RewritePath(url);
            RouteData urlRouteData = RouteTable.Routes.GetRouteData(httpContext);

            // If the route data was not found (e.g url leads to another site) then authorization is denied.
            // If you want to have a navigation to a different site, don't use AuthorizationMenu
            if(urlRouteData != null)
            {
                string controllerName = urlRouteData.Values["controller"].ToString();
                string actionName = urlRouteData.Values["action"].ToString();

                // Get an instance of the controller that would handle this route
                var requestContext = new RequestContext(httpContext, urlRouteData);
                var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
                var controller = (ControllerBase) controllerFactory.CreateController(requestContext, controllerName);

                // Find the action descriptor
                var controllerContext = new ControllerContext(httpContext, new RouteData(), controller);
                var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
                var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
            }
        }
        finally
        {
            // Reset our request path.
            httpContext.RewritePath(originalPath);
        }
那一片橙海, 2024-09-06 01:14:12
public Type ControllerType(string controllerName)
{
   var fullName = controllerName + "Controller";
   var assemblyName = Assembly.GetExecutingAssembly().FullName;
   return Activator.CreateInstance(assemblyName, fullTypeName).GetType();
}

public MethodInfo ActionMethodInfo(string actionName, Type controllerType)
{
   return controllerType.GetMethod(actionName);
}

您是否正在考虑类似的实现?需要一些尝试/捕获!

public Type ControllerType(string controllerName)
{
   var fullName = controllerName + "Controller";
   var assemblyName = Assembly.GetExecutingAssembly().FullName;
   return Activator.CreateInstance(assemblyName, fullTypeName).GetType();
}

public MethodInfo ActionMethodInfo(string actionName, Type controllerType)
{
   return controllerType.GetMethod(actionName);
}

Are you thinking of an implementation similar to this? Some Try/Catches required!

终止放荡 2024-09-06 01:14:12

MvcSiteMapProvider 就是这样做的。这是这个特定事物的代码。

这里是代码

MvcSiteMapProvider does this. Here is the code for this particular thing.

Here is the code

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文