Showing posts with label DataAnnotations. Show all posts
Showing posts with label DataAnnotations. Show all posts

Thursday, July 17, 2014

MVC Attribute to restrict users to enter any kind of HTML tags in the input fields

By default, if a user tries to enter any HTML tags in any of the input boxes in an MVC website, it will throw an error saying "Potentially dangerous request".
This is OK, as it doesn't allow user to enter HTML tags and prevents the site from security threat.

However, the error page is not user friendly, and it is not giving a clue to the user as what was wrong there. So you may need to avoid default error page of browser, and instead your custom validation message should be displayed.

Also, there may be circumstances when you want to allow some fields to accept HTML tags (such as rich text boxes), and rest of the input fields shouldn't allow HTML. In that case, this approach will help.

In order to achieve this we need to create an attribute in MVC and then can decorate Model properties with that attribute.

Step 1
- Decorate HttpPost method with [ValidateInput(false)] 
Validate input is true by default, and that is why it prevents execution of any code in case if there is any HTML input values are detected in posted data.
Here, we need to set it to false" as we would like to execute code of our custom attribute       

[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public virtual ActionResult CreateCustomer(Customer viewModel)
{
......
}


Step 2
- Create custom attribute as below:

using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using System.Text.RegularExpressions;
public class DenyHtmlInputAttribute: ValidationAttribute
{


protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null)
return ValidationResult.Success;


var tagWithoutClosingRegex = new Regex(@"<[^>]+>");


var hasTags = tagWithoutClosingRegex.IsMatch(value.ToString());


if (!hasTags)
return ValidationResult.Success;

return new ValidationResult(String.Format("{0} cannot contain html tags", validationContext.DisplayName));
}


}
Step 3 
- Decorate all input fields of your Model with the attribute created above:
[DenyHtmlInput]
public string Comments { get; set; }
That's it.

This is how you can restrict Html inputs on specific fields of your MVC view.

Saturday, April 21, 2012

Implement Custom Validation in ASP.NET MVC

This article aims to explain how we can implement Custom validation (server-side) in ASP.NET MVC.

System.ComponentModel.DataAnnotations namespace provides set of predefined validations which are common in almost all scenarios (like, Required, Range, Regular Expression, etc). Click here for more information.

This namespace contains "ValidationAttribute" class which is a base class for all validation attributes.
Following are the steps to be performed in order to implement a custom validation.
1. Inherit a new validation class from ValidationAttribute base class. (A new class can be created anywhere but should have System.Component.DataAnnotations referenced.)
2. Override "IsValid" method and write our own validation. (Here, we can get the value entered by user for the corresponding field/ property, so we can validate it).
3. Apply new attribute on the field/ property of a model wherever you need that custom validation to fire.

Sample Code:
In our "Person" model, we have a "BirthDate" field. We now want to validate if the Age of a person must be 18  or above.
1. A class inherited from ValidationAttribute, and overriding of IsValid method within:



[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class BirthDateValidation : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            if (Convert.ToDateTime(value) >= DateTime.Now.AddYears(-18))
            {
                return false;
            }
            return true;
        }
    }


2. Applying "BirthDateValidation" attribute on Birthdate property.


[Display(Name="Birth Date")]
        [BirthDateValidation(ErrorMessage="Registration is only allowed for people above 18 years.")]
        public DateTime BirthDate { get; set; }


3. Last thing, as it is a server-side validation (just like, Required, Range, etc), dont forget to relaunch the view from corresponding HttpPost action in your controller, in case if ModelState.IsValid is False. (indicating, a validation failed)

[HttpPost] 
       public ActionResult PersonEdit(Person person)
        {
            if (ModelState.IsValid == false)
            {
                return View("PersonEdit",  person);
            }
            else
            {
             //Write code to define actions on success
            }            
        }


That's all we need to implement this validation:

Screenshot:


Simple client-side Validations using ASP.NET MVC

This article aims to demonstrate how we can apply simple validations at view (page) level in ASP.NET MVC.

Say, you have a "Person" model, that you pass in the view to and fro controller action.

A Person model is having many fields, one of them is "PersonName" (Label: Person Name) and you want to make it required when user inputs data in corresponding view of this model.

In order to achieve this, first decorate PersonName field in Person model with "Required" attribute.
"Required" attribute is a part of System.ComponentModel.DataAnnotations namespace. So this must be imported in your model (using System.ComponentModel.DataAnnotations)

System.ComponentModel.DataAnnotations contain various attributes that can be applied on a model field. Along with that it has all necessary validators (like, Required, Range, MaxLength, MinLength, Regular Expression, Custom validator, etc).

For our case, we should write - 

[Required(ErrorMessage="Please Enter Person Name!")]
[Display(Name="Person Name")]
public string PersonName { get; set; }

This will automatically handle required validation for Person Name field input.
Now, in the view (.aspx, or .cshtml), we need to put ValidationSummary in order to display error message in case validation fails.
@Html.ValidationSummary(false, "Please correct following errors and try again!")

The last thing is to add a condition in HttpPost method to relaunch the view with latest inputs and error messages, in case if validation(s) fail.

[HttpPost]
        public ActionResult PersonEdit(Person person)
        {
            if (ModelState.IsValid == false)
            {
                return View("PersonEdit",  person);
            }
            else
            {
             //Write code to define actions on success
            }            
        }

Now, when the view is launched with person model, it will have same inputs as well as validation errors, so that they will get displayed in ValidationSummary control in view to let users know about the errors.

NOTE: Also, remember to put @Html.ValidationSummary control before @Html.BeginForm block, otherwise it will always show you validation messages even before HttpPost.