[Incredible Blog Post] Validation Using The Data Annotation Validators in ASP.NET MVC (10 Useful/Favorite Attributes;CustomValidation, Remote, Compare, StringLength, DataType, RegularExpression, Range, Display, Required, DisplayFormat)


Hi everyone,

In the previous post, I explained you “How To Write A Real Time Chat Application In Only 5 Minutes! (Using SignalR)“. I mentioned about something which is; what SignalR is, how to use it, etc. We also saw what an amazing technology SignalR is. Now, We’re going to concern about useful attributes whichI have used for validation.  Generally, they are used with properties in the classes.

What Are The Attributes

Attributes provide extended features of  associating metadata. In other words, attributes are used for associated metadata such as, properties, methods, classes and so forth.

Using Attributes

In C#,  you specify an attribute to place a property/class/etc, between square brackets ([]). In VB, an attribute is written between angle brackets (< >).  The attribute is applied to an element and this attribute must be located just before its element, both of them could be on the same line.

Single Attribute:

    public class User
    {
        [AttributeName]
        public string MyProperty { get; set; }

    }

Multiple Attributes(two ways)

First way:

    public class User
    {
        [AttributeName1][AttributeName2]
        public string MyProperty { get; set; }

    }

Second way:

    public class User
    {
        [AttributeName1,AttributeName2]
        public string MyProperty { get; set; }

    }

Technical Requirements

We’ll be using ASP.NET MVC 4 (Basic Template) on Visual Studio 2012 with C# to develop this example.

Beginning

There are some server side and client side techniques for validation inputs. We always need to validate inputs/fields such as username, email, birthdate, password, comparing password etc. However, the most important thing is that every input  uses different validation type. So, you have to know what kind of validation you should use. On the other hand, only using client side functions for validation does not give perfect result while we’re developing web application.

Let’s Do It

#1 Step: Right Click to Models, then add a Class and name it “User”

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_User

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_User_2

#2 Step: Add Properties To User Class

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_User_Add_Properties_username_password_email

    public class User
    {
        public string username { get; set; }

        public string password { get; set; }

        public string comparePassword { get; set; }

        public string email { get; set; }

        public string birthdate { get; set; }

        public string registrationDate { get; set; }
    }

#3 Step: Right Click to Controller, then add a Controller and name it “Home”

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_2

#4 Step: Add View and Name it “Index”

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_2

#5 Step: Reference Script Libraries and Add Style File (between head tags)

We have to add script and css files below to use validation perfectly. We need css classes in the file(/Content/Site.css) to show errors as  javascript functions are used to validate fields.

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_add_scripts_css_files

<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/Site.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.7.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
</head>

#6 Step: Add User Class as Model to Index Page

This operation is also called “Model Validation” which we are going to do . So, We must assign a model to the page for validation.

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Model_Validation

@model TheDataAnnotationValidators.Models.User
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/Site.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.7.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
</head>
<body>

</body>
</html>

#7 Step: Prepare the Index page

You generate page structure below automatically. Normally, we would like to create a TextBox, a Label, a DropDownList, a RadioButton, etc, one thing what you should do is to write this code: @Html.TextBox, @Html.Label, @Html.DropDownList, @Html.RadioButton. When you see a helper which contains “For” keyword after Helper name -such as @Html.TextBoxFor, @Html.LabelFor-, it means that it’s used for the “Model”. On the other hand, a ValidationMessageFor is used to show validation message for a related field.

@model TheDataAnnotationValidators.Models.User
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/Content/Site.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.7.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
</head>
<body>
    @using (Html.BeginForm())
    {
        <fieldset>
            <legend>User</legend>

            <div class="editor-label">
                @Html.LabelFor(model => model.username)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.username)
                @Html.ValidationMessageFor(model => model.username)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.password)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.password)
                @Html.ValidationMessageFor(model => model.password)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.comparePassword)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.comparePassword)
                @Html.ValidationMessageFor(model => model.comparePassword)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.email)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.email)
                @Html.ValidationMessageFor(model => model.email)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.birthdate)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.birthdate)
                @Html.ValidationMessageFor(model => model.birthdate)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.registrationDate)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.registrationDate)
                @Html.ValidationMessageFor(model => model.registrationDate)
            </div>
            <p>
                <input type="submit" value="Sender" />
            </p>
        </fieldset>
        @Html.ValidationSummary(true)
    }

</body>
</html>

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_fieldset_div_validation
#8 Step: Learning The Attributes

  • Display: To change display name of a property name
  • Required: To require a field
  • DataType: To define a field’s type

  • RegularExpression: To validate a field using Regex Pattern
  • StringLength: To specify a string’s character length
  • Compare: To compare two fields like password and comparePassword
  • Range: To limit values for a field
  • DisplayFormat: To show display in a format you want
  • CustomValidation: To validate new kind of validation that you want/need
  • Remote: To use an action in controller to validate a field

