Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从url或路由数据获取控制器类型和操作信息?_C#_Asp.net_Asp.net Mvc_Asp.net Mvc Routing - Fatal编程技术网

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

C# 如何从url或路由数据获取控制器类型和操作信息?,c#,asp.net,asp.net-mvc,asp.net-mvc-routing,C#,Asp.net,Asp.net Mvc,Asp.net Mvc Routing,给定System.Web.Routing.RoutedData,如何获取将调用的控制器操作方法和控制器类型 我的场景是这样的——我希望能够在操作的OnActionExecuting方法中执行或不执行某些操作 然而,我经常想知道的不是当前的操作,而是被调用的根操作;我的意思是我可能有一个名为Login的视图,这是我的登录页面。这种观点可能包括 另一个部分视图是LeftNav。当为LeftNav调用OnActionExecuting时,我希望能够确定它确实是为登录的根aciton调用的 我意识到,通

给定System.Web.Routing.RoutedData,如何获取将调用的控制器操作方法和控制器类型

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

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

我意识到,通过调用RouteTable.Routes.GetRouteDataactionExecutingContext.HttpContext,我可以获得根请求的路由,但是如何将其转换为 方法和类型信息

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

 var routeData = RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext)
 var routeController = (string)routeData.Values["controller"]; 
 var routeAction = (string)routeData.Values["action"];
问题是RouteControl是控制器名称,控制器后缀被删除,并且不是完全限定的;ie是登录,而不是MyCode.Website.LoginController

如果可能的话,我宁愿得到一个实际的类型和MethodInfo,或者至少是一个完全限定的类型名

有什么想法,或者其他方法吗

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

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);
}
您是否正在考虑类似的实现?需要一些Try/catch

  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中是可用的。这里的关键思想是您只为第一个请求保存它,因此它总是根控制器。

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


以下是我从各种来源编译的解决方案。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);
        }

谢谢你,丹,这是我的目标,但我真的希望避免。在下面的某个地方,MVC确切地知道它将调用什么方法、什么类型。这种方法和我的方法的问题是,我必须附加后缀控制器,还必须将名称空间预先添加到类型中,等等。这可能会起作用,但如果我能够连接到MVC正在做的事情,如果有多个方法具有相同的名称,则GetMethod将抛出AmbiguousMatchException,这是一种非常常见的模式。通常,您必须考虑与RouthDATA中的其他值相关的匹配,以便选择正确的操作方法。不幸的是,这不会起作用,因为它返回当前控制器动作的类型,而不是我所给出的示例中的根控制器动作。我调用GetRouteDataactionExecutingContext.HttpContext的原因是,这确实成功地为我提供了根目录的路由,但我无法将其转换为控制器类型和方法。不要从ASP.NET应用程序中使用ThreadLocal存储。ASP.NET请求可以在线程之间跳转,因此当您不希望线程本地存储时,它可能会消失。如果需要存储仅针对当前请求的信息,请使用HttpContext.Items。实际上,我不知道有任何ASP.NET集合仅存储当前请求的数据。当然,它比线程存储要好。谢谢你的提示。这个位置如何影响动作方法?