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

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

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

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

Я понимаю, что, позвонив RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext), я могу получитьмаршрут для «корневого» запроса, но как превратить это в метод и тип информации?

Единственное решение, которое у меня есть, это что-то вроде:

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

Проблема с этимявляется то, что "routeController" является именем контроллера с удаленным суффиксом "Controller" и не является полностью квалифицированным;то есть это «Логин», а не «MyCode.Website.LoginController».

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

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

[ РЕДАКТИРОВАТЬ - это ASP.Net MVC 1.0]

Ответы [ 4 ]

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

4 голосов
/ 15 октября 2013

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

Вы думаете о реализации, подобной этой?Требуются некоторые попытки / уловы !!!

Доброта,

Дан

0 голосов
/ 01 ноября 2012

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

Вот код

...