Action based ViewModel and Model validation.

A while ago, WPF guru Josh Smith blogged about using the ViewModel to provide a first line of defence when validating data using the MVVM model. In his article, Josh talks about having the ViewModel perform some validation before passing this back to the underlying model. In his example, he uses a string property to perform initial validation on a UI element before it updates an integer, so that the user can type in abc123, but the model only gets updated if it’s a valid number. Please read his article here for more information.

While I liked Josh’s implementation, there was something nagging at me – his implementation relied heavily on switch statements in the property validation, and this really goes against the grain for me. Thinking about this for a while, it seemed to me that we could achieve a similar implementation and, at the same time, provide a nice level of abstraction. To do this, we can use the Action<T> delegate to nicely decouple the validation from the actual property validation. The following class provides the underlying mechanism for separating the validation.

ModelBase class

Now, both the ViewModel and Model classes can derive from this class and get access to the same functionality. The following class demonstrates this:

Person class

The interesting bit of this class is how simple the implementation of IDataErrorInfo here actually is. All the “magic” has been taken care of by creating an Action that will invoke the ValidateAge method. By calling AddValidation on the base class and passing the name of the property that the validation applies to, we can automatically hook up to perform the validation.

You can download the sample project here. Be sure to change the extension back from Doc to Zip and then decompress it.

23 thoughts on “Action based ViewModel and Model validation.

  1. Steve

    Why don’t you move the validation to the base class, so that all classes get it?

    No need to pass instance when it’s not a static method so you’ll have this anyway.

    1. peteohanlon

      Steve – the next stage of this is to move the validation out altogether. In a future update, I’ll demonstrate using IoC to decouple the validation altogether.

    1. peteohanlon

      Mike, now that I’ve had a chance to read your article it seems to me like we’re looking at tackling two different problems. In the case of an Aspects framework, the validation is known up front and not subject to change. What I’m going to be looking at is the ability to add new rules “on the fly” without having to recompile the application. We do have applications where this would be useful.

  2. Mike

    No, you can replace/augment validation at runtime programmatically or by configuration. You’re not limited to attributes – they’re really only of use for coding-contracts or simple business rules validation. For more complex validation you’d probably want to register lambda functions on Types, Properties or Method Parameters. There’s a more detailed summary of features here http://thetreeknowseverything.net/2009/01/09/introducing-validation-aspects/

  3. Dave

    Interresting approach Pete, thanks for sharing that. But it feels quite strange to specify the validation rules twice, first in the entity business rules and second in the viewmodel.

    I use a much simpler approach, with a very simple validation engine that uses predicates as rule methods:
    BusinessRules.Register(x => x.FirstName).IsNotNullOrEmpty();
    BusinessRules.Register(x => x.Age).IsGreaterThanOrEqualTo(18);
    BusinessRules.Register(x => x.Age).IsLessThan(100);

    Each validation method is actually an extension method that wraps the appropriate validation predicate:

    public static IBusinessRule IsGreaterThan(this IBusinessRule businessRule, V comparisonValue) where V : IComparable {
    businessRule.Predicate = x => x.CompareTo(comparisonValue) > 0;
    businessRule.ErrorMessage = string.Format(ValidationErrors.IsGreaterThan, businessRule.Name, comparisonValue);
    return businessRule;
    }

    Furthermore, in the entity property setters i use a SetProperty function which handles the illegal input.

    1. peteohanlon

      Thanks for the comments Dave – to answer the unspoken question about the validation rules, they aren’t specified twice – they are different rules doing different things. The ViewModel validation is the first stop to ensure that we don’t try to pass a string into the age field in a model itself. In a future issue of the code, I’m going to show how to bind the CanExecute of a command into this to see whether or not an item can be saved based on the validation.

  4. Tomas Elison

    I am just about to write a small validation engine for my current project and I was thinking along the same lines as this. I love how you can so easily hook it up to IDataErrorInfo while still maintaining a nice structure in the background.

    Actually I think what Dave is outlining looks very interesting too. However I can’t really grasp the full idea of it. Sorry for hogging your blog Pete, but Dave I would love to see some more of your idea. If you don’t wanna publish more here, feel free to contact me by email at tomas at specopssoft dot com.

    1. peteohanlon

      Tomas – I’ve no problem with you “hogging the blog”;->. Dave’s approach is amazing, and I’m looking more into it myself. As for hooking into IDataErrorInfo while maintaining structure – this is a real question of programming style; I feel that switch statements are way overused and there are fantastic mechanisms and techniques that can be used to circumvent them.

      Thanks for your comments.

  5. Dave

    Tomas, my approach is not that different from Pete’s; it’s just that I use generic predicates as validators as opposite to Pete’s generic actions. Instead of creating a specific function (or class) for each validator, I use some extension methods which can be then reused in various projects. Indeed using lambda-based predicates gives you that flexibility I always missed in .NET
    I will try to find some time later tonight, to create a proper post about it and attach also a small example.

    Dave

    1. Jammer

      Dave – did you get a chance to put a simple example together? I’m interested in seeing a bit more of this as well as Tomas.

  6. Robert Gaut

    Very nice! I just changed what I was doing with your approach and like it so much more now. Thanks for the great post and elegant solution.

  7. Christoph

    Pete, I’m using the DataGrid. Therefore, I must use the DataGrid.RowValidationRules, wich works with an seperate class, wich does not have a reference to the ViewModel (I can’t find out, how to determine the VievModel in this class).
    Have you any idea, how to handle the DataGrid in an ViewModel-based validation?

  8. Pingback: How to: Good examples of MVVM Template | SevenNet

  9. Pingback: Good examples of MVVM Template - TecHub

Leave a comment