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.

Published Sunday, July 11, 2010 8:40 AM by imran_ku07

Comments

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Tuesday, July 13, 2010 8:22 AM by Mazeno0o

Thanks Imran it is a valuable topic.

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Wednesday, July 14, 2010 2:40 AM by tassadaque

Thanks Imran,

it was a great help. i wonder if we could achieve this using Ajax.Beginform

regards

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Saturday, August 7, 2010 9:05 AM by Mujeeb Hassan

Thanks Imran for sharing, interesting implementation in MVC..

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Sunday, August 8, 2010 6:20 PM by Moksha

thanks Imran is very useful

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Monday, August 9, 2010 7:16 AM by frazms

This is a very useful article imran.

Thanks

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Tuesday, August 10, 2010 9:44 AM by Suhail Ahmed

very good and helpful article, Imran keep it up

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Thursday, August 19, 2010 3:07 PM by billbris

In the file: CreateUser.aspx, the line <% Html.RenderPartial("CreateUser"); %> 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?

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Thursday, August 19, 2010 7:42 PM by imran_ku07

@billbris,

Just Download the sample application. I think you have not created this partial.

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Thursday, August 26, 2010 6:10 PM by billbris

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.

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Thursday, August 26, 2010 7:25 PM by imran_ku07

@billbris,

Just download the code

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Sunday, March 13, 2011 9:05 AM by Michel

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.

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Monday, March 14, 2011 9:28 AM by imran_ku07

@Michel,

See bradwilson.typepad.com/.../remote-validation-with-aspnet-mvc-2.html

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Tuesday, May 17, 2011 8:16 PM by chitranggolvelker

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

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Sunday, May 22, 2011 12:47 PM by weblogs.asp.net

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

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Tuesday, November 15, 2011 5:19 AM by Hanz

Thanx Imran. Great job!

# re: ASP.NET MVC Client Side Validation With Dynamic Contents

Thursday, June 14, 2012 2:05 AM by Gurpreet

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