...

/

Designing Custom Validation Attributes

Designing Custom Validation Attributes

In this lesson, we will learn code a custom validation attribute that will perform both server-side and client-side validation.

A custom validation attribute can be implemented by inheriting from the ValidationAttribute class. Server-side validation code is provided by overriding the methods that perform validation and error message formatting.

Client-side validation requires that our attribute implements the IClientModelValidator interface whose unique AddValidation method specifies the data- attributes to add to the input field. The actual client-side validation code must be provided through a JavaScript validator which is connected to the parser that processes all data- attributes through a JavaScript adapter.

We will describe all the above steps while implementing an example custom validation attribute: the ExtensionAttribute.

The ExtensionAttribute

As an example, we will define an attribute that checks the extension of a Web Address. It is useful when combined with the UrlAttribute to force the user to insert the address of a pdf, or of a supported image type. The basic idea is to pass it a string with all comma-separated allowed extensions. Something like .jpg,.jpeg, or .png. The usage should be similar to the example below:

Press + to interact
[Display(Name="URL of picture"), Url, Extension(".jpg,.jpeg,.png")]
public string WebPicture { get; set; }

The combined usage of both UrlAttribute and ExtensionAttribute forces the user to insert the Web Address of an image.

Server-side validation

Custom attributes can be inserted in a folder called Validation that is placed in the application root. There, we can add an ExtensionAttribute class that inherits from ValidationAttribute:

Press + to interact
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace MvcProject.ViewModels
{
public class ExtensionAttribute: ValidationAttribute, IClientModelValidator
{
private const string defaultMessage = "{0} is not a a supported image addrees";
private string extensions;
public ExtensionAttribute(string extensions)
{
this.extensions = extensions;
}
private string extensions;
public ExtensionAttribute(string extensions)
{
this.extensions = extensions;
}
public override bool IsValid(object value)
{
...
}
}
}

The default namespace name has been changed to match the namespace of all ViewModels, so we don’t need any using to use it with our ViewModels. However, we can also use a dedicated namespace.

The comma-separated list of extensions passed to the ...