Something I've found quite frustrating in ASP.Net MVC is that the default model binder implicitly applies the Required
annotation when binding an empty (string or null) value to a non-nullable value type instead of simply leaving the target with its default value, or at least providing an option to allow that to be the default behaviour.
Given a scenario where it's inconvenient to change the target property type on the model to a nullable value, what's the shortest amount of code I can employ to allow the default model binder to simply skip its attempt to bind an empty value to a non-nullable value type? I'm assuming I'll need to subclass DefaultModelBinder
, but I'm not sure what I need to override to achieve the desired behaviour.
example:
<input type="text" name="MyField"/>
Submit without a value:
public ActionResult MyAction(MyModel model)
{
// do stuff
}
public class MyModel
{
public int MyField { get; set; }
}
The property MyField
should be allowed to retain its default value of 0
seeing as an empty value was posted from the form.
Assume that I can't simply change the property type a Nullable<int>
.
ModelState. IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process.
How about something like this? (Disclaimer: Not tested to any degree of confidence)
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;
}
}
The idea -- in theory -- is to determine what value the DefaultModelBinder
assigned to the property, check if it was a null value and then assign it to the default value of the ValueType
that is being bound.
This should prevent the binder from adding ModelState
errors, and still would not affect the validation of other attributes such as [Range]
I would recommend taking this a step further and creating your own attribute (i.e., NonRequiredAttribute
). Then in your custom model binder you could check to see if the property has the new NonRequired
attribute, and execute this custom code only in the case that it does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With