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.

16 Comments

  • Thanks Imran it is a valuable topic.

  • Thanks Imran,
    it was a great help. i wonder if we could achieve this using Ajax.Beginform
    regards

  • Thanks Imran for sharing, interesting implementation in MVC..

  • thanks Imran is very useful

  • This is a very useful article imran.
    Thanks

  • very good and helpful article, Imran keep it up

  • In the file: CreateUser.aspx, the line compiles perfectly during build-time, however, I'm getting an unhandled compiler excpetion at run time (CS1026, expecting a ')'). I've read up on the error, and none of this makes sense. The semicolon is in place at the end of the statement, there's no '=' at the beginning of the code block, etc. I even tried using Html.Partial (removing the ';' and adding the '=').

    Ideas anyone?

  • @billbris,
    Just Download the sample application. I think you have not created this partial.

  • Thanks imran... as it turns out I had a syntax error in the actual CreateUser partial that in turn caused the error in the RenderPartial call.

  • @billbris,
    Just download the code

  • Hi,

    I need to add a validation that will use the database. Will be like a validation if this e-mail exists. How will be the best way to do this? I thought to put this validation in controller, but I don't know how I could return a error when the email exists and show it in screen, Should I use ModelState.AddModelError or ViewData["Error"]?

    Thank you for article, It had helped me a lot.

  • @Michel,
    See http://bradwilson.typepad.com/blog/2010/01/remote-validation-with-aspnet-mvc-2.html

  • Hi Imran,
    Nice article, thanks for the guidelines.

    I have a similar situation but my case is a little different. Different in the way I have Html.EnableClientValidation() and BeginForm() calls on my main view and not in my partial controls and my AJAX call is updating my Partial view and with that I do not get the validation messages back after the AJAX call.

    Just to explain why I have this scenario, in my View I have to use the same partial control multiple times. One of my partial control is used 2 times and the other which is for Address is used 4 times. And with AJAX calls I need to update each of these partial views separately.

    Could you please shade some light on what do I need to do?

    Thanks in advance!
    Chitrang

  • Asp net mvc client side validation with dynamic contents.. I like it :)

  • Thanx Imran. Great job!

  • This is a nice article. This is needed in most of the applications.

Comments have been disabled for this content.