Validations In MVC Part 4

Vasanthmvp
Posted by in ASP.NET MVC category on for Beginner level | Points: 250 | Views : 9092 red flag
Rating: 4 out of 5  
 2 vote(s)

In this article we will try to understand how to implement server side validation, client side validation logic to the Model class in ASP.NET MVC.

Introduction


In this article we will try to understand how to implement server side validation, client side validation logic to the Model class in ASP.NET MVC.


Description


MVC Overview:

          The ASP.NET MVC framework is an application pattern that provides an alternative to the ASP.NET Web forms for creating web applications.  A basic introduction to ASP.NET MVC and its features were discussed in the first two articles - http://www.dotnetfunda.com/articles/article2092-introduction-to-aspnet-mvc-csharp-part-1.aspx.

http://www.dotnetfunda.com/articles/article2100-mvc-application-structure-components-functionality-with-an-example-pa.aspx

http://www.dotnetfunda.com/articles/article2135-aspnet-mvc-in-action-with-a-sample-application-part-3.aspx

Validations are necessary in any application to prevent an exception prone data or wrong data be entered. Validations can be applied at both client levels as well on server side level. In MVC application, Validations are typically applied at Model level rather than at the User Interface level. Here, we will see that once the validation rules are enforced these are applicable in all the modes where our Model is used. We call this as DRY (Don’t Repeat Yourself) in MVC.

One of the core tenets of MVC is DRY. It encourages us to write the code only once and it should be reflected everywhere at the application. The Validation support provided by MVC is an example of DRY. In ASP.NET MVC, validations are implemented by using DataAnnotations. MVC supports declarative validation rules defined with attributes from System.ComponentModel.DataAnnotations namespace.

We will prolong the discussion on our previously elaborated application from the earlier article Part 3.

To apply required validation rules on GuestResponse model class, while declaring properties we include the namespace as shown below:

Using System.ComponentModel.DataAnnotations

namespace PartyInvites.Models
{
public class GuestResponse {
          [Required(ErrorMessage=”Please enter your name”)]
          public string Name { get; set; }
          [Required(ErrorMessage=”Please enter your email address”)]
          [RegularExpression(“.+\\@.+\\..+”, ErrorMessage=”Please enter a valid email address”)]
          (or) [Email]
          public string Email { get; set; }
          [Required(ErrorMessage=”Please enter your Phone Number”)]
          public string Phone { get; set; }
  [Required(ErrorMessage=”Please specify whether you’ll attend”)]
          Public bool? WillAttend { get; set; }
}
}

MVC detects the validation attributes and uses them to validate data during the process of model binding. The required attributes specifies that the corresponding property value is mandatory. In the above ex: Name is required, email is required, we observer that two rules are applied to Email property i.e., required and to check whether it is in a valid format. For a property we can apply as many attributes as we require. To enforce a rule that a invitee should give his Rsvp opinion we declared WillAttend as bool? datatype which accepts true, false, null and declared it as required.

We can also specify the property value as a datatype itself like:

[DataType(DataType.EmailAddress)]
[DataType(DataType.PhoneNumber)]
[DataType(DataType.Url)]

The System.ComponentModel.DataAnnotations assembly has many built in validation attributes like

Required – property value is mandatory (Customer Name is required)

Range – property value should be within the specified range (Credit Card CC Num – 3 to 4 digits, payment amount – 100 to 1,00,000)

Regular Expression – Property value should follow the regular expression patter as mentioned. (to check a valid email, url, etc.,)

StringLength – property value should be of specified length like 10 for Indian mobile Num, 6 for ZipCode in India (5 if other country)

The validation rules vary based up on our requirement.

We can check at the controller level, if there is any validation problem in the HttpPost method by using ModelState.IsValid property in the controller class.

[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse)
{
if(ModelState.IsValid) {
return View(“Thanks”, guestResponse);
}
Else {
return View();
}
}

If there are no validation errors then Model.IsValid is true and returns the Thanks View along with guestResponse for binding otherwise it returns RsvpForm view by calling the view method without any parameters. To show user the set of validation errors we make use of Html.ValidationSummary helper method in the view.

