如何覆盖ASP.Net MVC的默认模型绑定器,以便绑定到非可空值类型的空值不会触发模型验证错误

Nat*_*ley 6 asp.net-mvc model-binding

我发现在ASP.Net MVC中非常令人沮丧的是,默认模型Required绑定器在将空(字符串或空值)绑定到不可为空的值类型时隐式应用注释,而不是简单地使目标保留其默认值,或者至少提供一个选项,允许它成为默认行为.

鉴于将模型上的目标属性类型更改为可以为空的值不方便的情况,我可以使用的最短代码量是什么,以允许默认模型绑定器简单地跳过将空值绑定到不可空的值的尝试值类型?我假设我需要子类DefaultModelBinder,但我不确定我需要覆盖什么来实现所需的行为.

例:

<input type="text" name="MyField"/>
Run Code Online (Sandbox Code Playgroud)

提交没有价值:

public ActionResult MyAction(MyModel model)
{
    // do stuff
}

public class MyModel
{
    public int MyField { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

MyField应该允许该属性保留其默认值,0即从表单中发布空值.

假设我不能简单地改变属性类型a Nullable<int>.

NKe*_*die 2

像这样的事情怎么样?(免责声明:未经任何程度的可信度测试)

public class NonRequiredModelBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        var result = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
        if (result == null && propertyDescriptor.PropertyType.IsValueType)
            return Activator.CreateInstance(propertyDescriptor.PropertyType);

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

理论上,这个想法是确定DefaultModelBinder分配给属性的值,检查它是否为空值,然后将其分配给ValueType正在绑定的默认值。

这应该可以防止绑定器添加ModelState错误,并且仍然不会影响其他属性的验证,例如[Range]

我建议更进一步并创建您自己的属性(即NonRequiredAttribute)。然后,在自定义模型绑定程序中,您可以检查该属性是否具有新NonRequired属性,并在具有新属性的情况下执行此自定义代码。