从绑定中排除某些属性的最佳方法

Best way to exclude some properties from binding

我的一个 classes 有一些属性,我希望模型活页夹始终忽略它们。

目前我在操作方法中使用 [Bind(Exclude ="")],如下所示:

public ActionResult Edit([Bind(Exclude = "prop1, prop2, prop3")] BusinessModel model)

这个class已经用在了几个动作方法中。我必须手动排除它们,还是有更好的方法?

我应该特别注意 class,它们是导航属性。

使用集中式代码解决此问题的一种方法是覆盖 DefaultModelBinderBindModel 并排除您不想绑定的属性。

public class CustomDataBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(BusinessModel))
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;
            string name = request.Form.Get("Name");
            return new BusinessModel
            {
                Name = name
            };                
        }
        else
        {
            return base.BindModel(controllerContext, bindingContext);
        }
    }
}

然后在Application_Start()中的Global.asax注册。

ModelBinders.Binders.Add(typeof(BusinessModel), new CustomDataBinder());

在上述情况下,我使用了 BusinessModel,如下所述 -

public class BusinessModel
{
    public string prop1 { get; set; }
    public string Name { get; set; }
}

为了测试,我创建了一个简单的视图 -

@model WebApplication1.Controllers.BusinessModel

@using (Html.BeginForm("PostData", "Home"))
{
    @Html.EditorFor(model => model.prop1, new { htmlAttributes = new { @class = "form-control" } })
    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })

    <input type="submit" value="Create" class="btn btn-default" />
}

视图呈现时,我在两个编辑器中都输入了一些数据 -

当我点击创建按钮时,Prop1 编辑器中输入的值未绑定 -

很棒,但我想添加一个小细节。

return base.BindModel 使用新的 BindingContext 可能更好,它排除了要忽略的属性而不是 returning 一个 BusinessModel 对象直的。

这让 DefaultModelBinder 的 ModelState 验证机制开始运行。

public class CustomDataBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(BusinessModel))
        {
            BindAttribute bindAttribute = new BindAttribute
            {
                Exclude = "prop1, prop2, prop3"
            };

            // create new property filter where only properties which are not exluded in the above bindAttribute are bound
            Predicate<string> newPropertyFilter = propertyName => bindAttribute.IsPropertyAllowed(propertyName) && bindingContext.PropertyFilter(propertyName);         

            ModelBindingContext newBindingContext = new ModelBindingContext()
            {
                //bind default ModelMetaData
                ModelMetadata = bindingContext.ModelMetadata,

                //set to new property filter which exludes certain properties
                PropertyFilter = newPropertyFilter,

                //bind default ModelState
                ModelState = bindingContext.ModelState,

                //bind default ValueProvider
                ValueProvider = bindingContext.ValueProvider
            };
            return base.BindModel(controllerContext, newBindingContext);
        }
        else
        {
            return base.BindModel(controllerContext, bindingContext);
        }
    }
}