<!Doctype html>
<html>
<head> <title> Rsvp Form </title> </head>
<body>
      @Using (Html.BeginForm()) {
@Html.ValidationSummary()
           <p> Your Name: @Html.TextBoxFor( x => x.Name) </p>
           <p> Your Email: @Html.TextBoxFor( x => x.Email) </p>
           <p> Your phone: @Html.TextBoxFor( x => x.Phone) </p>
           <p> Will You attend?
                                @Html.DropDownListFor( x => x.WillAttend, new[] {
               New SelectListItem() {Text = “Yes, I’ll be there”, Value = bool.TrueString },
              New SelectListItem() {Text = “No, I can’t come”, Value = bool.FalseString },
“Choose an option”)
     }
</p>
<input type=”submit” value=”Submit RSVP” />
</body>
</html>

The validation summary helper method creates a placeholder with a hidden list item in the form. MVC makes this placeholder visible & shows list of validation error messages defined by the validation attributes. The user will not be allowed to show the Thanks View until appropriate data is entered and restricts the user to maintain the same view & preserve data. This makes a good sense of using Model Binding unlike in web form retaining the server control state by serializing values into a hidden form field “_ViewState”.


To highlight the fields, the same mechanism can be followed to check validation and highlight the fields. For a htmlhelper method like textbox, dropdown, etc., the way a html is generated slightly differs when there are validation rules applied at the model class.

Html.TextBoxFor( x => x.Name) textbox helper method detects the validation attributes while model binding and generates a html as shown below:

When there are no validation error:

<input data-val=”true” data-val-required=”Please enter your name” id=”Name” name=”Name” type=”text” value=”” />

When there are validation errors: The helper method adds a css class to highlight.

<input class=”input-validation-error” data-val=”true” data-val-required=”Please enter your name” id=”Name” name=”Name” type=”text” value=”” />

These css classes are found in ~/Content/Site.css style sheet. Add reference to our view page.

<link rel=”StyleSheet” href=”@Href(“~/Content/Site.css”)” type=”text/css” /> Sample figure:


All these attribute classes are derived from the abstract class ValidationAttribute

Public abstract
class ValidationAttribute : Attribute
{
Public string ErrorMessage { gets; set; }
Public virtual bool IsValid(object value);
Protected void ValidationResultIsValid(object value, validation context context);
}

These are the validation rules applied to a server control. Client side validation helps in reducing the server load for which, we follow ClientSIde Validation

To enable client side validation edit the web.config configuration file as

<appsettings>
<add key=”ClientValidationEnabled” value=”true” />
<add key=”UnobtrusiveJavaScriptEnabled” value=”true” />
</appsettings>

Now, include

the java script files like normally we add reference in html page.

<script src=”@Url.Content(“~/Scripts/jquery-1.8.1.min.js”)” type=”text/javascript”>
</script>
<script
src=”@Url.Content(“~/Scripts/jquery.validate.min.js”)” type=”text/javascript”>
</script>
<script
src=”@Url.Content(“~/Scripts/jquery.unobtrusive.min.js”)” type=”text/javascript”>
</script>


ISometimes, a custom validation is required in case where validation attribute can't support all. For ex : We want user not to select a previous to today date to set his examination slot. In such cases there are no validation attributes hence we go with custom validation. We have seen abstract class Validation attribute and its methods above. Every validation class defined should inherit this validation attribute class and override the necessary methods. It has two IsValid overloaded methods:

1. IsValid(object) - returns bool
2. IsValid(object, ValidationContext) - returns bool
Validation attribute can be applied at model level in which whole model will be passed as parameter to IsValid method and validated or individual property level. To let the user select a Exam slot date greater than today date we pass the selected date as object value to IsValid method and validate as:
//custom validation at server side
public class ExamDateAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
return ((DateTime)value > DateTime.Now && value != null); // both required as well as checking date
}
}
To apply this custom validation at client side, we have to implement an interface called IClientValidatable in our Custom validation attribute class i.e., ExamDateAttribute class to enable client side validation. It contains a method called GetClientValidationRules that returns a collection of ModelClientValidationRule instances.

public class ExamDateAttribute : ValidationAttribute, IClientValidatable 
{
public override bool IsValid(object value)
{
return ((DateTime)value > DateTime.Now && value != null); // both required as well as checking date
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetaData metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = ErrorMessage ;
ValidationType = "ExamSlotDate";
};
}
}
We have now declared the server side rule, but how to link up this to jquery?? So, we have to write two methods validator and adaptor. In the validator method we write the code to evaluate our object value, in case validation fails adaptor method will set the error message.
	jQuery.validator.addMethod('ExamSlotDate' , function (value, element, params) {
if( !/Invalid|NAN/.test(new Date(value))) {
return new Date(value) > new Date();
}
return isNan(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));
}, ' ');
jQuery.validator.unobtrusive.adapters.add('ExamSlotDate' , { }, function(options) {
options.rules['ExamSlotDate'] = true;
options.messages['ExamSlotDate'] = options.message;
});
Throgh the above methods, we have implemented Validation attribute, IClientValidatable which performs the server side and client side validation. The same can also be implemented by using IValidatable object at the model object level.

Conclusion

In the current article we have seen how to add server side and client side validations in an MVC application

Reference

asp.net/mvc site, pro asp.net mvc framework book
Page copy protected against web site content infringement by Copyscape

About the Author

Vasanthmvp
Full Name: VASANTH KUMAR
Member Level:
Member Status: Member
Member Since: 6/26/2012 12:13:54 AM
Country: India
Awesome Coding !! :)
http://www.dotnetfunda.com
Started my journey with what is .Net on 30-07-2012 and pretty excited to learn & share it on DotNetFunda since 15-08-2012. :) Exploring more & more :)

Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)