Meaning that the implementation I’m about to show will work just as well on Windows Store apps, so +1 for code sharing!
The demo app is a simple registration form, a new user will be able to enter his name, birthdate and country. We’ll build validation rules on those properties later on. We’ll only have one model class in this app, called Member.
There is some work involved in getting everything setup, don’t worry, it’s hardly rocket science.
We’re going to create a ValidaterFactory. We need this because we’re going to use SimpleIoc to inject the validators into the ViewModels. If you don’t want to do this you can just create the validators and instantiate them whenever you need one, the Codeplex page of Fluent Validation has great documentation on this.
A ValidatorFactory inherits from the ValidatorFactoryBase class included in the library
<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0c98066c-3061-4f46-b941-55c5db0b436d" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">class</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">ValidatorFactory</span><span style="background:#ffffff;color:#000000"> : </span><span style="background:#ffffff;color:#2b91af">ValidatorFactoryBase</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#2b91af">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> ValidatorFactory()</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#008000">//register the Validators</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">SimpleIoc</span><span style="background:#ffffff;color:#000000">.Default.Register<</span><span style="background:#ffffff;color:#2b91af">IValidator</span><span style="background:#ffffff;color:#000000"><</span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000">>, </span><span style="background:#ffffff;color:#2b91af">MemberValidator</span><span style="background:#ffffff;color:#000000">>();</span></li> <li> <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">override</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">IValidator</span><span style="background:#ffffff;color:#000000"> CreateInstance(</span><span style="background:#ffffff;color:#2b91af">Type</span><span style="background:#ffffff;color:#000000"> validatorType)</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">SimpleIoc</span><span style="background:#ffffff;color:#000000">.Default.GetInstance(validatorType) </span><span style="background:#ffffff;color:#0000ff">as</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">IValidator</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">}</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>The constructor of the ValidatorFactory is where I’m registering all validators. You could do this in the ViewModelLocator as well, like any other class / repository / viewmodel but this keeps my VMLocator cleaner and keeps the validation logic a bit closer together.</p> <p>The CreateInstance function needs to be overridden and returns the instance of the requested validator.</p> <h2>Building a validator</h2> <p>Almost there, in this step we’re building a validator for the Member class. A validator inherits from AbstractValidator<T> where T is the class you want to validate.</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c5172fc1-df28-4a4e-8309-74fa189b6cec" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">class</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">MemberValidator</span><span style="background:#ffffff;color:#000000"> : </span><span style="background:#ffffff;color:#2b91af">AbstractValidator</span><span style="background:#ffffff;color:#000000"><</span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000">></span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> MemberValidator()</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">RuleFor(member => member.Name).NotEmpty();</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">RuleFor(member => member.BirthDate).LessThan(</span><span style="background:#ffffff;color:#2b91af">DateTime</span><span style="background:#ffffff;color:#000000">.Today);</span></li> <li> <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>In the constructor of the validator we can finally start to add some rules. In this case we’re saying that the Name property should not be empty and that the birthdate property should be before today’s date.</p> <p>We’ll need to register this class into our IOC, so in ViewModelLocator add this line</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6af0c608-4849-4990-babf-a83b880adc51" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#2b91af">SimpleIoc</span><span style="background:#ffffff;color:#000000">.Default.Register<</span><span style="background:#ffffff;color:#2b91af">ValidatorFactory</span><span style="background:#ffffff;color:#000000">>(</span><span style="background:#ffffff;color:#0000ff">true</span><span style="background:#ffffff;color:#000000">);</span></li> </ol> </div> </div> </div> <p>We pass in ‘true’ as parameter to make sure the object is instantiated at the moment of registration, that way all validators are registered in the IOC as well (as seen in the ValidatorFactory’s constructor).</p> <p>As a reference, these are all the built in validators of Fluent Validation</p> <ul> <li>NotNull </li> <li>NotEmpty </li> <li>NotEqual </li> <li>Equal </li> <li>Length </li> <li>LessThan </li> <li>LessThanOrEqual </li> <li>GreaterThan </li> <li>GreaterThanOrEqual </li> <li>Predicate </li> <li>RegEx </li> <li>Email </li> </ul> <p>Quite an impressive list, and probably most of what you’ll need. Just in case that the one that you need isn’t included, you can build your own, we’ll discuss that in a bit. Let’s get these rules to work first.</p> <h2>Validating data</h2> <p>So we have a factory, we have a validator, all are getting registered in our IOC, time to hook up the ViewModels and getting some validation done. </p> <p>In the MainViewModel we add a property of type Member that we’ll bind against</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:158f3fba-ac57-4ea0-b953-42325ca4f05b" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000"> _newMember;</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000"> NewMember</span></li> <li><span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">get</span><span style="background:#ffffff;color:#000000"> { </span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> _newMember; }</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">set</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">if</span><span style="background:#ffffff;color:#000000"> (_newMember == </span><span style="background:#ffffff;color:#0000ff">value</span><span style="background:#ffffff;color:#000000">) </span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000">_newMember = </span><span style="background:#ffffff;color:#0000ff">value</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000">RaisePropertyChanged(() => NewMember);</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">}</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>Next, we’ll add two fields, one for the validator and one for the save command</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:844028c4-50a1-4b89-af04-0157f46d22d6" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">ICommand</span><span style="background:#ffffff;color:#000000"> _saveMemberCommand;</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">IValidator</span><span style="background:#ffffff;color:#000000"><</span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000">> _validator;</span></li> </ol> </div> </div> </div> <p>Next up is the ICommand property for the Save Command</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e1ddd4b1-15ea-4626-a873-d24b8c0020af" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">ICommand</span><span style="background:#ffffff;color:#000000"> SaveMemberCommand</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">get</span><span style="background:#ffffff;color:#000000"> { </span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> _saveMemberCommand ?? (_saveMemberCommand = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">RelayCommand</span><span style="background:#ffffff;color:#000000">(SaveMember)); }</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>Before we dive into the SaveMember method, we’ll need to do some constructor injection and initialization.</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:ff2ba343-671f-44da-8474-89da5c254e48" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> MainViewModel(</span><span style="background:#ffffff;color:#2b91af">ValidatorFactory</span><span style="background:#ffffff;color:#000000"> validator)</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">NewMember = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">Member</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">BirthDate = </span><span style="background:#ffffff;color:#2b91af">DateTime</span><span style="background:#ffffff;color:#000000">.Today</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">};</span></li> <li> </li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">_validator = validator.GetValidator<</span><span style="background:#ffffff;color:#2b91af">Member</span><span style="background:#ffffff;color:#000000">>();</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>As a parameter we get our ValidatorFactory, using its GetValidator<T> function we can fill up the _validator field. NewMember gets instantiated and the BirthDate property is set to a default of today.</p> <p>And last but not least, the SaveMember method</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dbe44cd5-73f5-477f-9b2d-ceaf9f572dd4" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">void</span><span style="background:#ffffff;color:#000000"> SaveMember()</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">if</span><span style="background:#ffffff;color:#000000"> (IsValid())</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">MessageBox</span><span style="background:#ffffff;color:#000000">.Show(</span><span style="background:#ffffff;color:#a31515">"Registration completed!"</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">}</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"> </li> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">bool</span><span style="background:#ffffff;color:#000000"> IsValid()</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">ValidationResult</span><span style="background:#ffffff;color:#000000"> validationResult = _validator.Validate(NewMember);</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">if</span><span style="background:#ffffff;color:#000000"> (!validationResult.IsValid)</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">ShowErrors(validationResult.Errors);</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">false</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">}</span></li> <li> </li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">true</span><span style="background:#ffffff;color:#000000">;</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"> </li> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">void</span><span style="background:#ffffff;color:#000000"> ShowErrors(</span><span style="background:#ffffff;color:#2b91af">IEnumerable</span><span style="background:#ffffff;color:#000000"><</span><span style="background:#ffffff;color:#2b91af">ValidationFailure</span><span style="background:#ffffff;color:#000000">> errors)</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">StringBuilder</span><span style="background:#ffffff;color:#000000"> builder = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">StringBuilder</span><span style="background:#ffffff;color:#000000">();</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000">builder.AppendLine(</span><span style="background:#ffffff;color:#a31515">"The following errors occured:"</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">foreach</span><span style="background:#ffffff;color:#000000"> (</span><span style="background:#ffffff;color:#2b91af">ValidationFailure</span><span style="background:#ffffff;color:#000000"> error </span><span style="background:#ffffff;color:#0000ff">in</span><span style="background:#ffffff;color:#000000"> errors)</span></li> <li> <span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">builder.AppendLine(</span><span style="background:#ffffff;color:#a31515">"- "</span><span style="background:#ffffff;color:#000000"> + error.ErrorMessage);</span></li> <li> <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">MessageBox</span><span style="background:#ffffff;color:#000000">.Show(builder.ToString(), </span><span style="background:#ffffff;color:#a31515">"error"</span><span style="background:#ffffff;color:#000000">, </span><span style="background:#ffffff;color:#2b91af">MessageBoxButton</span><span style="background:#ffffff;color:#000000">.OK);</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>To validate an instance we call the Validate function on a validator for that type, in this case ‘Member’. That function returns a ValidationResult. ValidationResult contains a bool property IsValid and a list of errors that it found.</p> <p>We iterate over this list and put every error into a StringBuilder to get a nice error message in a messagebox. If I try to save with an empty name and today’s date as birthdate I get this.</p> <p><a href="http://i39.tinypic.com/68bg2b.jpg" target="_blank"><img src="http://i39.tinypic.com/68bg2b.jpg" width="194" height="323" /></a></p> <p>Our validation is working! But those messages could be a bit better. Fluent Validator provides us with options to adjust the property name or the entire message. Change the constructor of the MemberValidator to this</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:98785c36-86cd-48bc-89fb-8e26edfec97d" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> MemberValidator()</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">RuleFor(member => member.Name).NotEmpty().WithMessage(</span><span style="background:#ffffff;color:#a31515">"You should enter your name"</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">RuleFor(member => member.BirthDate).LessThan(</span><span style="background:#ffffff;color:#2b91af">DateTime</span><span style="background:#ffffff;color:#000000">.Today).WithName(</span><span style="background:#ffffff;color:#a31515">"date of birth"</span><span style="background:#ffffff;color:#000000">);</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>On line 3 we use .WithMessage(“”) to replace the default message by whatever we want. Line 4 replaces the default name of the property, the result is similar yet slightly different</p> <p><a href="http://i43.tinypic.com/jts28l.jpg" target="_blank"><img src="http://i43.tinypic.com/jts28l.jpg" width="199" height="332" /></a></p> <h2>Adding a custom validator</h2> <p>Let’s say that we want to add validation to the Country property. This property must have a value of either ‘Belgium’, ‘Netherlands’ or ‘Luxemburg’ (this is called the BeNeLux). Obviously, this isn’t included as one simple validator so we’ll just build it ourselves.</p> <p>We’ll need a class that inherits from PropertyValidator and overrides the IsValid function.</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:fcd2aa55-3136-4106-bf6e-bbbaa174e0e6" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">class</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">CountryMustBeInBenelux</span><span style="background:#ffffff;color:#000000"> : </span><span style="background:#ffffff;color:#2b91af">PropertyValidator</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#2b91af">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> CountryMustBeInBenelux()</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">: </span><span style="background:#ffffff;color:#0000ff">base</span><span style="background:#ffffff;color:#000000">(</span><span style="background:#ffffff;color:#a31515">"{PropertyName} is not a Benelux country"</span><span style="background:#ffffff;color:#000000">)</span></li> <li> <span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"> </li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">protected</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">override</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">bool</span><span style="background:#ffffff;color:#000000"> IsValid(</span><span style="background:#ffffff;color:#2b91af">PropertyValidatorContext</span><span style="background:#ffffff;color:#000000"> context)</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">if</span><span style="background:#ffffff;color:#000000"> (context.PropertyValue == </span><span style="background:#ffffff;color:#0000ff">null</span><span style="background:#ffffff;color:#000000">)</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">false</span><span style="background:#ffffff;color:#000000">;</span></li> <li> </li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">string</span><span style="background:#ffffff;color:#000000"> country = context.PropertyValue.ToString().ToLower();</span></li> <li> </li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">return</span><span style="background:#ffffff;color:#000000"> country == </span><span style="background:#ffffff;color:#a31515">"belgium"</span><span style="background:#ffffff;color:#000000"> || country == </span><span style="background:#ffffff;color:#a31515">"netherlands"</span><span style="background:#ffffff;color:#000000"> || country == </span><span style="background:#ffffff;color:#a31515">"luxemburg"</span><span style="background:#ffffff;color:#000000">;</span></li> <li> <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>The string that we pass in to the base constructor is the default message that will be used for this validator. The IsValid function takes a parameter of PropertyValidatorContext. This will contain the property that we want to validate and its value.</p> <p>Next, in the MemberValidator constructor we add the validation for the Country property</p> <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:7e36e539-0b3c-4d79-935c-45a598fcd64a" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> MemberValidator()</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li> <span style="background:#ffffff;color:#000000">RuleFor(member => member.Name).NotEmpty().WithMessage(</span><span style="background:#ffffff;color:#a31515">"You should enter your name"</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">RuleFor(member => member.BirthDate).LessThan(</span><span style="background:#ffffff;color:#2b91af">DateTime</span><span style="background:#ffffff;color:#000000">.Today).WithName(</span><span style="background:#ffffff;color:#a31515">"date of birth"</span><span style="background:#ffffff;color:#000000">);</span></li> <li> </li> <li style="background: #f3f3f3"> <span style="background:#ffffff;color:#000000">RuleFor(member => member.Country).SetValidator(</span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">CountryMustBeInBenelux</span><span style="background:#ffffff;color:#000000">());</span></li> <li><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div> <p>As you can see we need to use the SetValidator function to add our own validator. </p> <p>The result now is this (I’ve entered a name and a valid birthdate to clean up the error list a bit)</p> <p><a href="http://i39.tinypic.com/1zdv6v.jpg" target="_blank"><img src="http://i39.tinypic.com/1zdv6v.jpg" width="231" height="385" /></a></p> <p> </p> <h2>Conclusion</h2> <p>In this article I’ve discussed the use of Fluent Validator to do data validation in Windows Phone 8 apps. I’ve used the portable version of the library so these examples should work just fine on Windows 8 as well.</p> <p>The Fluent Validator library has many more options than what I’ve discussed here and they are all well documented, head over the the <a href="http://fluentvalidation.codeplex.com/documentation" target="_blank">Codeplex</a> page if you want to do more and deeper validation.</p> <p>The sample project can be found on my <a href="http://sdrv.ms/1barHvp" target="_blank">SkyDrive</a></p>
This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.
Leave a Comment