0

I am using DataAnnotation Attributes to apply validation to properties on my model, outside of MVC.

public class MyModel
{
    [Required]
    [CustomValidation]
    public string Foo { get; set; }
}

I have implemented the following extension method to validate the model.

public static void Validate(this object source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    var results = new List<ValidationResult>();
    bool IsValid = Validator.TryValidateObject(source, new ValidationContext(source, null, null), results, true);
    if (!IsValid)
        results.ForEach(r => { throw new ArgumentOutOfRangeException(r.ErrorMessage); });
 }

I have to call this Validate() method every time I set a property which is not convenient:

MyModel model = new MyModel();
model.Foo = "bar";
model.Validate();

model.Foo = SomeMethod();
model.Validate();

I would like that the Validate() method be called automatically behind the scenes when the state of the model changes. Does anyone have any idead on how to achieve this?

For bonus points, does anyone know exactly how MVC achieve this automatic validation via DataAnnotations?

Thanks.

5
  • What makes you believe that MVC does this automatically? Or do you mean the client-side validation? That is accomplished using client-side code (JavaScript), which is generated from the annotations. Commented Jan 9, 2014 at 8:45
  • And why the results.ForEach(r => { throw new ... }); ? Since only a single exception will be thrown. Commented Jan 9, 2014 at 8:46
  • Okay, irrespective of what MVC does. How can I achieve the validation API that I desire (automatic)? Commented Jan 9, 2014 at 8:55
  • "In fact, ASP.net MVC will automatically verify these as part of its model binding." stum.de/2013/06/17/are-data-annotations-a-sign-of-bad-design Commented Jan 9, 2014 at 9:01
  • True, but MVC does not validate after each property change, as you explicitly state in your example. MVC will validate the model as a whole. Commented Jan 9, 2014 at 10:21

1 Answer 1

1

You can wrap your classes with proxies, intercept property setters and validate object after each setter invocation. For Castle DynamicProxy this would be:

public class ValidationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();

        if (invocation.Method.IsSpecialName && invocation.Method.Name.StartsWith("set_"))
        {
            invocation.InvocationTarget.Validate();
        }
    }
}

Then you would create models with DynamicProxy instead of operator new:

ProxyGenerator proxyGenerator = new ProxyGenerator();
MyModel model = proxyGenerator.CreateClassProxy<MyModel>(new ValidationInterceptor());

model.Foo = "bar";

model.Foo = SomeMethod();

It's important that all properties of MyModel must be virtual in order for proxy to work:

public class MyModel
{
    public virtual string Foo { get; set; }
}
Sign up to request clarification or add additional context in comments.

Comments

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.