ASP.NET MVC Client Side Validation With Dynamic Contents
Introduction:
There are lot of occasions when developers do not let the users to fill the complete form at once, instead developers use wizards steps to get the different information from users at different steps. For example, ASP.NET(Web Form) Wizard Control which allows the developers to easily create multi step user interface. But unlike traditional post back for every step, developers likes to use Ajax to show different wizards steps without a complete post back. Every wizard step includes different client side validation rules. In this article I will show you how to do the same task in ASP.NET MVC using the built-in client side validation libraries.
Description:
Let's create a sample application to allow the users to register them using two steps Ajax wizard form. In the first step users will fill thier own information and in second step user will fill their company information and third step just shows a Thank You message. First of all create a ASP.NET MVC application. Then just open HomeController.cs and add the following code,
public ActionResult CreateUser() { return View(); } [HttpPost] public ActionResult CreateUserPrevious(UserInformation u) { return View("CreateUserInformation", u); } [HttpPost] public ActionResult CreateUserInformation(UserInformation u) { if(ModelState.IsValid) return View("CreateUserCompanyInformation"); return View("CreateUserInformation"); } [HttpPost] public ActionResult CreateUserCompanyInformation(UserCompanyInformation uc, UserInformation ui) { if (ModelState.IsValid) return Content("Thank you for submitting your information"); return View("CreateUserCompanyInformation"); }
Next create a CreateUser view and add the following lines,
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ClientSideValidationWithDynamicContent.Models.UserInformation>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> CreateUser </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <div id="dynamicData"> <%Html.RenderPartial("CreateUserInformation"); %> </div> </asp:Content>
Next create a CreateUserInformation partial view and add the following lines,
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ClientSideValidationWithDynamicContent.Models.UserInformation>" %> <% Html.EnableClientValidation(); %> <%using (Html.BeginForm("CreateUserInformation", "Home")) { %> <table id="table1"> <tr style="background-color:#E8EEF4;font-weight:bold"> <td colspan="3" align="center"> User Information </td> </tr> <tr> <td> First Name </td> <td> <%=Html.TextBoxFor(a => a.FirstName)%> </td> <td> <%=Html.ValidationMessageFor(a => a.FirstName)%> </td> </tr> <tr> <td> Last Name </td> <td> <%=Html.TextBoxFor(a => a.LastName)%> </td> <td> <%=Html.ValidationMessageFor(a => a.LastName)%> </td> </tr> <tr> <td> Email </td> <td> <%=Html.TextBoxFor(a => a.Email)%> </td> <td> <%=Html.ValidationMessageFor(a => a.Email)%> </td> </tr> <tr> <td colspan="3" align="center"> <input type="submit" name="userInformation" value="Next"/> </td> </tr> </table> <%} %> <script type="text/javascript"> Sys.Mvc.FormContext._Application_Load(); $("#form0").submit(function (e) { if (!Sys.Mvc.FormContext.getValidationForForm(this).validate('submit').length) { $.post("/Home/CreateUserInformation",$(this).serialize(), function (data) { $("#dynamicData").html(data); }); } e.preventDefault(); }); </script>
Next create a CreateUserCompanyInformation partial view and add the following lines,
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl <ClientSideValidationWithDynamicContent.Models.UserCompanyInformation>" %> <% Html.EnableClientValidation(); %> <%using (Html.BeginForm("CreateUserCompanyInformation", "Home")) { %> <table id="table1"> <tr style="background-color:#E8EEF4;font-weight:bold"> <td colspan="3" align="center"> User Company Information </td> </tr> <tr> <td> Company Name </td> <td> <%=Html.TextBoxFor(a => a.CompanyName)%> </td> <td> <%=Html.ValidationMessageFor(a => a.CompanyName)%> </td> </tr> <tr> <td> Company Address </td> <td> <%=Html.TextBoxFor(a => a.CompanyAddress)%> </td> <td> <%=Html.ValidationMessageFor(a => a.CompanyAddress)%> </td> </tr> <tr> <td> Designation </td> <td> <%=Html.TextBoxFor(a => a.Designation)%> </td> <td> <%=Html.ValidationMessageFor(a => a.Designation)%> </td> </tr> <tr> <td colspan="3" align="center"> <input type="button" id="prevButton" value="Previous"/> <input type="submit" name="userCompanyInformation" value="Next"/> <%=Html.Hidden("FirstName")%> <%=Html.Hidden("LastName")%> <%=Html.Hidden("Email")%> </td> </tr> </table> <%} %> <script type="text/javascript"> Sys.Mvc.FormContext._Application_Load(); $("#prevButton").click(function () { $.post("/Home/CreateUserPrevious", $("#form0").serialize(), function (data) { $("#dynamicData").html(data); }); }); $("#form0").submit(function (e) { if (!Sys.Mvc.FormContext.getValidationForForm(this).validate('submit').length) { $.post("/Home/CreateUserCompanyInformation", $(this).serialize(), function (data) { $("#dynamicData").html(data); }); } e.preventDefault(); }); </script>
Next create a new class file UserInformation.cs inside Model folder and add the following code,
public class UserInformation { public int Id { get; set; } [Required(ErrorMessage = "First Name is required")] [StringLength(10, ErrorMessage = "First Name max length is 10")] public string FirstName { get; set; } [Required(ErrorMessage = "Last Name is required")] [StringLength(10, ErrorMessage = "Last Name max length is 10")] public string LastName { get; set; } [Required(ErrorMessage = "Email is required")] [RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Email Format is wrong")] public string Email { get; set; } }
Next create a new class file UserCompanyInformation.cs inside Model folder and add the following code,
public class UserCompanyInformation { public int UserId { get; set; } [Required(ErrorMessage = "Company Name is required")] [StringLength(10, ErrorMessage = "Company Name max length is 10")] public string CompanyName { get; set; } [Required(ErrorMessage = "CompanyAddress is required")] [StringLength(50, ErrorMessage = "Company Address max length is 50")] public string CompanyAddress { get; set; } [Required(ErrorMessage = "Designation is required")] [StringLength(50, ErrorMessage = "Designation max length is 10")] public string Designation { get; set; } }
Next add the necessary script files in Site.Master,
<script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcValidation.debug.js" type="text/javascript"></script>
Now run the application and navigate to Home/CreateUser, you will find the following screen,
Just fill the user information form and click Next, you will find the following screen,
Just fill the user company information form and click Next, you will find the following screen,
Now just see what makes the client side validation possible with dynamic contents. First of all note that ASP.NET MVC will emits client side validation script only if you have Html.EnableClientValidation() (which internally sets ViewContext.ClientValidationEnabled = true) inside your view or partial view. Client side validation for dynamic contents will still not work unless you call Sys.Mvc.FormContext._Application_Load() function(which simply do some initialization) in your dynamic contents(partial view).
Another very important point to note here is that dynamic contents includes a html form. This is necessary because ASP.NET MVC emits the validation script during MvcForm.Dispose method. Therefore if you do not have Html.BeginForm in your dynamic contents, no script will be emitted, due to which client side validation will not work.
Another key point to note here is that client side validation is explicitly invoking using, (!Sys.Mvc.FormContext.getValidationForForm(this).validate('submit').length). If the form is valid then I am just using jQuery.post to post the form to server asynchronously and get the dynamic contents and update the document. This is important to prevent the traditional postback because by default ASP.NET MVC client side validation library do a complete postback if the form is valid.
Summary:
Ajax wizards form are very popular way to get and validate the user information using wizard steps. ASP.NET MVC has no exception. In this article I shows you how you can very easily enable client side validation for dynamic contents. I am also attaching a sample application. Hopefully you will again enjoy this.