ASP.NET MVC Client Side Validation With Ajax.BeginForm

     Introduction:

          The ASP.NET MVC Ajax.BeginForm HTML helper make it very easy to submit form asynchronously and allows to perform partial page updates. That's why lot of developers likes to use Ajax.BeginForm HTML helper. In my last blog post I talked about how you can implement client-side validation for dynamic contents at here. I showed you that how you can leverage jQuery to make it possible. This will work very well if you want to use only jQuery. But what if you want to use Ajax.BeginForm Helper? So in this article I will show you how you can implement client-side validation for dynamic contents using Ajax.BeginForm.

    Description:

          Here I will continue to use the last example which was presented at here with some changes. First of all add the following code in HomeController.cs.

 

        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 View("ThankYou");
            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">
        <% Html.EnableClientValidation();%>
        <%using (Ajax.BeginForm("CreateUserInformation", new AjaxOptions { OnComplete = "CompleteFunction" }))
          { %>
            <%Html.RenderPartial("CreateUserInformation"); %>
        <%} %>
        <script type="text/javascript">
            function CompleteFunction(ajaxContext) {
                $("#form0")[0].validationCallbacks = [];
                $clearHandlers($("#form0")[0]);
                var newDiv = document.createElement("div");
                $(newDiv).html(ajaxContext.get_data());                
                var forms = newDiv.getElementsByTagName("form");
                $("#form0").html(forms[0].innerHTML);
                $("#form0")[0].action = forms[0].action;                
                Sys.Mvc.FormContext._Application_Load();                
                return false;
            }
        </script>
</asp:Content>

          Next create a CreateUserInformation partial view and add the following lines,

 

    <%@ Control Language="C#" 

Inherits="System.Web.Mvc.ViewUserControl<ClientSideValidationWithDynamicContent.Models.UserInformation>" %>

<%if (ViewContext.HttpContext.Request.IsAjaxRequest())
  {
      Html.EnableClientValidation();
      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>
  <%if (ViewContext.HttpContext.Request.IsAjaxRequest())
           Html.EndForm(); 
  %>
    

          Next create a CreateUserCompanyInformation partial view and add the following lines, 

 

    <%@ Control Language="C#" 

Inherits="System.Web.Mvc.ViewUserControl<ClientSideValidationWithDynamicContent.Models.UserCompanyInformation>" %>
<%if (ViewContext.HttpContext.Request.IsAjaxRequest())
  {
      Html.EnableClientValidation();
      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" name="prevButton" 

onclick="$.post('/Home/CreateUserPrevious',$(this.form).serialize(),function(data){var ajaxcon=new 

Sys.Mvc.AjaxContext();ajaxcon.get_data=function(){return data};CompleteFunction(ajaxcon);});" id="prevButton" 

value="Previous"/>                  
                <input type="submit" name="userCompanyInformation" value="Next"/>
                <%=Html.Hidden("FirstName")%>
                <%=Html.Hidden("LastName")%>
                <%=Html.Hidden("Email")%>
            </td>
        </tr>
        </table>
<%if (ViewContext.HttpContext.Request.IsAjaxRequest())
           Html.EndForm(); 
  %>

          Next create a ThankYou partial view and add the following lines, 

 

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%if (ViewContext.HttpContext.Request.IsAjaxRequest())
  {
      Html.EnableClientValidation();
      Html.BeginForm();
  }%>
Thank you for submitting your information
<%if (ViewContext.HttpContext.Request.IsAjaxRequest())
           Html.EndForm(); 
%>

          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 let's see what the above code is doing? First of all, note that here i am using the same model classes with same validation rules used in last article. All the controller actions code is also same except one step(which returns View("ThankYou") instead of  Content).

          The big idea is to note here is that every partial view contains the following extra lines,

 

    <%if (ViewContext.HttpContext.Request.IsAjaxRequest())
  {
      Html.EnableClientValidation();
      Html.BeginForm("....","...");
  }%>


  ...............................................
  ...............................................
  ...............................................
  ...............................................


  <%if (ViewContext.HttpContext.Request.IsAjaxRequest())
           Html.EndForm(); 
  %>

           These lines of code(Html.BeginForm method) are necessary to let the ASP.NET MVC to emit the validation scripts during partial post back. Inside Html.BeginForm method, action and controller parameters are also set so that next time Ajax.BeginForm will post the form to this new action.

            Inside CreateUser view, I am handling OnComplete event of Ajax.BeginForm method. Inside this event, previous handlers and callbacks are cleared so that no memory leakage happens. Then just replace the current page form contents with the new form contents which was received by submitting the asynchronous form. Here the current form action is also replaced with new form action so that Ajax.BeginForm will post the form to new action. Finally just call Sys.Mvc.FormContext._Application_Load method so that ASP.NET MVC initialize the new validation rules.

             Another interesting point worth to discuss here is that Previous button uses jQuery.post method to send a request to an action and then this action response is used to create AjaxContext object and pass this AjaxContext object to OnComplete event function. This allows you to bypass the client side validation.

    Summary:

          In this article, I discuss how to enable client side validation for dynamic contents which you get from using Ajax.BeginForm. The example in this article will helps you to enable the client side validation for dynamic contents with Ajax.BeginForm very easily. Just download the sample application and run the application and check it out. I hope you will enjoy this article too.

 

Published Sunday, July 18, 2010 3:20 PM by imran_ku07

Comments

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Thursday, August 5, 2010 5:32 AM by tassadaque

Thanks imran for showing how validation would work with ajax.Beginform. This is indeed cleanest way of creating wizard that i have seen so for.

but most of the times when we post form through ajax we save the record in db and also render it on page in some format. in this condition when u can have form success and form failure. in case of form success u need to bring in data from db and update "data-div" and in case of form failure, u have to bring back form with error messages and render it in "form-div". can we achieve this behavior in .NET mvc.

regards

Adeel

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Thursday, August 5, 2010 7:31 AM by imran_ku07

@tassadaque if you look clearly in the sample you will find I am sending conditional view by checking ModelState.IsValid

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Friday, August 6, 2010 1:23 AM by tassadaque

@imran

yes u r checking modelstate.isValid and sending content based on condition but in either case the returned html is being rendered in same target. what i have is one <div id="form"> for form and one <div id="data"> for <table> that renders some data. i have to update <div id="data"> if form is valid and values are persisted. on the other hand if form fails i have to update <div id="form">. i hope i m more clear this time :)

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Wednesday, August 11, 2010 12:31 AM by tassadaque

Thanks imran i think it should do the trick. thanks for all of ur answers. they did me a great help.

regards

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Friday, November 5, 2010 12:17 AM by ht

Thanks imran.

I run the MVC Client Side Validation With Ajax.BeginForm in VS.net 2010, it's well done, but when I tested it in VS.net 2008, it ran in firefox, but in IE7, it did not response when i press Next button. I found that there's a problem with $("#form0").submit(function (e), Sys.Mvc.FormContext.getValidationForForm(this) is undefined. How to solve the problem if I deploy it in VS.NET2008.

# re: ASP.NET MVC Client Side Validation With Ajax.BeginForm

Friday, November 5, 2010 2:03 AM by imran_ku07

@ht,

Client side code is not dependent on the version of Visual Studio. Just make sure correct version of script files are referenced.