Removing Data Validation from MVC Controllers

Published on May 6, 2015 by Jamie Munro


You require custom data validation that cannot be accomplished via the built-in data annotation validation attributes - or - your data validation requires access to multiple properties in your model.


Many times the easy answer is to place the validation inside of your controller. However, I'm a strong believer of placing data validation outside of your controllers and within your data model. This is commonly accomplished by adding data annotation above the properties, such as the [Required] attribute. Another common way is to create your own validation attributes.

This example will use a third way and that is to implement the IValidatableObject interface. This interface defines a Validate function that must be implemented and because it is inside of your data model it has access to all properties within your model.


To demonstrate the IValidatableObject I've created a model that contains three properties: Quantity, MaxQuantity (nullable), and FixedQuantity. The validation rules are, if FixedQuantity is true, MaxQuantity should be null.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace RedirectWithModel.Models
public class ValidationModel : IValidatableObject
public int Quantity { get; set; }
public int? MaxQuantity { get; set; }
public bool FixedQuantity { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
if (FixedQuantity && MaxQuantity.HasValue)
yield return new ValidationResult("A max quantity should not be specified when FixedQuantity is true");

Inside the Validate function, when FixedQuantity is true and MaxQuantity contains any value, a new ValidationResult is returned with an error message letting the user know what is wrong.

The following validation rule will be applied when the ModelState.IsValid is called typically from a controller or a global filter.

Tags: validation | ASP.NET | mvc5 | ivalidatableobject | validationcontext

Related Posts

blog comments powered by Disqus