If i have [Required(AllowEmptyStrings = true)]
declaration in my view model the validation is always triggered on empty inputs. I found the article which explains why it happens. Do you know if there is a fix available? If not, how do you handle it?
Note: I'm assuming you have AllowEmptyStrings = true because you're also using your view model outside of a web scenario; otherwise it doesn't seem like there's much of a point to having a Required attribute that allows empty strings in a web scenario.
There are three steps to handle this:
Step 1: The custom attribute adapter
I modified the RequiredAttributeAdapter to add in that logic:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; namespace CustomAttributes { /// <summary>Provides an adapter for the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> attribute.</summary> public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute> { /// <summary>Initializes a new instance of the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> class.</summary> /// <param name="metadata">The model metadata.</param> /// <param name="context">The controller context.</param> /// <param name="attribute">The required attribute.</param> public RequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute) : base(metadata, context, attribute) { } /// <summary>Gets a list of required-value client validation rules.</summary> /// <returns>A list of required-value client validation rules.</returns> public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() { var rule = new ModelClientValidationRequiredRule(base.ErrorMessage); if (base.Attribute.AllowEmptyStrings) { //setting "true" rather than bool true which is serialized as "True" rule.ValidationParameters["allowempty"] = "true"; } return new ModelClientValidationRequiredRule[] { rule }; } } }
Step 2. Register this in your global.asax / Application_Start()
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(RequiredAttribute), (metadata, controllerContext, attribute) => new CustomAttributes.RequiredAttributeAdapter(metadata, controllerContext, (RequiredAttribute)attribute)); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
Step 3. Override the jQuery "required" validation function
This is done using the jQuery.validator.addMethod() call, adding our custom logic and then calling the original function - you can read more about this approach here. If you are using this throughout your site, perhaps in a script file referenced from your _Layout.cshtml. Here's a sample script block you can drop in a page to test:
<script> jQuery.validator.methods.oldRequired = jQuery.validator.methods.required; jQuery.validator.addMethod("required", function (value, element, param) { if ($(element).attr('data-val-required-allowempty') == 'true') { return true; } return jQuery.validator.methods.oldRequired.call(this, value, element, param); }, jQuery.validator.messages.required // use default message ); </script>
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