Как я могу получить тип контроллера и информацию о действии из 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 / уловы требуется!!!
доброжелательность,
Дэн