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

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

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

例:

<input type="text" name="MyField"/>

提交没有价值:

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

public class MyModel
{
    public int MyField { get; set; }
}

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

假设我不能简单地将属性类型更改为Nullable< int>.

最佳答案
这样的事怎么样? (免责声明:未经任何程度的信任测试)

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;
    }
}

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

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

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

转载注明原文:asp.net-mvc – 如何覆盖ASP.Net MVC的默认模型绑定器,以便绑定到非可空值类型的空值不会触发模型验证错误 - 代码日志