Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>When you have big projects RIA may not be a good idea, for example applications with different layers (Services, Application, Domain, Infrastructure).</p> <p>Some time ago I had to implement Validation in a Silverlight app with complex rules. I was using Self-tracking entities generated with the Entity Framework. And one of my need was to rehuse all the validation code.</p> <p>First I tried to use the EntLib Validation Block and use the same code on both the client and the server. This approach doesn't work as you get some problems as SL and .NET4.0 use different versions of the DataAnnotations assembly.</p> <p>Finally I ended up writing some sort of validation service on the server that returns the errors of an entity if any. Something like this:</p> <pre><code>interface IValidate { IEnumerable&lt;string&gt; Validate(Entity entity); } </code></pre> <p>And then on the Client make the ViewModels implement INotifyDataErrorInfo (this interface supports async validation), so you can validate the entity with the Service and save the errors on the ViewModel.</p> <pre><code>class SomeViewModel : INotifyDataErrorInfo { public Entity Entity { get; set; } public void Validate() { this.ClearErrors(); // this method make the service calls var service = -- service instance --; var errors = -- get errors from service --; foreach (string error in errors) this.AddTopLevelError(error); } {...} } </code></pre> <p>This way all the validation logic lies on the Server and it can change at any time without affecting the client, because all the entities are passed througth this service before being added to a DataBase (if you're using one).</p> <p>The service could also return the errors and the property associated with the error, this way you could get a richer interaction with Silverlight. So the service could be:</p> <pre><code>interface IValidate { IEnumerable&lt;PropertyError&gt; Validate(Entity entity); } class PropertyError { public string PropertyName { get; } public IEnumerable&lt;string&gt; Errors { get; } } </code></pre> <p>Here you can notice that the validation rules could change on the server, and it doesn't matter how this logic is implemented. All this works fine and meets your requeriments, the problem is that Silverlight requires that the object being validated contains all the properties with errors.</p> <p>This is not a common scenario when working with Databases, as you could have for example (and this is a simple model)</p> <p><img src="https://i.stack.imgur.com/uAnFu.png" alt="simple model"></p> <p><em>this model was done using Entity Framework 4.1</em></p> <p>Because if you have a user instance and want to access to the Email property, you'll have to type: user_instance.Person.Email. So the Email property isn't in the user type, and <strong>here is the problem with this solution</strong> because you may want to validate the EMails too.</p> <p>Is this wasn't like this, when you have a ViewModel (implementing INotifyDataErrorInfo) with an Entity (like above) and wants the entity (User in this case) to be validated, you only have to add an error to the property <em>Entity.Person.Email</em>.</p> <p>But the world isn't perfect, so the solution i found was to duplicate each one of the properties to be validated on the ViewModel, something like this:</p> <pre><code>class SomeViewModel : INotifyDataErrorInfo { public User Entity { get; set; } public string Name { get { return Entity.UserName; } set {...} } public string Email { get { return Entity.Person.Email; } set {...} } {...} } </code></pre> <p>This way you can bind the controls to the ViewModels properties instead of the entities properties, but it gets a bit hard to work with the change notifications.</p> <p>You may also want to check: <a href="http://validationtoolkit.codeplex.com/" rel="nofollow noreferrer">this</a> toolkit. It solves this problem defining a wapper to your entity and using <code>DynamicObject</code> simulates an object that has all the properties from the wrapped one. This is a bit slow when working with large ammounts of data, but simplifies the work a lot.</p> <p>Hope this helps.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload