Please note… this post is out-dated and all of the madness below is no longer needed in order to implement Async Validation with RIA Services. Please see the new post for the current approach.

The Birth of QuickSilverlight.Validation

Over on the .NET RIA Services forums, “SilverlightRIA” asked about performing asynchronous validation with .NET RIA Services and the Silverlight Toolkit’s DataForm. He wanted to intercept the Commit from the DataForm and invoke his async validation, integrating the results into the DataForm’s validation UI. This was an interesting scenario so I put some time into a solution for it this week. The result is a library that I’m calling QuickSilverlight.Validation.

Integrating Validation Results into DataForm

It took a few hours of digging to find a way to get the async validation results to integrate into the DataForm’s UI. Here’s what DataForm does when you commit edits:

Loop through all of the fields, calling UpdateSource on each field’s binding. This will call the setters for all properties, which triggers validation.

If validation fails on the property, the field is highlighted, an item is added to the validation summary, and clicking that summary item will put focus into the affected field.

If validation succeeds on all of the properties, then entity-level validation is invoked.

If entity-level validation succeeds, then the entity is committed.

To integrate async validation results into the DataForm, it was imperative to have the property-level validators fail validation, producing the messages retrieved from the async validation. Here was my starting idea for how to get this going:

Apply an [AsyncValidation] attribute to the properties that can have async validation results applied to them.

Make the AsyncValidation attribute return a ValidationResult that comes from an async validation execution.

The trick of course is to fetch the async validation results before the properties are validated through DataForm. Here’s how I pulled that off:

Handle the DataForm.EditEnding event, which is raised before validation occurs.

Within that event handler, call DataForm.ValidateItem() to see if the item is valid with respect to its client-side, synchronous validators. Make the AsyncValidation attributes return Success at that stage.

If valid, initiate the call to get async validation results, and cancel the EditEnding event using CancelEventArgs.Cancel = true.

This prevents DataForm from progressing on to actually commit the edit.

When async validation completes, store the results for access by the AsyncValidation attributes.

Within the DataForm.EditEnding event handler, recognize that async validation result processing is in process, and don’t do anything to change the DataForm’s behavior. Let it validate the properties and object as it normally would, committing the entity if everything is valid.

At this stage, make the AsyncValidation attributes respect the async validation results, generating validation errors as appropriate.

When this is finished, clear any stored async validation results for the entity, so that the next time it’s validated, our async validation results won’t interfere with client-side synchronous validation.

Yep; that was a mouthful. But I have two flavors of good news. First, I am going to make the source code for all of this available. Second, I’ve packaged the code up into a library that allows you to get all of this behavior for next to nothing. We’re actually not yet finished though, as there were a few more details to work out to finish the end-to-end solution.

.NET RIA Services Integration

With .NET RIA Services, we want to apply the [AsyncValidation] attribute to the entities on the server, and have that metadata flow through to the client. We also want the same validation to execute on the server, but synchronously. Let’s first look at executing the validation on the server.

.NET RIA Services includes an updated System.ComponentModel.DataAnnotations assembly. One of the new features in that assembly with the July 2009 Preview is an interface called IValidatableObject. This interface only applies to the desktop version of this assembly—it’s not included in the Silverlight subset of the assembly. Here’s the definition of the interface:

The great part about this interface is that it allows not just a single ValidationResult, but an IEnumerable<ValidationResult> to be returned from the Validate method. .NET RIA Services respects this interface when it performs server-side validation of your entities, so all we need to do is implement this interface on our entity, and collect our results from within the Validate method. Instead of calling our process asynchronously, we call it synchronously, and we return the list of results.

Now, for applying the [AsyncValidation] attribute to our entities, I’ve created a server-side AsyncValidationAttribute class. Interestingly, this attribute doesn’t derive from ValidationAttribute like our Silverlight attribute did. On the server, this attribute isn’t going to perform any validation, since it’s all done in one step for IValidatableObject. So, this attribute is just a marker to allow metadata to flow through to the client-side proxy classes. The namespace and class name match what’s on the client, and .NET RIA Services will automatically flow this metadata through for us.

Calling ValidateProperty() for Async Validation

Things seem to be rolling pretty smoothly at this point, but there’s one problem left that is preventing this from working. This whole idea is based on the DataForm calling UpdateSource on each field’s binding, and having that trigger property-level validation. But this doesn’t work because of the way the entity’s property setters are generated in the client-side proxies. Here’s a sample property setter that .NET RIA Services generates, with our [AsyncValidation] attribute nicely applied:

