MVC3 Ajax partial view validation

by trouf on 5/05/2011

Ran into a wall of trouble after getting Ajax to work properly in my previous post. Turns out that validation rules are not applied to partial views loaded with Ajax (Even when using the provided Ajax.ActionLink helper).

Thanks to this excellent blogpost http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ i managed to work it out. But not until after bashing my head against the wall until numb.

The main problem was not so much the actual validation scripts, it was pretty clear to me that the validation rules would have to be rebuilt after injecting new objects into the DOM, but the fact that MVC refused to acually render the data-val / data-val-required properties for the elements that needed validating.

@using (Html.BeginForm("Create", "MyModel", FormMethod.Post, new { id = "CreateForm" }))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>MyModel</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Property)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Property)
            @Html.ValidationMessageFor(model => model.Property)
        </div>
     </fieldset>
}
view raw beginform.cs This Gist brought to you by GitHub.

These properties are usually rendered by Html.EditorFor / ValidationMessageFor when used as in the example above.

This is how it should look:

<input class="text-box single-line"
       data-val="true"
       data-val-required="This field is required!"
       id="Property"
       name="Property"
       type="text"
       value=""
/>
view raw proper.html This Gist brought to you by GitHub.

But when including a partial view through Ajax inside this outer form, the ability to use BeginForm inside that partial view is lost due to the fact that we can not have nested forms. And without BeginForm, no data-val properties :(

The key to getting the partial view to render the properties was to wrap the contents like the following code snippet:

@using(new MvcForm(ViewContext))
{
    <div class="editor-label">
        @Html.LabelFor(model => model.Property)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Property)
        @Html.ValidationMessageFor(model => model.Property)
    </div>

}
view raw partial.cs This Gist brought to you by GitHub.

And then to get the validation going, call xhalent’s brilliant js-function after appending the results of the Ajax request to the DOM.

$('#ajaxstuff').ajaxLink({
  data: {},
  success: function (data) {
    $('#ajaxdiv').append(data);
    $.validator.unobtrusive.parseDynamicContent('form');
  }
});
view raw js.js This Gist brought to you by GitHub.

stefan.pataky@gmail.com

There are 8 comments in this article:

  1. 13/05/2011SteveiG says:

    Thanks for this, saved me lots of time !!!

  2. 23/05/2011knut says:

    hey thank you very much! you saved us a lot of time :) why not install a flattr button? i’d donate! cheers from switzerland.

  3. 22/07/2011Sean says:

    Bingo. Exactly what I needed. Much appreciated.

  4. 26/08/2011aldwinb says:

    you, sir, are awesome. i’ve been searching for this for quite some time now. kudos!

  5. 16/11/2011Tom says:

    Hi, very nice post, helped me out in a tricky situation. Have one question though:

    When the using (new MvcForm … goes out it calls Dispose, which will write a tag.

    Is there any trick to make it not do that, or do I have to create my own class (inheriting MvcForm and override Dispose?

    ///. Tom

  6. 16/11/2011Amr Ellafy says:

    well done ! huge help for me!!

  7. 18/11/2011trouf says:

    Well, since ”using” expects an IDisposable it is pretty much inevitable that Dispose will be called when leaving the scope. I would try your suggestion :)

  8. 22/11/2011lanka says:

    Thanks for the solution. saved my day :D

Write a comment: