Search code examples
asp.net-mvcdatejquery-validateunobtrusive-validation

MVC model validation fails - Date must be a valid date


I am working on a production environment. The issue is the DOB field is provided with mvc model validations and in the view jquery.validate.unobtrusive.js is used to validate the form.

Date picker is used to pick the date, when I submit the form, the ModelState.IsValid fails.

The code is shown below. This works properly with Chrome, but not in other browsers.

In my model:

[Required(ErrorMessage = "Please enter DOB")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> DOB { get; set; }

This is my view:

<div class="col-md-6">
    <div class="col-xs-12">
        <label>DATE OF BIRTH<p>*</p></label>
    </div>
    <div class="col-xs-12">
        <div class="form-group">
            <div class="input-group" id="datetimepicker2">
                @Html.TextBoxFor(d => d.DOB, new { @class = "form-control input-validation-error" })
                <span class="input-group-addon"><span class="icon-small-calendar"></span></span>
                </div>
            @Html.ValidationMessageFor(m => m.DOB)
            </div>
    </div>
</div>

This is my datepicker:

$('#datetimepicker2').datetimepicker({
        format: 'MM/DD/YYYY',           
        maxDate: new Date()
    });

In my controller:

if (ModelState.IsValid)
   {
      ///some action
   }

In my web.config:

<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

Can someone help me how to fix this for all browsers

Thanks in advance Tarak


Solution

  • Usually, the error "Date must be a valid date" is generated client side (in browser) by the JQuery validation framework. If this is the case, you need to override the JavaScript method used for validation. In order to do so, in a client side javascript IIFE, you could add something like that:

    if (!$.validator) {
        return;
    }
    
    // Tell the validator that we want dates parsed using Globalize
        $.validator.methods.date = function(value, element) {
        // parse the value parameter into a Date datatype using your own logic or that of a framework like JQuery Globalize. In the example, I used JQuery Globalize
        var parsedValue = Globalize.parseDate(value, $.validator.methods.dateGlobalizeOptions.dateParseFormat);.
            return this.optional(element) || (parsedValue instanceof Date);
        };
    

    Additionally, you might need to implement a custom DataBinder on the server side:

    public class DateTimeModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
    
            object result = null;
            if (value != null)
            {
                result = DateTime.ParseExact(value, "MM/DD/YYYY", CultureInfo.InvariantCulture, DateTimeStyles.None);                
            }
    
            return result;
        }
    }
    //and in global.asax.cs add 
    ModelBinders.Binders.Add(typeof(Datetime), new Binders.DateTimeModelBinder());