Asp.net mvc 3 如何获取动作、给定动作、控制器和区域名称的MethodInfo?
我有以下扩展方法:Asp.net mvc 3 如何获取动作、给定动作、控制器和区域名称的MethodInfo?,asp.net-mvc-3,Asp.net Mvc 3,我有以下扩展方法: public MyCustomAttribute[] GetActionAttributes( this Controller @this, string action, string controller, string area, string method) { } 在给定区域、控制器、操作名称和方法(GET、POST)的情况下,ASP.NET MVC 3如何找到操作方法 到现在为止我什么都没有。。。没有关于如何做到这一点的线索
public MyCustomAttribute[] GetActionAttributes(
this Controller @this,
string action,
string controller,
string area,
string method)
{
}
在给定区域、控制器、操作名称和方法(GET、POST)的情况下,ASP.NET MVC 3如何找到操作方法
到现在为止我什么都没有。。。没有关于如何做到这一点的线索
我目前正在寻找控制器操作中的堆栈跟踪,以了解MVC是如何发现它的
我为什么需要这些属性
我的属性包含有关给定用户是否可以访问它的信息。。。但取决于他们是否可以访问它,我不想显示或隐藏一些html字段、链接和其他可以调用该操作的内容
其他用途
我曾经考虑过使用它在一个动作上放置一个属性,它告诉css类将要呈现的链接调用它。。。还有其他一些UI提示。。。然后构建一个HtmlHelper来呈现链接,查看这些属性
不是重复的
是的,有些人会说这可能是这个问题的重复。。。
这并没有我想要的答案:
这就是为什么我指定了问题的具体情况。如果您有如下配置的默认路由
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的一篇很棒的博客文章和一个实用工具您可以通过使用authorized属性来实现此功能。您可以在授权方法中获取控制器和操作名称。请在下面找到示例代码
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
}
}
}
公共密封类AuthorizationFilterAttribute:AuthorizationAttribute
{
///
///用于验证用户权限以及验证用户会话处于活动状态时。
///
///过滤上下文。
授权时的公共覆盖无效(AuthorizationContext filterContext)
{
字符串actionName=filterContext.ActionDescriptor.actionName;
字符串控制器=filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
如果(!IsUserHasPermission(控制器,actionName))
{
//做你需要的操作
}
}
}
我查阅了MVC 3的源代码,并用MVC 4进行了测试,发现了如何做到这一点。
我把问题标错了。。。它不适用于MVC 3,我使用的是MVC 4。尽管如此,因为我可以找到一个查看MVC3代码的解决方案,所以它也可以与MVC3一起工作
最后。。。我希望这是值得5个小时的探索,有很多尝试和错误
与
- MVC3(我想)
- MVC 4(已测试)
- 静态对象
(对单元测试非常不利)ControllerBuilder.Current
- 来自MVC的很多类(高耦合总是不好的)
- 不通用(它适用于MVC 3默认对象,但可能不适用于从MVC派生的其他实现…例如派生的MvcHandler、自定义IControllerFactory等…)
- 内部依赖关系(取决于MVC 3的特定方面,(MVC 4的行为也类似于此)可能MVC 5不同…例如,我知道
对象不用于查找控制器类型,所以我只使用存根RouteData对象)RouteData
- 模拟复杂对象以传递数据(我需要模拟
和HttpContextWrapper
,以便将HttpRequestWrapper
设置为http方法
或POST
。这些非常简单的值来自复杂对象(哦,上帝!=\)GET
祝大家编码愉快 这是一个简短的通知!确保使用filterContext.RouteData.DataTokens[“area”];而不是filterContext.RouteData.Values[“area”]
祝你好运。需要更多信息。可能有多个操作具有相同的名称,但响应不同的参数。您是在谈论路由参数吗?我是在谈论方法参数。多个操作方法可能具有相同的名称,但具有不同的参数。如果模型绑定器可以匹配参数,将调用正确的方法。不同的方法仍将具有相同的控制器名称和操作名称;如果使用多个方法,代码将不完整。
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; }
}
}
}