1

How I can develop a custom validation rule in MVC? I.e. I have many decimal properties in my model and I would like to make a range validation from 1 to 100 to all of them without use data annotation in each.

1 Answer 1

1

You can add validation to your whole model by making it implement IValidatableObject, for example:

public class MyModel: IValidatableObject
{
  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
  {
     if (MyProperty > 100 || MyProperty < 1)
       yield return new ValidationResult("MyProperty is out of range (1..100)", new [] { "MyProperty" });
     ...

  }
}

Here's a resource that has a more elaborate example.

In case you want to cover all decimal properties automatically you can do this:

public abstract class MyValidatableBaseModel: IValidatableObject
{
  protected abstract virtual Type GetSubClassType();

  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
  {
     var decimalProperties = GetSubClassType().GetProperties().Where(p => p.PropertyType == typeof(decimal));
     foreach (var decimalProperty in decimalProperties)
     {
        var decimalValue = (decimal)decimalProperty.GetValue(this, null);
        var propertyName = decimalProperty.Name;
        //do validation here and use yield return new ValidationResult
     } 
  }
}

public class MyModel : MyValidatableBaseModel
{
    protected override Type GetSubClassType()
    {
        return GetType();
    }
}

Any model that inherits from MyValidatableBaseModel (in the example, MyModel) and overrides GetSubClassType to returns it's own type will have that automatic validation for decimal properties

Sign up to request clarification or add additional context in comments.

3 Comments

@Max You can get clever and use reflection to go through all the properties of your model that satisfy a certain condition (e.g. are of decimal type) and apply validation to them. I'll update the answer with an example shortly
it's a nice solution but in that case I will have to add this code to all models (the inheritance doesn't work in this case). Do you have any workaround on this?
@MaxBündchen The trick is to take advantage of polymorphism to get the type of the derived class so that we can use reflection to get its properties. You still have to override GetSubClassType. Not perfect, but its less work than having to annotate each property individually

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.