问题描述
|
我有一个自定义的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\"
}
}
有什么建议,其他解决方案吗?
提前谢谢了
解决方法
不,您不能100%确定地从模型联编程序中获取当前操作。模型绑定器不耦合到动作,而是绑定到模型。例如,您可以致电
TryUpdateMode(model)
在选择动作之前的过滤器中。还要注意,可以反映的操作方法甚至可能不是CLR方法(请参阅http://haacked.com/archive/2009/02/17/aspnetmvc-ironruby-with-filters.aspx)。
我认为真正的问题是,您到底想实现什么目标?这是正确的方法吗?如果您希望将操作中的信息传递给模型绑定器(请注意以下提示:如果信息不存在,模型绑定器应适当降级),则应使用操作过滤器将信息放入HttpContext.Items(或类似的地方),然后让您的资料夹将其取回。
动作筛选器的OnActionExecuting方法接收具有ActionDescriptor的ActionExecutingContext。您可以在其上调用GetCustomAttributes。
, 您可以尝试以下方法:
var actionName = controllerContext.RouteData.GetRequiredString(\"action\");
var myAttribute = (MyAttribute) Attribute.GetCustomAttribute(controllerContext.Controller.GetMethod(actionName),typeof(MyAttribute));
, 您可以覆盖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();
}
顺便说一句,“ 9”已经包含“ 10”类型的项目,使您可以访问“ 11”,因此上述代码可能是多余的。但是,请注意,这是特定于实现的,因此可能会随时间而变化。
最后,从您的活页夹类中的存储中获取属性:
var requestContext = (ExtendedRequestContext)controllerContext.RequestContext;
if (requestContext.CustomAttribute != null)
{
// apply your logic here
}