Unobtrusive validation attributes rendered for nul

2019-06-24 01:34发布

问题:

I have this setup:

ViewModel:

public class MyViewModel
{
    public DateTime? Start { get; set; }
}

View:

@model MvcApplication2.Models.MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Start)
}

Resulting HTML:

<input class="text-box single-line" data-val="true" data-val-date="The field Start must be a date." id="Start" name="Start" type="datetime" value="" />

This HTML includes the unobtrusive validation attributes. Why is that? I was under the impression that there would be no validation if the ViewModel property is a nullable DateTime?

回答1:

The problem had to do with Globalization. Since I'm supporting multiple cultures, I'm including the jquery-globalize scripts and added the following:

$(document).ready(function () {
    $.validator.methods.date = function (value, element) {
        return Globalize.parseDate(value);
    }
});

Globalize.parseDate failed on an empty value. This only becomes obvious on nullable date fields, where an empty value should be considered valid. If I replace it with

return value == '' ? null : Globalize.parseDate(value);

everything works as expected.



回答2:

Because MVC is smart enough to figure out that since the type of your property is DateTime then whatever is placed in there must at the minimum be a valid date. In other words the validation restrictions placed are due to the fact that your property is of type DateTime. The validation will only be enforced is something is entered into the field.



回答3:

Even though this is an old post, it appears near the top of the Google search results when the search term "MVC Date Validation for nullable field" is entered.

HTML5 has an excellent solution: use @type = "date", and @min and @max attributes for the field like this:

@Html.TextBoxFor(Model => Model.YourPropertyHere, "{0:yyyy-MM-dd}", new { id = "YourPropertyID", @class = "form-rounded", @type = "date", @min = "2019-01-01", @max = "2099-01-01" })

and also the validation message:

@Html.ValidationMessageFor(model => model.YourPropertyHere, "", new { @class = "text-danger" })

The @class attribute references Bootstrap's css.