【问题标题】:Using BindAttribute Prefix Directly on Model Class直接在模型类上使用 BindAttribute 前缀
【发布时间】:2014-05-12 01:07:49
【问题描述】:

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

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

BindAttribute 的文档表明它可以用于类。这不是受支持的方案吗?

【问题讨论】:

    标签: .net asp.net-mvc-5 model-binding


    【解决方案1】:

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

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

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

    ModelBinders.Binders.Add(typeof(MyViewModel), new MyViewModelBinder());
    

    在这个例子中,我已经硬编码了前缀,但是你可以让模型绑定器更通用和可重用,并考虑到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);
        }
    }
    

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

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

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

    /someaction?some_prefix.foo=the_foo_value&some_prefix.bar=the_bar_value
    

    【讨论】:

    • 谢谢。我宁愿不再向系统引入任何移动部件,所以由于这不是受支持的 OOtB 场景,我将仅修饰参数并继续。
    • 在我做之前的一个快速问题,是否有可能将绑定器与基本模型类相关联将允许它在从它继承的所有模型中重用,而无需在应用程序启动时指定多个此类指令?
    • 如果我没记错的话,这将适用于基本模型和单一注册,但我不能 100% 确定,应该对其进行测试。
    • 它不适用于基本模型和单个注册:(.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多