Introduction
There was a need for checking that user input does not contain any tags and display a corresponding validation message. As you may know ASP.NET has a built in feature for verifying if the HTTP request has a potentially dangerous content, that is called Request validation.
By default it is true in ASP.NET MVC for security reasons.
So how do we overpass this and create our custom validation mechanism for verifying that user input contains
HTML code...
I have attached a sample project where this mechanism is implemented. This tip/example gives only the basic understanding of how to implement
your own custom validation attribute for verifying the input. Also only server side validation happens in this example.
Let the code speak
I'll shortly describe the code from the sample project below:
First of all we have to create a custom validation attribute for checking if the model's property value has any
HTML/XML tags. Let's call our custom attribute
DisallowHtmlAttribute
. To implement our validation logic we should override the
IsValid
method and place the logic there. Here is how it looks:
public class DisallowHtmlAttribute : 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("The field cannot contain html tags");
}
}
Okay, we've created our custom validation attribute, however we should have some mechanism for adding this validation attribute to all properties of the model
that is passed to the view.
This can be done by creating our own custom DataAnnotationsModelValidatorProvider
that will be adding and returning
our DisallowHtmlAttribute
to the list of modal validators. Let's call it DisallowHtmlMetadataValidationProvider
and let's check its implementation:
public class DisallowHtmlMetadataValidationProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata,
ControllerContext context, IEnumerable<Attribute> attributes)
{
if (attributes == null)
return base.GetValidators(metadata, context, null);
if (string.IsNullOrEmpty(metadata.PropertyName))
return base.GetValidators(metadata, context, attributes);
var isHtmlInput = attributes.OfType<AllowHtmlAttribute>().Any();
if (isHtmlInput)
return base.GetValidators(metadata, context, attributes);
attributes = new List<Attribute>(attributes) { new DisallowHtmlAttribute() };
return base.GetValidators(metadata, context, attributes);
}
}
Now we have to add DisallowHtmlMetadataValidationProvider
to the MVC's current application validator provider. Such things are usually done in Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new DisallowHtmlMetadataValidationProvider());
}
We are almost there. The only thing we have to do now is to disable the request validation, but first let's see how currently the site behaves when the user's input
contains HTML/XML tags. Let's enter something like this:
This is what we get after posting data to the server:
This is the correct behavior because we haven't disabled the request
validation in the application. We can easily disable the request validation for
all Controller and Actions by registering ValidateInputAttribute
with the false
parameter in the global action filters in the Global.asax file.
filters.Add(new ValidateInputAttribute(false));
Or if you need to disable Request validation only for a specific controller or action, just decorate it with:
[ValidateInput(false)]
Now we are done and every time the user input contains an HTML or XML tag he'll see a validation message:
Simple as that!