Search code examples
c#asp.net-mvcmodel-validation

C# MVC Model Validation Timing


We have a model that is being displayed in a form on a partial view with model validations. We have a few fields like this:

[Required(ErrorMessage = "{0} cannot be empty")]
public string FirstName { get; set; }

[Required(ErrorMessage = "{0} cannot be empty")]
public string LastName { get; set; }

[RegularExpression(@"(\d{5})?", ErrorMessage = "Zip must be a 5 digit number or empty.")]
public string ZipCode { get; set; }

Then in the view we are displaying text boxes for those fields with validation messages for them like this:

<td>
    @Html.TextBoxFor(m => m.Officer.FirstName)
    @Html.ValidationMessageFor(m => m.Officer.FirstName)
</td>
<td>
    @Html.TextBoxFor(m => m.Officer.LastName)
    @Html.ValidationMessageFor(m => m.Officer.LastName)
</td>
<td>
    @Html.TextBoxFor(m => m.Officer.ZipCode)
    @Html.ValidationMessageFor(m => m.Officer.ZipCode)
</td>

The validations are working, but I am noticing something odd with the timing and I haven't been able to find any documentation as to why.

When filling out the form, if I leave FirstName or LastName blank, the validation messages don't appear until I submit the form, check if the model state is valid and return to the page.

However, if I edit zip code with an invalid entry, the validation message popups immeadiately, even if I haven't submitted the form.

Is there anyway to get them to process at the same time so that it doesn't appear weird to the user?


Solution

  • ASP.NET MVC uses Data Annotations for both server-side and client-side validation.

    In the view, you are using Razor.. when you render input fields using HTML Helper Methods (@Html.TextBoxFor for example), the razor view engine looks at the data annotations applied on the reference properties and adds additional attributes to the HTML markup.

    However, only certain/standard data annotations work for client side and they are:

    • [Required] - you won't see the validation message if you leave it empty & before hitting submit.. the client-side performance is seen after clicking 'Submit' and the form not being sent to the server because the client already noticed that those fields are empty.. you can check this by right-clicking on the page where the form is, and clicking 'Inspect' then clicking the 'Network' tab and then hit submit (leave all required fields blank).. you shouldn't see anything under that tab because the client validated the form before it was sent to the server
    • [StringLength]
    • [Range]
    • [Compare]
    • [Phone]
    • [EmailAddress]
    • [Url]
    • [RegularExpression]

    Furthermore, in order for this to work, in your Bundle.config.. you have a bundle probably called "~/bundles/jqueryval".. and that bundle is not referenced in your _Layout page. But, you probably do have a section at the bottom of your _Layout page called @RenderSection("scripts", required: false)..

    So at the bottom of your view that you want to use the validation, you need to write:

    @section scripts{
        @Scripts.Render("~/bundles/jqueryval")
    }