ASP.NET MVC 3: Using JSON result for jQuery Ajax Forms validation

This blog post is my third blog post about jQuery Ajax forms with ASP.NET MVC 3.

This third post shows how to customize the way the validation result is handled on the client side. The first post about jQuery Ajax forms with ASP.NET MVC 3 describes how to use partial page updates to avoid complete page reloads after submitting the form. In detail, the server validates the (form) data and returns HTML that either contains the form including server side errors or a success message and on the client side this HTML code is used to replace the old form with. Using this technique there is no way to customize the handling of the success message; for example it could be desirable to show the success message in a popup instead of replacing the form.

To make this flexibility possible the server’s response is changed from (pure) HTML code to a JSON array containing to values:

  1. A boolean that indicates whether the server side validation was successful
  2. A string that contains (depending of the validation result) the HTML code of the form with server side errors or the success message

To enable the server to create a JSON array containing the (rendered) HTML code of a view we will use the extension method RenderPartialViewToString() that I’ve described here.

We start with the source code of the second post and change the HomeController‘s Form action to look like this:

[HttpPost]
public ActionResult Form(ValidationModel validationModel)
{
  Thread.Sleep(2000); // Fake processing time
  if (!ModelState.IsValid)
  {
    return Json(new object[] {false, this.RenderPartialViewToString("Partial/_Form", validationModel)});
  }
  return Json(new object[] {true, this.RenderPartialViewToString("Partial/_Success", validationModel)});
}

On the client side we add a new “success dialog”

<div id="SuccessDialog" style="text-align: center; padding: 50px;">
    <div id="SuccessContainer"></div>
</div>

and some jQuery JavaScript that initializes this dialog:

// Initialize success dialog ...
$("#SuccessDialog").dialog({
  autoOpen: false,
  draggable: false,
  modal: true,
  resizable: false,
  title: "Success",
  buttons: [
    {
      text: "Continue",
      click: function () { $(this).dialog("close"); }
    },
    {
      text: "Reload",
      click: function () { location.reload(); }
    }
  ]
});

In this example we add two buttons to the dialog, one for closing the dialog and continuing editing and one to reload the page.

In a last step we adapt the success handler of the jQuery Ajax post to process the JSON array returned by the server:

success: function (data) {
  if (data[0]) {
    $("#SuccessContainer").html(data[1]);
    $("#SuccessDialog").dialog("open");
   } else {
     $("#FormContainer").html(data[1]);
     $.validator.unobtrusive.parse("form");
   }
}

You can download the Visual Studio 2010 project containing all the source code here.

Summarized all three blog posts have shown how to build Ajax’s forms with ASP.NET MVC 3 supporting client side and server side validation, partial page update and a customizable way how to send data to the server and how to handle the server’s response on the client side.

Comments

  1. Joseph Sturtevant

    I cannot get the client-side aspect of your example to work in IE8. Do you know how to fix this? I thought it might be a library version issue, but even the latest versions do not seem to work.

  2. Jan Jonas

    Hi Joseph, thanks for your comment. IMHO, the example you can download here should work in IE8.
    Do you get any JavaScript error? Have you also tried the examples source code from part 1 or part 2 of my posts about jQuery Ajax forms with ASP.NET MVC 3?

  3. Joseph Sturtevant

    I think I fixed my IE8 issue. It appears to be that on IE8 the client side validation is not able to preempt the form submit event handler. The solution I’m using is to insert ‘if (!form.valid()) return;’ immediately after ‘var form = $(this);’ in the event handler. This seems to be working so far. If anyone has any additional insight or a better solution, I would love to know what it is.

  4. Jan Jonas

    Hi Joseph,
    sorry for the delay in my response. I see the problem in IE8. I think, the reason is that in IE8 the submit handler that is registered using jQuery live is triggered before the validation has been performed (see http://forum.jquery.com/topic/jquery-validate-live-submit-firing-before-validation-in-ie). Using

    $("form").live("submit", function (event) {
      event.preventDefault();
      var form = $(this);
      if (!form.valid()) return;
      [...]

    as you have suggested seems to fix the problem.

  5. Leroy

    Hi Joseph,

    Great blob series, that took ,e far down the path of JQuery!

    Just a quick note – when I implemented this structure, I found that it looked like my PartialView was being cached.

    After many hours of searching, I found that this is actually based on the way that HtmlHelpers use ModelState, and so to prevent the behaviour I added

    ModelState.Clear() before reconstructing the PartialView.

    Hope this helps your readers,

    All the best,

    Leroy.

  6. Brent

    These posts are helpful. One additional question: do you know whether a form added to the page after initial load (e.g., via some AJAX call) would require additional processing to “ajaxify” it? I’m having a curious issue where I can use such forms in the modern browsers (IE9, Chrome, Firefox), but not IE8. IE8 just posts the form contents, instead of submitting them via XHR. However, IE8 works properly if the form is loaded first along with the rest of the page. I’m guessing I need to tell AJAX-loaded forms to do something, but I’m not sure what.

  7. Jan Jonas

    Hi Brent,
    Have you seen Joseph’s and my comments about possible IE8 problems? The “ajaxify”-part is described in detail in my blog post ASP.NET MVC 3: Using jQuery .ajax() function to submit Ajax Form supporting (unobtrusive) Client Side Validation and Server Side Validation. Basically, the trick is to register your own submit handler, which could be done by using jQuery’s live functionality (as you can see in my examples).

Leave a comment

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

*