1: [AsyncValidation()]

2: [DataMember()]

3:publicchar Gender

4: {

5: get

6: {

7:returnthis._gender;

8: }

9: set

10: {

11:if ((this._gender != value))

12: {

13:this.ValidateProperty("Gender", value);

14:this.OnGenderChanging(value);

15:this.RaiseDataMemberChanging("Gender");

16:this._gender = value;

17:this.RaiseDataMemberChanged("Gender");

18:this.OnGenderChanged();

19: }

20: }

21: }

The detail that tripped me up is that ValidateProperty() is only called if the property value has changed. But in our case, we trigger the UpdateSource() calls twice – once for the standard validation, then a second time after we receive the async validation results. Upon the second execution of this, the property value hasn’t changed, and ValidateProperty() is not called. Somehow, we need to force ValidateProperty() to get called for each field displayed by the DataForm. CodeProcessor (and my co-worker Warren Aldred) to the rescue!

.NET RIA Services allows you to decorate your DomainService with a CodeProcessor. This CodeProcessor can hook into the code generation for the client-side proxies, and manipulate the CodeDom of the generated code. We want to manipulate any properties marked with [AsyncValidation] so that the property looks like this:

1: [AsyncValidation()]

2: [DataMember()]

3:publicchar Gender

4: {

5: get

6: {

7:returnthis._gender;

8: }

9: set

10: {

11:// Validate this property even if the value hasn't changed, so that the async validation can occur properly

12:this.ValidateProperty("Gender", value);

13:

14:if ((this._gender != value))

15: {

16:this.OnGenderChanging(value);

17:this.RaiseDataMemberChanging("Gender");

18:this._gender = value;

19:this.RaiseDataMemberChanged("Gender");

20:this.OnGenderChanged();

21: }

22: }

23: }

It’s a very slight modification. We just move the ValidateProperty() call to happen before we check for a value change. And the good news is that I have packaged this CodeProcessor up with my QuickSilverlight.Validation library, so you don’t even need to mess with CodeDom. I built an AsyncValidationCodeProcessor that can be used either directly, or you can compose its functionality into another CodeProcessor if you’re already using one. I respected composition over inheritance here, so that you could apply async validation even if you’re already manipulating the CodeDom.

Applying [AsyncValidation] to an Entity

Since I was manipulating the CodeDom, I figured I might as well add one more feature related to the [AsyncValidation] attribute too. If you want to turn async validation on for all of your entity’s properties, you can simply apply the [AsyncValidation] attribute to the entity class itself, and the AsyncValidationCodeProcessor will explode this onto all properties that make calls to ValidateProperty().

How to Use QuickSilverlight.Validation

Now that we have designed a working solution, let’s look at what you need to do to get async validation working on your entity, using QuickSilverlight.Validation and the AdventureWorks Employee entity. For my example, I added a stored procedure to the AdventureWorks database:

If you are already using a custom CodeProcessor, then just hook the 2 together by calling the AsyncValidationCodeProcessor.ProcessAsyncValidationProperties method from within your CodeProcessor.

Step 2: Implement IValidatableObject

Using a partial class for your entity on the server, implement this interface to get validation results to be returned as part of the entity-level validation. This is where I call my ValidationService.ValidateEmployee method from the server-side validation.

Step 3: Apply [AsyncValidation]

You can apply this attribute either to the entity class or to specific properties. In my case, I am only producing async validation errors for the Gender and MaritalStatus properties, so I will only apply the attribute to those properties. Using the EmployeeMetadata class, I apply the attribute to the 2 fields that correspond to the desired properties.

1:internalsealedclass EmployeeMetadata

2: {

3: [AsyncValidation]

4:publicchar Gender;

5:

6: [AsyncValidation]

7:publicchar MaritalStatus;

8: }

(I’ve trimmed out the unrelated code from this snippet)

Step 4: Implement IAsyncValidatableObject on the Client

This article hasn’t yet discussed the details for how an entity on the client will actually perform its async validation. For the most part, this will be domain specific. But the solution integrates with your domain-specific validation by using an interface called IAsyncValidatableObject. Note that this interface is NOT part of DataAnnotations, but rather a custom interface created solely for QuickSilverlight.Validation.

1:namespace QuickSilverlight.Validation

