.net 使用属性影响MVC ModelBinder

.net 使用属性影响MVC ModelBinder,.net,asp.net-mvc,asp.net-mvc-3,model-binding,modelbinders,.net,Asp.net Mvc,Asp.net Mvc 3,Model Binding,Modelbinders,在MVC3.Net中,可以为控制器方法的方法签名中的参数类型设置绑定属性: [HttpPost] public ActionResult Edit([Bind(Exclude = "Name")]User user) { ... } 我已经编写了一些定制的ModelBinder。如果能够基于参数类型上设置的属性来影响它们的行为,那就太好了,如下所示: [HttpPost] public ActionResult Edit([CustomModelBinderSettings(DoCust

在MVC3.Net中,可以为控制器方法的方法签名中的参数类型设置绑定属性:

[HttpPost]
public ActionResult Edit([Bind(Exclude = "Name")]User user)
{
   ...
}
我已经编写了一些定制的ModelBinder。如果能够基于参数类型上设置的属性来影响它们的行为,那就太好了,如下所示:

[HttpPost]
public ActionResult Edit([CustomModelBinderSettings(DoCustomThing = "True")]User user)
{
   ...
}
但是,我似乎找不到恢复属性数据的方法。这可能吗

编辑

我正在尝试从自定义ModelBinder中访问AttributeData。在下面的示例中,设置始终为空

public class TestBinder : DefaultModelBinder {
        public override object BindModel(
            ControllerContext controllerContext, 
            ModelBindingContext bindingContext) {

            //Try and get attribute from ModelType
            var settings = (CustomModelBinderSettingsAttribute) 
                TypeDescriptor.GetAttributes(bindingContext.ModelType)[typeof(CustomModelBinderSettingsAttribute)];

            ...

感谢您的帮助。

要从CustomModelBinderAttribute中访问DoCustomThing属性的值,您不必做任何事情。您在哪里尝试读取DoCustomThing的值,但它不可用

public class CustomModelBinderSettingsAttribute : CustomModelBinderAttribute
{
    public string DoCustomThing { get; set; }
    public override IModelBinder GetBinder()
    {
        // Pass the value of DoCustomThing to the custom model binder instance.
        MyCustomizableModelBinder binder = new MyCustomizableModelBinder(this.DoCustomThing);
        return binder;
    }
}
回答:不可能:

我浏览了MVC源代码,最终发现ControllerActionInvoker类从Action方法参数显式访问bind属性,并在bindingContext的属性上设置它们。如果不重写MVC基础结构的大部分内容,就不可能从ModelBinder访问添加到操作参数的属性

但是,可以使用如下所示的代码检索ViewModel上设置的属性:

var attr = ("GetTypeDescriptor(controllerContext, bindingContext).GetAttributes()[typeof(BindAttribute)];

唉,这不是我在本例中打算做的,但现在必须这样做。

如果您拥有或创建了新的AuthorizeAttribute过滤器属性,它可能会将filterContext.ActionDescriptor您的操作存储在HttpContext.Current.Items中,然后在ModelBinder中检索该值。使用ActionDescriptor,您可以通过bindingContext.ModelName找到所需的参数,并检查属性是否存在

注意事项:

ModelBinder未绑定到已执行的操作 使用ControllerContext可以调用ActionName,但调用的实际方法可能会有多个参数重载 AuthorizeFilter在ModelBinder之前调用,普通ActionFilter在ModelBinder之后调用
您可以通过拦截Controller.ActionInvoker.FindAction并将属性存储在此处提到的HttpContext.Current.Items或extended ControllerContext.RequestContext中来获取操作及其参数的属性,如下所示:

公共类MyControllerActionInvoker:ControllerActionInvoker { 受保护的覆盖操作描述符FindActionControllerContext controllerContext,ControllerDescriptor ControllerDescriptor,string actionName { var action=base.FindActioncontrollerContext,controllerDescriptor,actionName; 如果操作!=null { var requestContext=ExtendedRequestContext.BindcontrollerContext; //如有必要,请使用action.GetCustomAttributes添加操作的属性 foreach var参数在action.GetParameters中 { var attr=parameter.GetCustomAttributestypeofMyBinderAttribute,false.FirstOrDefault; 如果attr!=null requestContext.Attributes.Addparameter.ParameterName,MyBinderAttributeattr; } } 返回动作; } } 公共类ExtendedRequestContext:RequestContext { 公共字典属性{get;private set;} 公共静态ExtendedRequestContext BindControllerContext controllerContext { var requestContext=新的ExtendedRequestContext { HttpContext=controllerContext.RequestContext.HttpContext, RouteData=controllerContext.RequestContext.RouteData, 属性=新字典 }; controllerContext.RequestContext=RequestContext; 返回请求上下文; } } 在控制器的构造函数或自定义控制器工厂中替换默认操作调用程序:

公共MyController:base { ActionInvoker=新的MyControllerActionInvoker; } 顺便说一下,Controller.TempData已经包含ReflectedParameterDescriptor类型的项,该项允许您访问ActionDescriptor,因此上述代码可能是多余的。但是,请注意,这是特定于实现的,因此可能会随着时间的推移而改变

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

var requestContext=ExtendedRequestContextcontrollerContext.requestContext; 如果requestContext.Attributes.ContainsKeybindingContext.ModelName { var attr=requestContext.Attributes[bindingContext.ModelName]; //在这里应用你的逻辑 }
谢谢你的回复。我已更新了我的问题,以包括我试图从Not true访问属性数据的上下文示例,请参见下面的答案参见:[在视图模型属性上查找自定义属性][1][1]: