Как я могу получить тип контроллера и информацию о действии из url-адреса или из данных маршрута?

как я могу получить действие контроллера (метод) и тип контроллера, который будет вызван, учитывая System.Web.Routing.RouteData?

мой сценарий таков - Я хочу иметь возможность выполнять определенные действия (или нет) в OnActionExecuting метод действия.

однако я часто хочу знать не текущее действие, а вызываемое действие "root"; под этим я подразумеваю, что у меня может быть представление под названием "Login", которое является моей страницей входа. Это представление может включать еще один частичный вид "LeftNav". Когда OnActionExecuting вызывается для LeftNav, я хочу иметь возможность определить,что он действительно вызывается для "корневого" aciton входа.

Я понимаю это, позвонив 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.Вебсайт.LoginController".

Я бы предпочел получить фактический Type и MethodInfo если это возможно, или, по крайней мере, полное имя типа.

какие-то мысли, или альтернативные подходы?

[редактировать - это ASP.Net MVC 1.0]

4 ответов


  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#. Ключевая идея здесь заключается в том, что вы сохраняете его только для первого запроса, поэтому это всегда корневой контроллер.


вот решение, которое я скомпилировал из разных источников. The 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);
        }

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 / уловы требуется!!!

доброжелательность,

Дэн


MvcSiteMapProvider это. Вот код для этой конкретной вещи.

здесь код