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,
01 |
public
ActionResult CreateUser()
|
02 |
{
|
03 |
return
View();
|
04 |
}
|
05 |
[HttpPost]
|
06 |
public
ActionResult
CreateUserPrevious(UserInformation u)
|
07 |
{
|
08 |
return
View("CreateUserInformation", u);
|
09 |
}
|
10 |
[HttpPost]
|
11 |
public
ActionResult
CreateUserInformation(UserInformation u)
|
12 |
{
|
13 |
if(ModelState.IsValid)
|
14 |
return
View("CreateUserCompanyInformation");
|
15 |
return
View("CreateUserInformation");
|
16 |
}
|
17 |
18 |
[HttpPost]
|
19 |
public
ActionResult
CreateUserCompanyInformation(UserCompanyInformation
uc, UserInformation ui)
|
20 |
{
|
21 |
if
(ModelState.IsValid)
|
22 |
return
Content("Thank you for submitting your
information");
|
23 |
return
View("CreateUserCompanyInformation");
|
24 |
}
|
Next create a CreateUser view and add the following lines,
01 |
<%@ Page Title="" Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<ClientSideValidationWithDynamicContent.Models.UserInformation>" %>
|
02 |
03 |
<asp:Content
ID="Content1"
ContentPlaceHolderID="TitleContent"
runat="server">
|
04 |
CreateUser
|
05 |
</asp:Content>
|
06 |
07 |
<asp:Content
ID="Content2"
ContentPlaceHolderID="MainContent"
runat="server">
|
08 |
<div
id="dynamicData">
|
09 |
<%Html.RenderPartial("CreateUserInformation");
%>
|
10 |
</div>
|
11 |
</asp:Content>
|
Next create a CreateUserInformation partial view and add the following lines,
01 |
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<ClientSideValidationWithDynamicContent.Models.UserInformation>" %>
|
02 |
03 |
<% Html.EnableClientValidation();
%>
|
04 |
<%using
(Html.BeginForm("CreateUserInformation",
"Home"))
|
05 |
{ %>
|
06 |
<table
id="table1">
|
07 |
<tr
style="background-color:#E8EEF4;font-weight:bold">
|
08 |
<td
colspan="3"
align="center">
|
09 |
User Information
|
10 |
</td>
|
11 |
</tr>
|
12 |
<tr>
|
13 |
<td>
|
14 |
First Name
|
15 |
</td>
|
16 |
<td>
|
17 |
<%=Html.TextBoxFor(a =>
a.FirstName)%>
|
18 |
</td>
|
19 |
<td>
|
20 |
<%=Html.ValidationMessageFor(a =>
a.FirstName)%>
|
21 |
</td>
|
22 |
</tr>
|
23 |
<tr>
|
24 |
<td>
|
25 |
Last Name
|
26 |
</td>
|
27 |
<td>
|
28 |
<%=Html.TextBoxFor(a =>
a.LastName)%>
|
29 |
</td>
|
30 |
<td>
|
31 |
<%=Html.ValidationMessageFor(a =>
a.LastName)%>
|
32 |
</td>
|
33 |
</tr>
|
34 |
<tr> <td>
|
35 |
Email
|
36 |
</td>
|
37 |
<td>
|
38 |
<%=Html.TextBoxFor(a =>
a.Email)%>
|
39 |
</td>
|
40 |
<td>
|
41 |
<%=Html.ValidationMessageFor(a =>
a.Email)%>
|
42 |
</td>
|
43 |
</tr>
|
44 |
|
45 |
<tr>
|
46 |
<td
colspan="3"
align="center">
|
47 |
<input
type="submit"
name="userInformation"
value="Next"/>
|
48 |
</td>
|
49 |
</tr>
|
50 |
</table>
|
51 |
<%} %>
|
52 |
<script
type="text/javascript">
|
53 |
Sys.Mvc.FormContext._Application_Load();
|
54 |
$("#form0").submit(function (e) {
|
55 |
if
(!Sys.Mvc.FormContext.getValidationForForm(this).validate('submit').length)
{
|
56 |
$.post("/Home/CreateUserInformation",$(this).serialize(),
function (data) {
|
57 |
$("#dynamicData").html(data);
|
58 |
});
|
59 |
}
|
60 |
e.preventDefault();
|
61 |
});
|
62 |
</script>
|
Next create a CreateUserCompanyInformation partial view and add the following lines,
01 |
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl
<ClientSideValidationWithDynamicContent.Models.UserCompanyInformation>" %>
|
02 |
03 |
<% Html.EnableClientValidation(); %>
|
04 |
<%using
(Html.BeginForm("CreateUserCompanyInformation",
"Home"))
|
05 |
{ %>
|
06 |
<table
id="table1">
|
07 |
<tr
style="background-color:#E8EEF4;font-weight:bold">
|
08 |
<td
colspan="3"
align="center">
|
09 |
User Company Information
|
10 |
</td>
|
11 |
</tr>
|
12 |
<tr>
|
13 |
<td>
|
14 |
Company Name
|
15 |
</td>
|
16 |
<td>
|
17 |
<%=Html.TextBoxFor(a =>
a.CompanyName)%>
|
18 |
</td>
|
19 |
<td>
|
20 |
<%=Html.ValidationMessageFor(a =>
a.CompanyName)%>
|
21 |
</td>
|
22 |
</tr>
|
23 |
<tr>
|
24 |
<td>
|
25 |
Company Address
|
26 |
</td>
|
27 |
<td>
|
28 |
<%=Html.TextBoxFor(a =>
a.CompanyAddress)%>
|
29 |
</td>
|
30 |
<td>
|
31 |
<%=Html.ValidationMessageFor(a =>
a.CompanyAddress)%>
|
32 |
</td>
|
33 |
</tr>
|
34 |
<tr>
|
35 |
<td>
|
36 |
Designation
|
37 |
</td>
|
38 |
<td>
|
39 |
<%=Html.TextBoxFor(a =>
a.Designation)%>
|
40 |
</td>
|
41 |
<td>
|
42 |
<%=Html.ValidationMessageFor(a =>
a.Designation)%>
|
43 |
</td>
|
44 |
</tr>
|
45 |
|
46 |
<tr>
|
47 |
<td
colspan="3"
align="center">
|
48 |
<input
type="button"
id="prevButton"
value="Previous"/>
|
49 |
<input
type="submit"
name="userCompanyInformation"
value="Next"/>
|
50 |
<%=Html.Hidden("FirstName")%>
|
51 |
<%=Html.Hidden("LastName")%>
|
52 |
<%=Html.Hidden("Email")%>
|
53 |
</td>
|
54 |
</tr>
|
55 |
</table>
|
56 |
<%} %>
|
57 |
<script
type="text/javascript">
|
58 |
Sys.Mvc.FormContext._Application_Load();
|
59 |
$("#prevButton").click(function () {
|
60 |
$.post("/Home/CreateUserPrevious",
$("#form0").serialize(), function (data)
{
|
61 |
$("#dynamicData").html(data);
|
62 |
});
|
63 |
});
|
64 |
$("#form0").submit(function (e) {
|
65 |
if
(!Sys.Mvc.FormContext.getValidationForForm(this).validate('submit').length)
{
|
66 |
$.post("/Home/CreateUserCompanyInformation",
$(this).serialize(), function (data) {
|
67 |
$("#dynamicData").html(data);
|
68 |
});
|
69 |
}
|
70 |
e.preventDefault();
|
71 |
});
|
72 |
</script>
|
Next create a new class file UserInformation.cs inside Model folder and add the following code,
01 |
public
class
UserInformation
|
02 |
{
|
03 |
public
int
Id { get; set; }
|
04 |
05 |
[Required(ErrorMessage = "First Name is required")]
|
06 |
[StringLength(10, ErrorMessage = "First Name max length is 10")]
|
07 |
public
string
FirstName { get; set; }
|
08 |
09 |
[Required(ErrorMessage = "Last Name is required")]
|
10 |
[StringLength(10, ErrorMessage = "Last Name max length is 10")]
|
11 |
public
string
LastName { get; set; }
|
12 |
13 |
[Required(ErrorMessage = "Email is required")]
|
14 |
[RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Email Format is wrong")]
|
15 |
public
string
Email { get; set; }
|
16 |
}
|
Next create a new class file UserCompanyInformation.cs inside Model folder and add the following code,
01 |
public
class
UserCompanyInformation
|
02 |
{
|
03 |
public
int
UserId { get; set; }
|
04 |
05 |
[Required(ErrorMessage = "Company Name is required")]
|
06 |
[StringLength(10, ErrorMessage = "Company Name max length is 10")]
|
07 |
public
string
CompanyName { get; set; }
|
08 |
09 |
[Required(ErrorMessage = "CompanyAddress is required")]
|
10 |
[StringLength(50, ErrorMessage = "Company Address max length is 50")]
|
11 |
public
string
CompanyAddress { get; set; }
|
12 |
13 |
[Required(ErrorMessage = "Designation is required")]
|
14 |
[StringLength(50, ErrorMessage = "Designation max length is 10")]
|
15 |
public
string
Designation { get; set; }
|
16 |
}
|
Next add the necessary script files in Site.Master,
1 |
<script
src="../../Scripts/jquery-1.4.1.js"
type="text/javascript"></script>
|
2 |
<script
src="../../Scripts/MicrosoftAjax.js"
type="text/javascript"></script>
|
3 |
<script
src="../../Scripts/MicrosoftMvcAjax.js"
type="text/javascript"></script>
|
4 |
<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.