Unobtrusive Validation with MVC 3 and Html.BeginForm

Yesterday a colleague of mine and I were trying to find out why client side unobtrusive validation attributes were being generated everywhere EXCEPT one specific page on our upcoming release of WebCenter 6.  Client side validation attributes in MVC 3 are html 5 data-val-*attributes.   They enable you to tie your validation to Data Annotation attributes on your models without having to write a line of javascript code.  This is sweet in my book because the JavaScript is completely decoupled from the actual C# code.

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.

  1. When you render an input using an HtmlHelper like @Html.EditorFor, @Html.TextBox etc., they are rendered with the InputExtensions.InputHelper method.
  2. InputHelper calls HtmlHelper.GetUnobtrusiveValidationAttributes to render the data-val attributes.
  3. 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.
  4. GetFormContextForClientValidation will return the FormContext that was instantiated with @Html.BeginForm OR return null.
  5. 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.

2 thoughts on “Unobtrusive Validation with MVC 3 and Html.BeginForm

  1. Informative and helpful :) In our app we’re getting part of a form through an AJAX request, which leads to the partial view not having a FormContext. Would have taken a lot longer to figure this out if I hadn’t read your post. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>