我所拥有的是以下扩展方法:
public MyCustomAttribute[] GetActionAttributes(
this Controller @this,
string action,
string controller,
string area,
string method)
{
}
ASP.NET MVC 3如何根据区域,控制器,操作名称和方法(GET,POST)找到操作方法?
到目前为止,我什么都没有......没有关于如何做到这一点的线索。
我目前正在寻找控制器动作中的堆栈跟踪,以了解MVC如何发现它。
为什么我需要这些属性
我的属性包含有关给定用户是否可以访问它的信息...但是根据他们是否可以访问它,我不想显示或隐藏某些html字段,链接和其他可能的内容称之为行动。
其他用途
我曾想过使用它来在一个动作上放置一个属性,告诉css类将被渲染的链接调用它......以及其他一些UI提示......然后构建一个HtmlHelper,它将会渲染该链接,查看这些属性。
不重复
是的,有人会说这可能是这个问题的重复...... 没有我想要的答案:
How can i get the MethodInfo of the controller action that will get called given a request?
这就是我说明问题情况的原因。
答案 0 :(得分:9)
我查看了MVC 3源代码,并使用MVC 4进行了测试,并发现了如何做到这一点。 我已经标记了错误的问题......它不适用于MVC 3,我使用的是MVC 4.虽然我可以找到一个查看MVC 3代码的解决方案,但它也可以与MVC 3一起使用。
最后......我希望这需要5个小时的探索,经过大量的试验和错误。
使用
不幸的是,这个解决方案非常复杂,并且依赖于我不太喜欢的事情:
ControllerBuilder.Current
(单元测试非常糟糕)RouteData
对象不是用于查找控制器类型,因此我只使用存根RouteData对象)HttpContextWrapper
和HttpRequestWrapper
才能将http method
设置为POST
或GET
......这些非常简单的值来自复杂的物体(天啊!= \))public static Attribute[] GetAttributes(
this Controller @this,
string action = null,
string controller = null,
string method = "GET")
{
var actionName = action
?? @this.RouteData.GetRequiredString("action");
var controllerName = controller
?? @this.RouteData.GetRequiredString("controller");
var controllerFactory = ControllerBuilder.Current
.GetControllerFactory();
var controllerContext = @this.ControllerContext;
var otherController = (ControllerBase)controllerFactory
.CreateController(
new RequestContext(controllerContext.HttpContext, new RouteData()),
controllerName);
var controllerDescriptor = new ReflectedControllerDescriptor(
otherController.GetType());
var controllerContext2 = new ControllerContext(
new MockHttpContextWrapper(
controllerContext.HttpContext.ApplicationInstance.Context,
method),
new RouteData(),
otherController);
var actionDescriptor = controllerDescriptor
.FindAction(controllerContext2, actionName);
var attributes = actionDescriptor.GetCustomAttributes(true)
.Cast<Attribute>()
.ToArray();
return attributes;
}
修改强>
忘记模拟的课程
class MockHttpContextWrapper : HttpContextWrapper
{
public MockHttpContextWrapper(HttpContext httpContext, string method)
: base(httpContext)
{
this.request = new MockHttpRequestWrapper(httpContext.Request, method);
}
private readonly HttpRequestBase request;
public override HttpRequestBase Request
{
get { return request; }
}
class MockHttpRequestWrapper : HttpRequestWrapper
{
public MockHttpRequestWrapper(HttpRequest httpRequest, string httpMethod)
: base(httpRequest)
{
this.httpMethod = httpMethod;
}
private readonly string httpMethod;
public override string HttpMethod
{
get { return httpMethod; }
}
}
}
希望所有这些都有助于某人...
为所有人编写快乐代码!
答案 1 :(得分:3)
您可以使用 AuthorizeAttribute 来实现此功能。您可以在 OnAuthorization 方法中获取Controller和Action名称。请在下面找到示例代码。
public sealed class AuthorizationFilterAttribute : AuthorizeAttribute
{
/// <summary>
/// Use for validate user permission and when it also validate user session is active.
/// </summary>
/// <param name="filterContext">Filter Context.</param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
string actionName = filterContext.ActionDescriptor.ActionName;
string controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
if (!IsUserHasPermission(controller, actionName))
{
// Do your required opeation
}
}
}
答案 2 :(得分:0)
如果您的默认路由配置为
routes.MapRoute(
"Area",
"",
new { area = "MyArea", controller = "Home", action = "MyAction" }
);
您可以在控制器操作中获取路径信息,如
ht tp:// localhost / Admin
会给你
public ActionResult MyAction(string area, string controller, string action)
{
//area=Admin
//controller=Home
//action=MyAction
//also you can use RouteValues to get the route information
}
这是一篇很棒的博客文章和Phil Haack RouteDebugger 2.0
的实用程序答案 3 :(得分:0)
这是一个简短的通知!一定要使用filterContext.RouteData.DataTokens [“area”];而不是filterContext.RouteData.Values [“area”];
祝你好运。