从自定义HtmlHelper扩展中,我想获得MethodInfo
的动作。
我知道我可以得到控制器的类型,以及动作的字符串名称:
public static void MyHelper(this HtmlHelper helper)
{
var controller = helper.ViewContext.Controller;
var actionName = ViewContext.Controller.ValueProvider.GetValue("action").RawValue;
}
但是我真正想要的是MethodInfo
,因为我想从动作方法中拉出一个自定义的Attribute
。我不能只是调用反射.GetMethod(actionName);
,因为通常有超过1个具有相同的名称(两个具有相同名称的操作,一个用于http GET,一个用于POST)。
在这一点上,我想我可能不得不手动获得所有方法与动作名称,并通过ViewContext.Controller.ValueProvider
中的所有信息,看看什么方法有参数匹配的值在提供者,但我希望MethodInfo已经在某处可用…
要做到这一点真的不容易。通常你用自定义动作过滤器来修饰控制器动作(不只是任何类型的属性)。所以你可以让这个自定义动作过滤器在当前HttpContext中注入一些信息,这样HTML助手就会知道视图是从一个用这个自定义动作过滤器装饰的控制器动作中提供的。
获取当前Action的MethodInfo的一种方法是使用StackTrace和RouteData的组合。
你需要过滤掉所有不需要的StackTrace帧。
代码将从嵌套的控制器类中工作,您可以在其中放置您的公共帮助程序,或者您可以在父控制器
中放置public FooController : BaseController
{
[YourCustomAttribute]
public ActionResult Edit(int id)
{
MethodInfo action = CurrentExecutingAction();
// your code here, now you can get YourCustomAttribute Attribute for the Action
}
}
public abstract class BaseController : Controller
{
protected MethodInfo CurrentExecutingAction(Type type = null)
{
type = type ?? GetType();
var rd = ControllerContext.RouteData;
var currentAction = rd.GetRequiredString("action");
StackTrace s = new StackTrace();
return s.GetFrames()
.Select(x => x.GetMethod())
.Where(x => x is MethodInfo && x.Name == currentAction && x.DeclaringType.IsAssignableFrom(type))
.Select(x => (MethodInfo) x)
.LastOrDefault();
}
}
我已经回答了我自己的问题,那和这个非常相似。
- 问题:我如何获得一个动作的MethodInfo,给定的动作,控制器和区域名称?
- 答:https://stackoverflow.com/a/13044838/195417
给定一个活动控制器,以及另一个控制器和动作的名称,以及http方法(GET, POST),我开发了一个可以获取属性的方法。
像这样:
public static Attribute[] GetAttributes(
this Controller @this,
string action = null,
string controller = null,
string method = "GET")
你这样称呼它:
var attrs = liveController
.GetAttributes("anotherAction", "anotherController", "POST");