我如何获得一个动作,给动作,控制器和地区名称的MethodInfo? [英] How do I get the MethodInfo of an action, given action, controller and area names?

查看:162
本文介绍了我如何获得一个动作,给动作,控制器和地区名称的MethodInfo?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有如下扩展方法:

public MyCustomAttribute[] GetActionAttributes(
    this Controller @this,
    string action,
    string controller,
    string area,
    string method)
{
}

如何ASP.NET MVC 3找到操作方法,鉴于区域,控制器,动作名称和方法(GET,POST)?

How does ASP.NET MVC 3 find the action method, given the area, controller, action names and the method (GET, POST)?

要这一刻我什么都没有......关于如何做到这一点没有任何线索。

To this moment I have nothing... no clues on how to do this.

我目前正在寻找一个控制器动作里面的堆栈跟踪,以了解如何MVC dicovered它。

I am currently looking for the stack trace inside a controller action, to find out how MVC dicovered it.

为什么需要这些属性

我的属性包含有关是否给定用户能够或不能访问它的信息...但是这取决于它们是否能够或不能访问它,我wan't显示或隐藏一些HTML字段,链接,和其他的东西,可能呼吁采取行动。

My attributes contain information about whether a given user can or not access it... but depending on whether they can or not access it, I wan't to show or hide some html fields, links, and other things that could call that action.

其他用途

我也曾想过用这个来放置在一个动作的一个属性,它告诉CSS类将被渲染调用它的链接...和其他一些UI提示的...然后建立一个的HtmlHelper的意愿渲染环节,看着这些属性。

I have thought of using this to place an attribute over an action, that tells the css class of the link that will be rendered to call it... and some other UI hints... and then build an HtmlHelper that will render that link, looking at these attributes.

不重复

是的,有些人会说,这可能是这个问题的一个副本...
在没有我想要的答案:

Yes, some will say this is possibly a duplicate of this question... that does not have the answer I want:

<一个href=\"http://stackoverflow.com/questions/10814147/how-can-i-get-the-methodinfo-of-the-controller-action-that-will-get-called-given\">How我可以将调用特定的请求控制器动作的MethodInfo的?

这就是为什么我指定我的问题的情况。

That's why I have specified the circumstances of my question.

推荐答案

我已经看过MVC 3源$ C ​​$ C内,并与MVC 4的测试,并发现了如何做到这一点。
我已标记的问题错...它不是MVC 3,我使用MVC 4.虽然,我能找到一个解决办法寻找MVC 3 code,那么就可以用MVC 3工作过。

I have looked inside MVC 3 source code, and tested with MVC 4, and discovered how to do it. I have tagged the question wrong... it is not for MVC 3, I am using MVC 4. Though, as I could find a solution looking at MVC 3 code, then it may work with MVC 3 too.

在最后...我希望这是一个值得5小时的探索,有很多的试验和错误。

与作品


  • MVC 3(我认为)

  • MVC 4(测试)

不幸的是,这种解决方案是相当复杂的,并且依赖于事情,我不很喜欢:

Unfortunately, this solution is quite complex, and dependent on things that I don't like very much:


  • 静态对象 ControllerBuilder.Current (非常单元测试坏)

  • 很多从MVC类(高耦合总是不好)

  • 不具有普遍性(它与MVC 3默认的对象,但可能不会与MVC衍生的其他实施工作...如衍生MvcHandler,定制IControllerFactory,等...)

  • 内部依赖(取决于MVC 3的具体方面,(MVC 4的行为像这样太)可能是MVC 5是不同的......比如我知道的RouteData 对象不是用来查找控制器的类型,所以我只是使用存根的RouteData对象)

  • 复杂物体的嘲弄来传递数据(我需要嘲笑 HttpContextWrapper 的Htt prequestWrapper ,以设置 http方法 POST GET ......这些pretty简单值来自于复杂的对象(哦,上帝!= \\))

  • static object ControllerBuilder.Current (very bad for unit testing)
  • a lot of classes from MVC (high coupling is always bad)
  • not universal (it works with MVC 3 default objects, but may not work with other implementations derived from MVC... e.g. derived MvcHandler, custom IControllerFactory, and so on ...)
  • internals dependency (depends on specific aspects of MVC 3, (MVC 4 behaves like this too) may be MVC 5 is different... e.g. I know that RouteData object is not used to find the controller type, so I simply use stub RouteData objects)
  • mocks of complex objects to pass data (I needed to mock HttpContextWrapper and HttpRequestWrapper in order to set the http method to be POST or GET... these pretty simple values comes from complex objects (oh god! =\ ))
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; }
        }
    }
}

希望这一切可以帮助别人...

编程快乐给大家!

这篇关于我如何获得一个动作,给动作,控制器和地区名称的MethodInfo?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