#9 Step: Implementation

Display:You can apply one or more attributes to a class property. First of all, let’s organize all input labels as;

    public class User
    {
        [Display(Name="Username")]
        public string username { get; set; }

        [Display(Name = "Password")]
        public string password { get; set; }

        [Display(Name = "Compare Password")]
        public string comparePassword { get; set; }

        [Display(Name = "Email")]
        public string email { get; set; }

        [Display(Name = "Birthdate")]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_data_annotation_display_name

It’s nice, isn’t it? Keep going…

Required: All fields except RegistrationDate field are required to fill blank.

ErrorMessage=if a user does not fill field which associated with attribute, ErrorMessage is used to show a customized validation message.

    public class User
    {
        [Display(Name = "Username"), Required(ErrorMessage="You have to fill The Username field is required")]
        public string username { get; set; }

        [Display(Name = "Password"),Required]
        public string password { get; set; }

        [Display(Name = "Compare Password"),Required]
        public string comparePassword { get; set; }

        [Display(Name = "Email"),Required]
        public string email { get; set; }

        [Display(Name = "Birthdate"),Required]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_Class_Controller_Home_required_displayname_data_annotation_validator

DataType: As you see, We used @Html.EditorFor for all fields. However, we have also an absolute requirement for password fields to show password char. We should decide which field is which kind of DataType.

    public class User
    {
        [Display(Name = "Username"), Required(ErrorMessage = "You have to fill The Username field is required")]
        public string username { get; set; }

        [Display(Name = "Password"), Required, DataType(DataType.Password)]
        public string password { get; set; }

        [Display(Name = "Compare Password"), Required]
        public string comparePassword { get; set; }

        [Display(Name = "Email"), Required]
        public string email { get; set; }

        [Display(Name = "Birthdate"), Required]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_DataType_Password

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_DataType_Password_DataAnnotation

As we did for the password field, we add DataType to the comparePassword field.

RegularExpression: better known by general usage name RegEx, provides a match to a string of text using a pattern string which persists user to data input. This pattern can use different patterns like email, phone number, zip code, etc.

You can find several patterns on RegexLib.com, more information about RegularExpression.

A Sample Pattern String: “^[0-9a-zA-Z]+([0-9a-zA-Z]*[-._+])*[0-9a-zA-Z]+@[0-9a-zA-Z]+([-.][0-9a-zA-Z]+)*([0-9a-zA-Z]*[.])[a-zA-Z]{2,6}$”

    public class User
    {
        [Display(Name = "Username"), Required(ErrorMessage = "You have to fill The Username field is required")]
        public string username { get; set; }

        [Display(Name = "Password"), Required, DataType(DataType.Password)]
        public string password { get; set; }

        [Display(Name = "Compare Password"), Required, DataType(DataType.Password)]
        public string comparePassword { get; set; }

        [Display(Name = "Email"), Required, RegularExpression("^[0-9a-zA-Z]+([0-9a-zA-Z]*[-._+])*[0-9a-zA-Z]+@[0-9a-zA-Z]+([-.][0-9a-zA-Z]+)*([0-9a-zA-Z]*[.])[a-zA-Z]{2,6}$", ErrorMessage = "Incorrect Email Format!")]
        public string email { get; set; }

        [Display(Name = "Birthdate"), Required]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Regular_Expression

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Incorrect_Email_Format

StringLength: allows a string between min and max characters length

    public class User
    {
        [Display(Name = "Username"), Required(ErrorMessage = "You have to fill The Username field is required"), StringLength(10, ErrorMessage = "The {0} must be between {2} and {1} characters long.", MinimumLength = 6)]
        public string username { get; set; }

        [Display(Name = "Password"), Required, DataType(DataType.Password)]
        public string password { get; set; }

        [Display(Name = "Compare Password"), Required, DataType(DataType.Password)]
        public string comparePassword { get; set; }

        [Display(Name = "Email"), Required, RegularExpression("^[0-9a-zA-Z]+([0-9a-zA-Z]*[-._+])*[0-9a-zA-Z]+@[0-9a-zA-Z]+([-.][0-9a-zA-Z]+)*([0-9a-zA-Z]*[.])[a-zA-Z]{2,6}$", ErrorMessage = "Incorrect Email Format!")]
        public string email { get; set; }

        [Display(Name = "Birthdate"), Required]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_StringLength_Data_Annotation

asp_net_mvc_4_razor_Data_Annotation_Validators_Validation_Attribute_Add_StringLength_Data_Annotation_min_max

Compare: We always need to compare min two values which may be email to email or password to password. In this sample, we’ll compare ‘password’ field to ‘compare password’ field.

Attention: You must use a property’s csharp name – not displayName- in Compare Attribute

    public class User
    {
        [Display(Name = "Username"), Required(ErrorMessage = "You have to fill The Username field is required"), StringLength(10, ErrorMessage = "The {0} must be between {2} and {1} characters long.", MinimumLength = 6)]
        public string username { get; set; }

        [Display(Name = "Password"), Required, DataType(DataType.Password)]
        public string password { get; set; }

        [Display(Name = "Compare Password"), Required, DataType(DataType.Password), Compare("password", ErrorMessage = "The Password does not match with the other")]
        public string comparePassword { get; set; }

        [Display(Name = "Email"), Required, RegularExpression("^[0-9a-zA-Z]+([0-9a-zA-Z]*[-._+])*[0-9a-zA-Z]+@[0-9a-zA-Z]+([-.][0-9a-zA-Z]+)*([0-9a-zA-Z]*[.])[a-zA-Z]{2,6}$", ErrorMessage = "Incorrect Email Format!")]
        public string email { get; set; }

        [Display(Name = "Birthdate"), Required]
        public string birthdate { get; set; }

        [Display(Name = "Registration Date")]
        public string registrationDate { get; set; }
    }

asp_net_mvc_data_annotation_Compare_controller_model

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required

Range: Allow users for data input given range from one value to the other value.

Attention: Since we use integer value for Range, we changed the birthdate property’s name as “birthday

        [Display(Name = "Birthday"), Required, Range(1950, 1995,ErrorMessage = "Value for {0} must be between {1} and {2}")]
        public string birthday { get; set; }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_Range_Int

            <div class="editor-label">
                @Html.LabelFor(model => model.birthday)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.birthday)
                @Html.ValidationMessageFor(model => model.birthday)
            </div>

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_Range_Int_labelFor

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_Range_Int_labelFor_Range

DisplayFormat: You can change how to display a field’s value easily.

Attention: Since we use DisplayFormat, we changed the registrationDate  property’stype as “DateTime” instead of “string

        [Display(Name = "Registration Date")]
        public DateTime registrationDate { get; set; }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_registrationDate

Attention 2:  There is another change in the below. This is because, You just imagine that you want to update user information, you need to take current user information and then show the user who owner of these information is. Here, I just took  instance of user class for this sample.

        public ActionResult Index()
        {
            User myUser = new User();
            myUser.registrationDate = DateTime.Now;
            return View(myUser);
        }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_modelState

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_registrationDate2

Attention 3: We want to show Registratin Date as “MM/dd/yy” format

        [Display(Name = "Registration Date"), DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yy}")]
        public DateTime registrationDate { get; set; }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_registrationDate_DataFormat
asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_registrationDate_DataFormat_2

CustomValidation: The exist validation attributes are not inadequate for you to validate different type. You can simply use this one.

Attention: We create a class, named CustomAttributes, under models folder.

    public class CustomAttributes
    {
        public static ValidationResult PasswordStrongTest(string value, ValidationContext validationContext)
        {
            if (value == null)
                return ValidationResult.Success;

            if (!Regex.IsMatch(value, @"(?=^.{6,10}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&amp;*()_+}{&quot;:;'?/&gt;.&lt;,])(?!.*\s).*$"))
                return new ValidationResult("It expects at least 1 small-case letter, 1 Capital letter, 1 digit, 1 special character and the length should be between 6-10 characters. ", new List<string> { "password" });

            return ValidationResult.Success;
        }
    }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_CustomAttribute

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_password_CustomValidation

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_ValidationResult

Remote: You can use a method which returns ActionResult in a controller. 

Attation: Here, we are going to apply this Attribute to username field. What we need to do is to add a method in the controller;

        [HttpPost]
        public ActionResult CheckUserNameExist(string username)
        {
            List<string> usernames = new List<string>() { "mcansozeri", "billGates", "steveJobs" };

            return Json(usernames.Find(x => x == username) == null);
        }

asp_net_mvc_data_annotation_Compare_controller_model_compare_password_dataType_Required_JsonResult_HttpPost

Result: I would like to demostrate all of the Attributes.

Download

Download using here.

 

Have a nice coding!

, , , , , , , , , , , , , , , , , , , , , , , ,

  1. #1 by http://www.abortionreview.org/index.php/member/67626/ on March 5, 2013 - 12:25 am

    That is very fascinating, You’re an overly skilled blogger. I’ve joined your feed and stay up
    for looking for extra of your fantastic post.
    Additionally, I’ve shared your website in my social networks

  1. [Blog Post(Turkish)] ASP.NET MVC İle İlgili Tüm Yazılarım (29 Yazı, 1 Yazı Dizisi ve 1 İpucu Serisi) « Mahmut Can Sozeri

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s