ASP.NET MVC 3: Ajax Form with jQuery validate supporting (unobtrusive) Client Side Validation and Server Side Validation

Update 2011-08-07: I’ve written a new follow-up blog post to this one which shows how to upgrade the techniques described here with custom (jQuery) JavaScript code to implement a more flexible Ajax form handling.

This blog post shows step by step instructions how to build an Ajax form with jQuery validate supporting (unobtrusive) client and server side validation using ASP.NET MVC 3.

Summarized the (Ajax) form will have the following features:

  1. Client side validation: Before submitting the data to the server the client validates the data to reduces the number of requests and to improve usability.
  2. Server side validation: The server validates the data again to find malicious requests that bypasses client side validation and to perform additional validations that cannot be done on client side, e.g. validations that need database access.
  3. Partial page updates: If server side validation fails the error messages are injected in the DOM on the client side to avoid complete page reloads.

To follow the steps below you can start from a new (empty) ASP.NET MVC 3 Web Application with Razor support or you can download the Visual Studio 2010 project containing all the source code here.

To enable (unobtrusive) client side Ajax and validation support include the following JavaScript files (in Views/Shared/_Layout.cshtml):

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-1.4.4.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.validate.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")"></script>

and make sure, that ClientValidationEnabled and UnobtrusiveJavaScriptEnabled is enabled in your Web.config (which should be the default values):

<appSettings>
  <add key="ClientValidationEnabled" value="true"/>
  <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

Next, we create a Model (Models/ValidationModel.cs) which defines a property with some validation attributes:

public class ValidUserNameAttribue : ValidationAttribute
{
  public override bool IsValid(object value)
  {
    return (value != null && value.ToString() == "Bob");
  }
}
 
public class ValidationModel
{
  [Required]
  [StringLength(8, MinimumLength = 3)]
  [ValidUserNameAttribue(ErrorMessage = "User name != 'Bob'")]
  [Display(Name = "User Name")]
  public string UserName { get; set; }
}

The custom ValidUserNameAttribue adds a validation that is only performed on server side. In a real world example this attribute could for example query a database to ensure the user name is unique. In this example only “Bob” is accepted as a valid user name. Both other attributes (Required and StringLength) trigger validation on client and on server side.

The (minimalistic) HomeController defines two actions: Index to render the form and Form to validate the request and render the result.

public class HomeController : Controller
{
  [HttpGet]
  public ActionResult Index()
  {
    return View(new ValidationModel());
  }
 
  [HttpPost]
  public ActionResult Form(ValidationModel validationModel)
  {
    return PartialView(!ModelState.IsValid ? "Partial/_Form" : "Partial/_Success", validationModel);
  }
}

In a last step we need to define the views. As you can see in the HomeController‘s Form action we will use partial views for the form and the success message to enable the partial page updates on the client side.

Home/Index.cshtml:

@model MVC3_Ajax_Form_jQuery_Validation.Models.ValidationModel
 
@{
    ViewBag.Title = "ASP.NET MVC 3: Ajax Form with jQuery validate supporting Unobtrusive Client Validation and Server Side Validation";
}
 
@DateTime.Now: Index.cshtml rendered
<hr/>
 
<div id="FormContainer">
    @Html.Partial("Partial/_Form")
</div>

The Index view defines a <div> tag that is used as form container, i.e. it’s content is replaced with the server’s response. If the server side validation fails the server sends HTML code of the form containing server side validation error messages, otherwise HTML code containing a success message.

Home/Partial/_Form.cshtml:

@model MVC3_Ajax_Form_jQuery_Validation.Models.ValidationModel
 
@DateTime.Now: Partial/_Form.cshtml rendered
<hr/>
 
@using (Ajax.BeginForm("Form", new AjaxOptions() { UpdateTargetId = "FormContainer" , OnSuccess = "$.validator.unobtrusive.parse('form');" }))
{
 
    <p>
        Error Message: @Html.ValidationMessageFor(m => m.UserName)
    </p>
 
    <p>
        @Html.LabelFor(m => m.UserName):
        @Html.EditorFor(m => m.UserName)
    </p>
 
    <input type="submit" value="Submit" />
}

The Partial/_Form.cshtml partial view defines the (Ajax) form. This partial view is included with @Html.Partial()in the Index view for the initial page load and used by the HomeController‘s Form action to render the form with server side validation messages.
It’s important to call $.validator.unobtrusive.parse(‘form’); in the OnSuccess callback to reinitialize the client side validation after the form container’s HTML content is replaced!

Home/Partial/_Success.cshtml:

@model MVC3_Ajax_Form_jQuery_Validation.Models.ValidationModel
 
User name '@Model.UserName' is valid :)

The Partial/_Success.cshtml partial view defines the success message that is used to replace the form after the request passes server side validation.

Both the view Home/Index.cshtml and Home/Partial/_Form.cshtml render the current time-stamp that shows that the partial page update is working: After submitting a user name unequals ‘Bob’ only form render time-stamp changes.

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