2: {

3:/// <summary>

4:/// Interface to indicate that an object supports asynchronous validation.

5:/// </summary>

6:publicinterface IAsyncValidatableObject

7: {

8:/// <summary>

9:/// Method called to invoke the asynchronous validation operation.

10:/// </summary>

11:/// <param name="userState">

12:/// State information that must be provided to the <see cref="AsyncValidationCompletedEventArgs"/>

13:/// used on the <see cref="AsyncValidationCompleted"/> event.

14:/// </param>

15:void ValidateAsync(AsyncValidationState validationState);

16:

17:/// <summary>

18:/// The event to raise when asynchronous validation is completed. The

19:/// <see cref="AsyncValidationCompletedEventArgs"/> must be given the validationState provided to

ValidateAsync receives an AsyncValidationState object. This object is required to be passed into the AsyncValidationCompletedEventArgs constructor. This is the glue that holds the end-to-end process together.

AsyncValidationCompletedEventArgs accepts the IEnumerable<ValidationResult> produced by your validation. So you must project whatever type of results you get into an enumerable of ValidationResult instances. Be sure to provide the array of member names as the second parameter in the ValidationResult constructor.

I chose to implement ValidateAsync explicitly, so that it wouldn’t clutter the API for my Employee entity.

Step 5: Enable Async Validation on the DataForm

As mentioned very early on, this solution relies on subscribing to the EditEnding event of the DataForm. Attached Behaviors save the day here. The QuickSilverlight.Validation library includes an AsyncValidation class that takes care of all of the logic described for bending the DataForm to our will. This class includes an attached property called Enabled. By setting it to true for a DataForm, it will subscribe to the EditEnding event and ensure that the async validation is processed.

Here’s what you need to do in your XAML to enable async validation for a DataForm:

1:<df:DataFormx:Name="EmployeeForm"AutoCommit="False"

2:qsv:AsyncValidation.Enabled="True"/>

Yes, seriously, that’s it! Just set AsyncValidation.Enabled=”True” and the DataForm will behave as we need. Of course, setting Enabled=”False” will disable the behavior by unsubscribing from the EditEnding event. There’s no code required in the code-behind to make this work either.

QuickSilverlight.Validation Library

This library includes 2 assemblies: QuickSilverlight.Validation for the Silverlight side of things; and QuickSilverlight.Validation.Web for the server side of things, to integrate with .NET RIA Services. On the client side, there’s no dependency on .NET RIA Services. So this can also be used for classes that were not generated by .NET RIA Services.

Your Comments.

Absolutely fascinating Jeff. A tour de force. I'm looking forward to looking at the code as soon as I can.

It also reveals to my jaundiced eye flaw after flaw of the present Silverlight validation design.

I'm not blaming you, btw. You're just trying to make the best of the situation. I'm about to lay some heavy blows. I want to be respectful. I know you've put careful thought into this and what you are doing is not stupid.

But I have to share my concerns which are, in no particular order...

Why does DataForm call the setters for all properties as if that were always harmless? It so happens that setters of RIA Services generated entities bail out if the value is unchanged. But what if the objects aren't RIA Services objects? Sure setters are supposed to be simple ... but it's an intrusive assumption. And what is the difference if the object does or does not implement IEditableObject?

I have to guess. We know Silverlight can run the validations for all of the properties independently of calling the setters; that is what happens when you validate the object as a whole directly with ValidateItem(). I figure that the authors decided to tie the display of property validation failures to exceptions thrown in a property setter. There is plumbing for that in Silverlight (and WPF). If I'm right, they are calling setters for a side-effect in the UI.

That is just horrible. I"ve learned to live with it but never to love it. But now the implications are really ugly. Exhibit 'A': the shenaigans you go through to defeat/cope with property setting (e.g., moving the validation invocation above the "no change" test inside setter).

The UI implications of validation failures should be independent of the validation mechanism. I should be able to validate the entity and give the validation results ... with information about the properties associated with each validation result ... to something that can be expressed in the UI.

I'm not saying it is the "right way", but this was at least possible with IDataErrorInfo ... which has yet to find its way back into Silverlight. I'm not the only one to complain about its absence. And if they every get around to doing it right, they'll help me live in an async world by giving me the ability to tell the UI "Go check IDataErrorInfo again for all the properties you know about"). I admit I haven't really thought this through. But we need better.

Next, your scheme works during commit, but what about at the time the property is set? The only good reason for invoking validation from within a setter is to give "immediate" feedback on set... rather than wait until the whole entity is validated. I don't see a mechanism here for dealing with async property validation at the moment the value is set.

Ideally, you might respond immediately with a "pending validation" result (which may have no UI effect). Then, whenever you do know, you come back and update the property's associated validation display. Don't see anything like that here. Yes, it's a tough problem. Rocky tackled it in CSLA for SL, btw.<< part one of three>>

<<part two of three>>Next, following your example we must modify the entity heavily - on server and client - to introduce async validation. I shouldn't have to touch my object. This is more kruft and magic. Look at how much persistence/async awareness code creeps into your Employee during implementation of IAsyncValidateObject. Jacking the CodeProcessor "to manipulate the CodeDom of the generated code" ... this just makes me cringe.

One consequence: I cannot know, apriori whether a property always will be validated on set or only if set with a different value. Before you jiggered the code, it would not be validated if I set the property to its current value; after you jigger the code, it will validate even if I reset the value to its current value. Is that OK? Who knows?

Next, my UI must know whether I've got async validations. You've added an attached behavior to the DataForm that I must set to indicate if the entity has (or does not have) async validations..That's another small way I can screw up ... as more business logic intrudes into my XAML. I guess I should just always set the attribute for async "just in case".

Next, after you get the AsyncValidation results you squirrel them away somewhere so you can pick 'em up later and clear them later still. I haven't looked yet but it seems as if the async validation is rotating its internal state between returning "OK' (pass 1) and returning validation result (pass 2) before going back to the pass 1 state after all validation results have been consumed. Race conditions are waiting for you.

Next, my object is getting harder and harder to test. I'm sure that it was a demo'ers shortcut the way you "new"-ed up the ValidationService() in your Employee (both server and client versions ... that you have two of them is yet another complexity). But someday you have to think about how you're going to get a pluggable service into the Employee at test versus runtime.

It means also that the developer will have to write an interface on that service which every entity will have to know. That interface will grow as you add async validation methods and the arguments are going to be a lot more complicated than just the strings you show here. Are you going to have one service for all entity types or different services for each type? The implications are ugly either way.

<<part 3 of 3>>Now, to be fair, async validation throws a wrench into the works anyway you look at it. It's tough.

My preference would be to finesse it somehow. I'd try to separate the commiting of the form from the async validations and clearly indicate to the user that the validity of the entity was provisional.

If you have to do it, you must feel that the user has to know now that something is wrong. You must believe that the user would not go on if she knew that a particular validation ... which could only be performed at the server ... would fail to pass.

What you want is synchronous behavior ... you don't want the user to be able to move on until the validation is complete. In WPF you'd do as you are doing on the server in your example ... you'd make the validation synchronous and the UI would freeze until the validation was completed.

Obviously you have to validate asynchronously in Silverlight. I think you want something like this:

- Intercept the EditEnding

- Validate the object, receiving a set of validation results

- If any of those validation results are asyn results that have not completed, you want to stall the UI giving the user the option to cancel the commit.

- When all validation results (including async) are back, then you tell the UI.

- The UI knows how to express failed results on screen; it doesn't rely on the special binding sauce for property exceptions.

- If all is good, you commit the entity.

Too bad you can't do this. As I said, you are up against a mistaken design IMHO.

BTW, when I say "stall the UI", I mean it in the same way that we stall a Silverlight UI while fetching data. Typically done with some kind of "busy screen" that prevents the user from interacting with the UI.

Why? Because you want to prevent the user from moving away from the data form while you're validating. I don't think setting "CancelEventArgs.Cancel = true" is sufficient. That merely unlocks the form for more editing. What stops her from changing the marital status again before the async validation returns?. No ... you have to prevent further data entry while you await validation results. And you probably have to prevent the user from leaving the form too. If you do otherwise, you risk confusing the user about whether her changes are good; no use telling her they're bad when she's already moved on to the next employee.

As I mentioned somewhere in here, I know that Rocky has addressed this problem in CSLA Silverlight. I don't know precisely how and I'm not sure what I'd think of it. Just wondering if you looked.

Finally, I want to commend you on this post. It's thoughtful, intelligent, and there is clearly a lot of work here.

Wow, thank you Ward! I really appreciate the extremely thorough review and feedback. You'll forgive me for not responding back point by point. :-)

Before an item can be committed, it's necessary to call all of the property setters, passing in the current values. Consider the case when the item was constructed with a valid property value, but then the user edited the field, changing it to an invalid value. In this case, the property setter was called when the value was edited, throwing an exception from ValidateProperty(), and the item's actual property value was not updated. When ValidateItem() is called in this case, the item seems to be in a valid state because all of the properties check out just fine, yet the form reflects the bad values. The commit would be successful, but not using the values the user entered. This is the primary requirement for invoking all of the property setters again, and by good design, property setters should not have side effects, so it should be harmless to call them.

I do concede that I should be able to integrate my field-level errors with the UI more easily than re-triggering the UpdateSource() calls though. I plan to discuss this with the DataForm crew.

As far as property-level async validation, I put a lot of thought into it. I had a few folks mention this during the week too, with Glenn being the first to request it. But I didn’t include it in this round as it was beyond the scope of what was asked for on the forums. I built my scenario and solution to meet the needs as closely as possible, and figured I could do another round of work on this if there was good reason to. Additionally, as you mentioned, the UI implications for async property-level validation are much more critical. I think that solutions could be developed, but perhaps not using DataForm—I think something more custom would be appropriate if you want to have that much control over your UI—or at least template the DataForm so that you can really take control.

On the UI front; I did try to apply effects to the UI while waiting for validation. But ultimately, I decided that anything I would do would only be satisfying to me—others would certainly want different effects. Without taking the effort to provide hook points and properties to control how the UI should be affected, I erred on the side of doing nothing at all rather than doing something that couldn’t be controlled. Ostensibly, one could still add the effects they desire by handling events on the DataForm and adjusting the UI as they wish.

I didn’t think the amount of code incurred on the entity was too bad. Implement an interface on the server and client, to perform entity-level validation, returning (or raising an event with) the results. I wasn’t sure how else you would apply entity-specific logic for getting validation results, so I’d love to hear any suggestions you have. The attributes are no different from any other validation attribute you'd apply.

It was unfortunate that I had to mess with the CodeDom stuff. This sparked some conversations in the office yesterday, and I believe some details related to this will come under review again, but I don’t know at this point if the generated properties will change form.

As far as the race conditions et al, I did my best given the constraints I had. I beat up on it and ended up trying several different approaches, and I think what I have is pretty solid as far as preventing race conditions. There are some implementation details in the AsyncValidation class that take care of this, but I didn’t call them out in the post. But if you can find a condition I’m not handling, please let me know!

Thanks again for the great feeback—not only on this effort, but on our validation stack as a whole. It’s a challenging space, and I enjoy working in it.

Your scenario has me puzzled. I'm persuaded the problem is in how the control responds to a disconnect between the visual state (showing bad value) and the object state (retaining a good value). If SL implemented IDataErrorInfo (or equivalent) this could be managed without calling setters. Even as it is today it could be so: the control could compare the result of calling getters with what appears in the control (making use of the converters of course); tricky to be sure ... but better than calling setters.

Part of my point is that this is all too baroque. Commit should validate the item, the results of item validation should tell us about which properties are invalid (through some association of validation results and property triggers), and the control should behave accordingly. Agreed this doesn't address the disconect between visual state and object state ... but I don't think calling setters is the way to do it.

As for setters not having side-effects ... ah, Dr, heal theyself. For your solution guarantees that setters have the sideeffect of invoking validation every time. To be fair, I am not a stickler for this principle. One way or another, whether the setter does it or not, something is going to cause validation based on the user's entry of data into whatever control maps to that setter (this comment is aimed at DDD afficionados).

Race condition: It is not fair that I have not looked at the code yet.

But here is what I'd try if I did:1) Set marital to a new-and-valid condition2) Attempt commit3) While you have canceled the commit temporarily so you can check with the server to see if marital condition is cool, I regain access to the form and change marital condition again .. to a bad condition.4) Your server trip returns and says "all is well"5) I commit the edit6) I save7) Server rejects because fails the re-run of the marital validation.

Hey, maybe you latched things just right and I can't make changes while you're away validating at the server. That's what I wanted to make sure you were doing. I just didn't see that latch in your post.

Even if this all works, it sure looks like a lot of effort in a lot of different places. I'm still not loving the convention of throwing exceptions when validations fail. Pity the dev.

ONE FINAL THOUGHT. Blog post language is tricky. It is hard to convey respect while voicing concerns. I have a ton of respect for you and the SL team that has built this power-packed control.

If nothing else our exchange may help readers (if there be any) appreciate the challenges of this kind of endeavor.

I might be horribly on a wrong path in what I am trying to achieve, but still in the above code the MessageBox displays exactly what I want. Is there any way -foreach loop iteration dump the errors inot validationresult and then show the summary.

The above code is in the code behind (.xaml.cs). Other than the service call that returns the above errors , all my code is basic from the ria preview document (a grid, then a dataform to edit and a child window to add).