Entity validation, unit testing and MVC 3 with Fluent – RuleSets and Predicates

Morning all,

I have been looking at validation for my current project. We are building an MVC 3 site that calls a wcf service later that is wrapped around Crm 2011.

Initially I was looking at data annotations out of the box. These work really well and MVC 3 works seamlessly with these with client validation and unobtrusive JQuery. 
 When  I came to look at rulesets however it seems a lot more complicated. I them stumbled upon Fluent validation:
This is a very user friendly clean way of writing validation on your entities in the same way that data annotations are written. The difference came when I started to look at rule sets which you will see in my attached screen shots.

Firstly I defined 2 classes in my domain model. Thsese are called ContactForValidationPOC and AddressForValidationPOC as shown below:
 ———————————————————————————————————-
As you can see there are no data annotations and ContactForValidationPOC has a complex property of Addresses.

We are going to write some rulesets that will validate the contact for a STAFF ruleset and a public ruleset. (Note that there are not real world validation needs as of yet,it’s just proof of concept code.)
You will notice that at the top of the ContactForValidationPOC class we have an attribute shown as follows:
[Validator(typeof(ContactValidator))] 
This tells the class that there is a validator class call ContactValidator somewhere.
Also please note that I have referenced the correct Fluent  validation dlls in my project. 
You can find the details of this here:
http://fluentvalidation.codeplex.com/ 
So back to the ContactValidator. Here it is:
You can see that we have 2 rule sets. The first is a staff rule set and the second is a public rule set. 
They are quite similar and the only difference really is that the Age must be over 18 for a staff member. 
Both rule sets also use a .Must predicate validator. 
This is a great place to put more complex logic.

Here we need to ensure that there is at least 1 address in the Addresses collection that is marked as IsPrefferedAddress.
Ok, so that is all done, now we need to unit test or validation rules.  
 
So I have a unit test written here. Firstly I set up a new ContactForValidationPOC entity and add a couple of addresses to it. 
I then call Validate on it and ask it to validate using the Staff rule set. After validation we check that the ValidationResult (result) is valid 
and then do a simple check for the number of validation errors. Obviously my test could be more detailed in a real world example. 
As I debug through my test I can see that my entity is not valid (IsValid = false
and it has a collection of validation errors on it.


This is good as we didn’t enter a first name, our Age is under 18 and we set all AddressForValidationPOC’s in the Addresses collection to IsPrefferedAddress = false.
Ok so we now know that our validation is working correctly on the server side.
We haven’t even touched the MVC code yet.

I have whipped up a quick MVC controller with a view and have disabled the settings 
in the web.config that make client side validation work as shown in the following picture:
Note: they should be set to false to prove that server side validation is still working correctly now that we are validating through MVC.

Here are my controller and view: 
Note: I have just forced 2 addresses into the ContactForValidationPOC entity to make things easier, these are both set to IsPrefferedAddress = false 

Here is the view that kicked off the validation:


You can see that, when debugging the controller we get the same validation results. 
IsValid = false and a number of errors relating to our Staff rule set.

Note that in our controller we could have control over what rule set is loaded if we so desired:


We could use some logic to check what type of rule set to load, staff or public.

Now I will change the web.config setting to ensure that client side validation gets included:

We now can fire up the view in a web browser and see client side validation in action:

Well that is it, a high level explanation of domain entity server and client validation using Fluent, unit tests and MVC.

Some positive points:

Some possible negatives:

  • Only the following validators are supported on the client:
    – NotNull/NotEmpty

    – Matches (regex)
    InclusiveBetween (range)
    – CreditCard

    – Email

    – EqualTo (cross-property equality comparison)

    – Length
  • Cant think of any more at the moment.

I hope this was helpful.


RuSs


Advertisements

EDMX or DbContext API

Hi all,

I have used EF for a while. I am used to using an EDMX file for my model. I have also recently used Code First and the DbContext API and I really like this.
Last night I started building an app. and was thinking, am I starting on the right foot? Do I use EDMX or DbContext API? If the thing i’m building turns out to be big, will I have chosen the right technology.

What if I use DbContext API and get it to generate my database. Obviously I don’t want this to keep generating my database down the track when i’m at a stable point in development (or do I?). Then if I want to tweak my database or domain model will all the strings come un done?

The DbContext API is a simplified version. Will it do everything I need? I dont think ill need stored procedures as I can do everything with linq.

So my real question is. If I am building something that is serious and out there is the real world and it may turn out to require some complex coding, which way do I go? EDMX or DbContext API?

Is EDMX now old school? 
Comments / thoughts?

RuSs

A small update

Morning all,
Well it’s been a while since I posted in my blog that i’m sure no one reads! I have finally got used to living in Melbourne and have started enjoying it more now that the weather is getting better.
I will hopefully be posting some interesting stuff on MVC up here is the next few weeks.
Here is a list of things I have looked at in the last few weeks.
  • MVC(3) – I have been trying to get around to getting up to date on MVC for years. Ever since I tried and failed to read Martin fowler’s book on design patterns (http://martinfowler.com/eaaDev/uiArchs.html).
    Well finally I have got around to it and I love it. Combined with the Entity Framework edmx or code first it is such a great way to work. This is the way, for most sites, the web should be built. No hidden viewstate, no nightmare page load order and code that you have total granular control over. Awesome!!
  • Razor view engine – initially it looks dodgy but after a little playing around it’s cleaner and easier to read than traditional asp.net forms. One thing I have learned about Razor is, if it looks messy and hard to read, then you probably have started putting business logic where it should not go.
  • Unit testing and TDD with MVC – Combined with Ninject and Moq this is easy. You can directly test your controllers. Compare this to ASP.NET web forms where your controller was, sort of, your code behind. You needed httpContext etc. Now you can test just your controller logic without other webby things clouding the test.
  • JQuery – ok so this is not new but im loving it so far.
  • NuGet – the NuGet package manager is quite cool. NuGet is a Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects that use the .NET Framework. When you add a library or tool, NuGet copies files to your solution and automatically makes whatever changes are needed in your project, such as adding references and changing your app.config or web.config file. When you remove a library, NuGet removes files and reverses whatever changes it made in your project so that no clutter is left.
    For example if you need to get the latest JQuery libraries into you solution you open Tools > library package manager > package manager console and type:

    PM> Update-Package jquery

    PM with auto update your JQuery to the correct version. Note that your references inside Views > Shared > _Layout.cshtml (for example) will not be auto updated.

Well, I know this is a bit of a lame post but it was more to get me back into the habit of writing on my blog. I hope to come up with some more interesting stuff soon.

RuSs