Here is what they look like:
<input type="text" name="UserName" data-val-required="The Username field is required." data-val="true" class="text-box single-line" />
- data-val turns unobtrusive validation on for the input
- data-val-required enables the required validation rule to kick in with the specified error message you see above
If you want to go into more detail, check out Brad Wilson’s in depth post about Unobtrusive Client Validation in ASP.NET MVC3.
The specific problem we were both encountering was that these attributes were simply not being output on our view when rendered in the browser.
I peeked into the source of System.Web.Mvc.dll and here is what I discovered.
- When you render an input using an HtmlHelper like @Html.EditorFor, @Html.TextBox etc., they are rendered with the InputExtensions.InputHelper method.
- InputHelper calls HtmlHelper.GetUnobtrusiveValidationAttributes to render the data-val attributes.
- GetUnobtrusiveValidationAttributes calls ViewContext.GetFormContextForClientValidation which checks to see if ClientValidation is enabled in the either your web.config or the scope of the view that you are rendering.
- GetFormContextForClientValidation will return the FormContext that was instantiated with @Html.BeginForm OR return null.
- If it returns null, no attributes are rendered, thus the need for Html.BeginForm.
So to re-cap. I discovered the problem was that my colleague had NOT created his form using Html.BeginForm. Instead, he had manually added a <form> tag, which in turn never created the ViewContext.FormContext object.
If you want to see for yourself, go download the latest MVC 3 sources from the ASP.Net site on CodePlex.
In my opinion, this is totally ridiculous. And I guess the devs over at Microsoft agree because they are removing this requirement in MVC 4.
Here are Brad’s own words:
Important note: jQuery Validate requires your input elements to be inside of a <form> element in order to be validated. In addition, MVC 3 requires that you have called Html.BeginForm() to render this form, so that it can find its book-keeping object to help render the HTML attributes. Starting with MVC 4, we’ve eliminated the need for Html.BeginForm(), but the requirement for the HTML <form> element is still there.