Asp.NET MVC ModelBinder,获取Action Method

时间:2011-06-01 08:14:40

标签: asp.net-mvc asp.net-mvc-2 asp.net-mvc-3

我有一个自定义的ModelBinder,我想得到这个动作。因为我想使用反射来获取动作的属性,所以动作名称是不够的。

我的行动方法:

[MyAttribute]
public ActionResult Index([ModelBinder(typeof(MyModelBinder))] MyModel model)
{
}

这里通常是ModelBinder

public class MyModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {
        // here i would like to get the action method and his "MyAttribute"
    }
}

任何建议,其他解决方案?

非常感谢提前

3 个答案:

答案 0 :(得分:4)

不,你不能100%确定地从模型绑定器中获取当前操作。模型绑定器不与动作耦合,而是绑定到模型。例如,您可以致电

TryUpdateMode(model)

在选择操作之前的过滤器中。另请注意,操作方法可能甚至不是可以反映的CLR方法(请参阅http://haacked.com/archive/2009/02/17/aspnetmvc-ironruby-with-filters.aspx)。

我认为真正的问题是,你究竟想要完成什么,这是正确的方法吗?如果您希望将来自操作的信息传递给模型绑定器(如果信息不存在,请注意模型绑定器应该正常降级的建议),您应该使用操作过滤器将信息放入HttpContext.Items(或在某个地方)然后让你的活页夹检索它。

动作过滤器的OnActionExecuting方法接收具有ActionDescriptor的ActionExecutingContext。你可以在那上面调用GetCustomAttributes。

答案 1 :(得分:1)

你可以试试这个:

var actionName = controllerContext.RouteData.GetRequiredString("action");
var myAttribute = (MyAttribute) Attribute.GetCustomAttribute(controllerContext.Controller.GetMethod(actionName), typeof(MyAttribute));

答案 2 :(得分:0)

您可以覆盖ControllerActionInvoker.FindAction()以获取操作的属性,并将其存储在此处提及的HttpContext.Current.Items或扩展ControllerContext.RequestContext中,如下所示:

public class MyControllerActionInvoker : ControllerActionInvoker
{
    protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
    {
        var action = base.FindAction(controllerContext, controllerDescriptor, actionName);

        if (action != null)
        {
            var requestContext = ExtendedRequestContext.Bind(controllerContext);
            var attr = action.GetCustomAttributes(typeof(MyAttribute), false).FirstOrDefault();

            if (attr != null)
                requestContext.CustomAttribute = (MyAttribute)attr;
        }

        return action;
    }
}

public class ExtendedRequestContext : RequestContext
{
    public MyAttribute CustomAttribute { get; set; }

    public static ExtendedRequestContext Bind(ControllerContext controllerContext)
    {
        var requestContext = new ExtendedRequestContext
        {
            HttpContext = controllerContext.RequestContext.HttpContext,
            RouteData = controllerContext.RequestContext.RouteData
        };

        controllerContext.RequestContext = requestContext;
        return requestContext;
    }
}

默认操作调用程序在控制器的构造函数或自定义控制器工厂中被替换:

public MyController() : base()
{
    ActionInvoker = new MyControllerActionInvoker();
}

顺便说一下,Controller.TempData已经包含ReflectedParameterDescriptor类型的项目,您可以访问ActionDescriptor,因此上述代码可能是多余的。但是,请注意这是特定于实现的,因此可能会随着时间而改变。

最后,从您的binder类中获取该存储的属性:

var requestContext = (ExtendedRequestContext)controllerContext.RequestContext;
if (requestContext.CustomAttribute != null)
{
    // apply your logic here
}