直接在模型类上使用BindAttribute前缀

lsu*_*rez 2 .net model-binding asp.net-mvc-5

我想将控制器动作与系统的其他元素完全隔离,因为它是遗留代码的重构,因此可以在系统的各个位置呈现动作.为了隔离局部视图模型中属性名称的任何重叠,我希望在表单名称属性前加上一定的值,并使用BindAttribute来指示ModelBinder将模型属性与适当的前缀表单字段进行匹配.

由于我有一些使用这个模型的动作,我希望我可以将[Bind]装饰器直接放在模型类本身上,避免必须装饰进入每个动作的每个模型参数.但是,这种方法似乎没有注册到绑定器,所以我最终得到了无人居住的属性.另一方面,如果我将装饰器移动到参数,一切都很好.

BindAttribute的文档表明它可以在类上使用.这不是支持的方案吗?

Dar*_*rov 5

您可以为相应的视图模型编写自定义模型绑定器:

public class MyViewModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        bindingContext.ModelName = "some_prefix";
        return base.BindModel(controllerContext, bindingContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在您Application_Start的视图模型中注册并与之关联:

ModelBinders.Binders.Add(typeof(MyViewModel), new MyViewModelBinder());
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我已经硬编码了前缀,但你可以使模型绑定器更通用和可重用,并考虑到BindAttribute你可以用来装饰你的视图模型:

public class MyViewModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // TODO: cache the result of this LINQ query to 
        // avoid using reflecting on each request. After all
        // the metadata of the view model won't change at runtime
        var bindAttribute = bindingContext
            .ModelType
            .GetCustomAttributes(typeof(BindAttribute), true)
            .OfType<BindAttribute>()
            .FirstOrDefault();

        bindingContext.ModelName = bindAttribute != null ? bindAttribute.Prefix : null;
        return base.BindModel(controllerContext, bindingContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后剩下的就是使用Bind属性装饰你的视图模型:

[Bind(Prefix = "some_prefix")]
public class MyViewModel
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

并请求采用此视图模型的操作:

/someaction?some_prefix.foo=the_foo_value&some_prefix.bar=the_bar_value
Run Code Online (Sandbox Code Playgroud)