[Required]
A value must be provided.
[Range]
Eg: 1-10
[Regular Expression]
Value must specify a regular expression.
[StringLength]
Value must be a min length and less than a max length
[Compare]
Value must equal another property
[Remote]
Value is validated client side with a JSON call to the Server.
Eg: The user name Available.
[Extensible]
Specify your own custom Validations
A namespace has to be added( System.ComponentModel.Data.Annotations)
Examples:
Prod.cs
A value must be provided.
[Range]
Eg: 1-10
[Regular Expression]
Value must specify a regular expression.
[StringLength]
Value must be a min length and less than a max length
[Compare]
Value must equal another property
[Remote]
Value is validated client side with a JSON call to the Server.
Eg: The user name Available.
[Extensible]
Specify your own custom Validations
A namespace has to be added( System.ComponentModel.Data.Annotations)
Examples:
Prod.cs
we will see how to create custom validations by implementing the
ValidationAttribute
class or IValidatableObject
interface.Validation Attributes class will make our class as Annotations.
To enable client-side validation we have to do couple of things. First we have to make sure the
ClientValidationEnabled
and UnObtrusiveJavaScriptEnabled
are set to true in web.config
.<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
The next thing is include the necessary JavaScript files in the layout page.
There are some cases where we need to do basic validations. In some cases we need to apply validations to class properties that are not supported by the built-in validation attributes. For example in our application we need price to be validated as
Price<minPrice || price>maxPrice
Example 1
Validation attributes can be applied to models as well, if the custom validation attribute is applied to a model then the complete model itself will be passed as value parameter to the
IsValid
methods. When the custom validation depends upon more than one property of a class then we can apply the attribute to the class or model itself.In our scenario the
Start Date
should be a future date and it is independent of other properties so let's implement the first IsValid
method. The implementation is quite simple as shown below Eg2:
Public class PriceValidationAttribute:ValidationAttribute
{
Private decimal minPrice=10;
Private decimal maxprice=100.00
Public override bool IsValid(object value)
{
Decimal price=(decimal)value;
if (price<this.minprice || price>this.maxPrice)
return false;
}
The custom validation we have applied to the
Party
model is done only at the server side and how we can do that in the client-side also? The ASP.NET MVC team understands this problem and has come up with a solution for that. The solution is we have to implement an interface called IClientValidatable
in our custom attribute class to enable client-side validation. The interface contains a single method named GetClientValidationRules
that returns a collection of ModelClientValidationRule
instances.public classFutureDateValidatorAttribute : ValidationAttribute, IClientValidatable
{
public override bool IsValid(object value)
{
return value != null && (DateTime)value > DateTime.Now;
}
public IEnumerable<ModelClientValidationRule>
GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "futuredate"
};
}
}
In the implementation we are just returning a single instance setting the error message and
"futuredate"
for theValidationType
. We can use any other name instead of "futuredate"
for ValidationType
.Implementing only this interface not completely solves the problem! we have to do couple of things more. We have to create a
jQuery validator
and adapter
. In the validator we write the logic to evaluate the StartDate
is a future date or not and in the adapter we set the error message that has to be displayed when the validation fails.jQuery.validator.addMethod('futuredate', 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('futuredate', {}, function (options) {
options.rules['futuredate'] = true;
options.messages['futuredate'] = options.message;
});
We have successfully created a custom validation by implementing the
ValidationAttribute
and IClientValidatable
to perform the validation at both the client and server side.IValidatableObject
The MVC framework provides another way to do custom validations using
IValidatableObject
. Unlike theValidationAttribute
the IValidatableObject
is implemented in the model class itself. TheIValidatableObject
contains a single method called Validate
that returns a collection of ValidationResult
instances.public interface IValidatableObject
{
IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
The important differences between the
ValidationAttribute
and IValidatableObject
are: the former one is used to perform a single validation while the later one is used to perform single or multiple validations. If we want the validation to happen both at the server-side and at the client-side then the ValidationAttribute
is the right choice. If we want the validations should happen only at the server-side then IValidatableObject
is the right choice. The IClientValidatable
only supports ValidationAttribute
for client-side validations and notIValidatableObject
. ValidationAttribute
is used to perform a single validation. IValidatableObject
can be used to do multiple validations.The MVC framework provides another way to do custom validations using
IValidatableObject
. Unlike theValidationAttribute
the IValidatableObject
is implemented in the model class itself. TheIValidatableObject
contains a single method called Validate
that returns a collection of ValidationResult
instances.public interface IValidatableObject
{
IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
The important differences between the
ValidationAttribute
and IValidatableObject
are: the former one is used to perform a single validation while the later one is used to perform single or multiple validations. If we want the validation to happen both at the server-side and at the client-side then the ValidationAttribute
is the right choice. If we want the validations should happen only at the server-side then IValidatableObject
is the right choice. The IClientValidatable
only supports ValidationAttribute
for client-side validations and notIValidatableObject
. ValidationAttribute
is used to perform a single validation. IValidatableObject
can be used to do multiple validations.We are going to add two more validations to our
Party
class. The party provider doesn't allow the party to continue after 10 PM (bad!) and they don't server drinks if the NoOfJoinees
is less than 5 (too bad!). If you see these validations they are pretty much tied to the business and they can't be reusable across classes, so the best way to go is IValidatableObject
approach. The other thing is we can do a set of validations using this approach.Below listing shows the implementation.
Collapse | Copy Code
public class Party : IValidatableObject
{
[Required(ErrorMessage = "Start date is required")]
[FutureDateValidator(ErrorMessage = "Start date should be a future date")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Duration is required")]
public int DurationInHours { get; set; }
[Required(ErrorMessage = "No. of joinees is required")]
[Range(2, 10, ErrorMessage = "No. of joinees should be minimum 2 and not more than 10")]
public int NoOfJoinees { get; set; }
public bool Drinks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (StartDate.TimeOfDay > new TimeSpan(22 - DurationInHours, 0, 0))
{
yield return new ValidationResult("The party should not exceed after 10.00 PM");
}
if (NoOfJoinees < 5 && Drinks)
{
yield return new ValidationResult("Drinks are only allowed if no. of joinees is 5 or more.");
}
}
}