AJ's blog

February 28, 2010

Understanding Validation in Silverlight

Filed under: .NET, .NET Framework, Silverlight, Software Architecture — ajdotnet @ 3:51 pm

Input validation is necessary in every business application. Time to look into validation with Silverlight.

Starting a little internet research will reveal two variations:

  • Putting validation code into property setters, throwing exceptions (covered by Jesse Liberty).
  • Decorating properties with validation attributes, either checked by the data grid, or manually, again eventually based on exceptions (see MSDN).

OK, obviously you don’t need me to repeat what has been described by others in sufficient detail.

However, neither the property setter approach, nor validation attributes work well with code generated classes (which are employed quite regularly with SL). Would property changed event handler solve that? How do value converters fit into the picture? What about mutual dependent properties? Null values? Actually, there’s no overall concept that would help answer these questions.

Note: WCF RIA Services (see also here; formerly known as RIA Services) addresses the „generated code“ issue by copying the validation from the server to the client. However I refrain from using WCF Services in this learning experience, since the aim is to understand what’s going on under the hood. Additionally I can easily envision cases in which I may want different (i.e. more restricting) validations on the frontend than on the server.

Defining “Validation”

Let’s clarify what we are talking about. Validation (more to the point, input validation) deals with checking some user input, however it is made, against, let’s call it syntactical and semantical rules. Syntactical rules include all that is necessary to satisfy the type of the backing data, e.g. ensuring the string actually is a valid time (provided the property is of type DateTime). Semantical rules deal with additional restrictions, usually business related, say whether some value is in a certain range.

Note: Validation always happens after the user has made his input, making sure the input was correct. The alternative approach (though not always feasible) is to let him only make valid input in the first place, e.g. with date pickers, numeric up/down, or masked edit boxes. This renders at least the need for syntactic validation obsolete, semantic validation may or may not be covered. Still, it may provide the better user experience.

Syntactic rules are usually enforced implicitly during the actual conversion. The need for a conversion depends on what data the control actually provides (e.g. a date picker control supplies a DateTime ready to use, no need for validation in this case). In other cases syntactic validation is covered by the databinding mechanism of Silverlight.

Semantical rules are up to the developer.

There’s another difference between syntactic and semantic validation: Syntactic validation has to occur before changing the data (since it’s a precondition to a successful type conversion), thus it is also tied to the UI and the databinding process. Semantic validation on the other hand can also happen after the data has already been changed. And it doesn’t have to happen in the UI either. Matter of fact, some validations may not even be possible in the UI, but have to be enforced by the business logic or even the database. Heck, they may happen out-of-band at any time, say by asking some other system asynchronously.

Note: Within my Silverlight UI I don’t care who actually does the validation, but the fact that it may happen outside of the usual sequence (databinding, triggered by some user input) is important.

Typical use cases for validation include:

syntactic validation
A) ensuring a string represents a certain type (numeric, date,…)

semantic validation
B) ensuring some input, i.e. required fields
C) ensuring a certain text length
D) ensuring a value matches some criterion (range check, regular expression, date in the future, etc.)

special cases
E) mutually dependent fields (mutual exclusion, value dependencies, etc.)
F) distinguishing between input and no input (i.e. null values)

Validation “mechanics” in SL

Validation is tied to data binding and to get it working the binding properties have to be set respectively:

Now let’s take a closer look at the data binding process. Here’s a (somewhat simplified) sequence diagram of the relevant code for validation, after a control changed its value. Basically it all depends on exceptions:

(Note: this is not entirely correct regarding the exception handling, but is conveys the actual meaning better.)

Let’s go over the locations I numbered:

1: The value converter you could declare in the binding expression is called – yet it does not take part in the validation handling. Meaning, any exception thrown here won’t appear as validation error, but as actual application error. This renders value converters useless in cases that need syntactic validation (like use case A).

2: Right after the value converter, a try marks the area in which every exception will be treated as validation error.

Personally I don’t understand why the value converters have been left out of this area (seems to be a conscious decision). They would have offered some easy to use validation mechanism…

3: The type converter of the property’s type is called, which translates the value from the type passed in by the control (a textbox passes a string, other controls may pass in other types) to the target type, say Int32. Exceptions thrown here will show up as something like „Input string was not in a correct format.“, and of course the property retains its original value. Hence the type converter does syntactic validation (use case A). There’s however no feasibly way to customize the conversion, like what a value converter could do.

Personally I don’t understand why the value converters… . Ah, said that already, didn’t I?

4: The property value is set, and in turn ticks off any validation code put in the property setter for semantic validation. The samples on the internet usually have the validation code before actually changing the property value, thus the property still retains its original value in case of a validation error, read exception. Anyway, use cases B (ignoring null values for the moment), C, and D are covered here.

5: The setter will also raise the PropertyChangedEvent, and in turn any exception thrown in a respective handler will also take part in the validation handling. However if we get that far, the property now has the invalid data already set. Still, this may be another location for use cases B, C, and D.

6: Any validation error is announced to the control via the BindingValidationError event. Many controls have an error state and will show a red border and an error tooltip. Alternatively there is a ValidationSummary control that takes care of presenting the feedback:

7: Finally there’s some missing parts in the sequence diagram:

  • The databinding mechanism doesn’t check the validation attributes, so who does? The DataGrid is the only control that actively validates the row in edit mode, but one can trigger the validation himself.
    If done before writing the data, this approach bypasses any value and type conversion (another reason why value converters have no part in validation). Theoretically one could validate a property this way without setting the values at all. However due to the type conversion issue, the only sensible approach is validate afterwards (which is what the DataGrid does), and let the data binding mechanism care about conversions. This way one could trigger that validation generically in the PropertyChanged event handler.
  • Nobody cares about errors (exceptions) in property setters and event handlers (point 4 and 5) outside of this sequence. Meaning any other code manipulation the properties and causing an exception will tear the whole application down.

As a corollary: Validation works one binding at a time. This implies that mutually dependent properties (use case E) are not part of the equation. If property X caused an error that may be fixed by changing property Y, SL doesn’t help. One can work around this (by a combination of UI design and simulated PropertyChanged events), but it’s ugly work.

I left out use case F (null values) so far: Data intensive applications may have to distinguish between no entry (empty string, null value) and the 0-value for the data type (e.g. „0“, „00:00“). The data type of the property would be a nullable value type, e.g. Nullable<Int32> or Nullable<DateTime>. The sad part: Type converters don’t handle null values, neither does some other part of the data binding mechanism. nullable types are treated like their non-nullable counterpart, thus no empty strings are allowed, worse, an empty string even usually causes an exception, thus validation error. The best way to solve this is a separate property of type string that handles null and 0 representation and does the type conversion. However it takes some effort to keep those two properties in sync and propagate PropertyChanged events of the other property.

Consequences & Conclusions

Now that the input validation mechanism is understood (I hope), I can draw some conclusions:

To set or not to set…

There is some inconsistency between whether an invalid value will actually be set in the data property or not: Type converter (syntactic validation) and property setter issues (semantic validation) generally leave the value as is. Validations in property changed notifications – including validation attributes if implemented that way – (also semantic validations) will set the property to the invalid value and notify only afterwards. This in turn means that our view model logic has to take the validity of the data into account, i.e. a save button should check some kind of IsValid property on the model.

To throw or not to throw…

In SL3 the validation mechanism relies on exceptions. Adverse effect is that the first validation error hides subsequent errors, which may obscure the feedback for the user. Secondly this code is also present when I set the properties from code, with no data binding infrastructure readily available to catch the exceptions. Hence I have to be very careful, or some innocent code may take my whole application down.

To depend or not to depend…

Validation in SL3 doesn’t cover mutually dependent properties properly. Some nasty stunts and compromises may get you a working solution, but it hurts to write that code (been there, done that!).

Anyway, with SL4 around the corner (see below) I‘d refrain from putting too much effort into this issue right now.

To convert or not to convert…

As said before, value converters do not exactly work with validation, at least if the conversion itself may fail. Thus I’d refrain from using them altogether in case validation is also needed. I’d rather put the conversion logic into „shadow properties“, i.e. properties that replace/complement the original property, changing only the property type (usually to string). Another reason for these shadow properties would be the null/0 issue mentioned above.

To keep these two properties connected and synchronized takes some effort. For example if one property changes, the other should raise the PropertyChanged event as well.

Silverlight 4

With SL4 we’ll get IDataErrorInfo and INotifyDataErrorInfo for asynchronous validation, as announced by Tim Heuer, and described in more detail by Fredrik Normén.

Contrary to SL3 this isn’t tied to exceptions any more. This will change the picture completely:

  • The first validation error won’t necessarily prevent other validations
  • Other code setting the value (outside of databinding) won’t have to deal with exceptions (and still partake in validation).
  • Asynchronous validation is covered.
  • Mutual dependencies can be addressed.

The one notable gap is the still missing MetadataTypAttribute that would enable the usage of validation attributes for code generated classes. The only other aspect not covered is the null values and value converter issue. But strictly speaking this is more an issue of type conversion than of the validation itself. (Still a pesky issue.)

If SL4 changes nearly everything, then why this post in the first place? Well, apart from the fact that existing code doesn’t migrate itself, while the contents presented here are less relevant, they are still valid.

Final Verdict

With SL3 I’d say about 80% of my validation demands are covered. But as always, the remaining 20% don’t appear all that often, but if they do, it hurts.

Looking ahead, SL4 will provide a better foundation for validation, and solve some issues — yet it still won’t cover every aspect. Still, having looked at SL4 may give some hints on what to implement today for SL3 (and what not), with a clean migration path to SL4.

That’s all for now folks,
AJ.NET

kick it on DotNetKicks.com

Advertisement

6 Comments »

  1. Brilliant and interesting write up. Thank you for thE Sequence diagram. Quite useful.

    Comment by Raghuraman — February 28, 2010 @ 6:13 pm

  2. Hi AJ!

    Thanks for this post! It is a real pain to develop an enterprise application in Silverlight 3.
    There are so many other shortcomings besides validation in SL3.

    Could you please elaborate a little more what you mean with shadow properties in this post?

    Cheers
    Sven

    Comment by Sven Lange — March 11, 2010 @ 2:40 pm

  3. Hi Sven,

    thanks for the feedback!

    “It is a real pain to develop an enterprise application in Silverlight 3.”
    Beg to differ 😉

    So far I’ve been working on or looking into about half a dozen business applications with Silverlight. And compared to ASP.NET, Silverlight has been a far better experience in almost every regard. I have ported a reference application from ASP.NET to SL, and it was simpler, more consise, robust, less code, and it provided additional features like deep links out off the box. You have to adjust to the architectural implications of asynchronous behavior (that part is probably one of the two most difficult for most people I’ve seen, the other being the lack of established and sufficient architectural patterns). But with one guy understanding SL in a team, you can achieve way more than with classical ASP.NET (IMHO). Actually validation is the one issue I came across so far that spoils the picture.

    But that’s strictly _my_ opinion. Perhaps you could name some of the other shortcomings you see. Maybe I haven’t come across them yet, or I can use the topics for my next blog post 😉

    Regarding shadow properties:
    The idea is simply to have a property wrap another and do some additional stuff. For example, if your original property “SomeNumber” is of type int? you could have another property “SomeNumberAsText” of type string. The second one does the type conversion, e.g. the setter would translate an empty string to null and “0” to 0. Additionally you would also have to mirror the property changed events to support databinding correctly. I.e. when “SomeNumber” is changed, the event should also be raised for “SomeNumberAsText”, as it changes implicitly.
    This could become more complex in cases where the original property cannot maintain all information, if the original property is mapped to different properties (say an enum mapped to distict boolean properties) or for mutual dependencies. As matters are with SL3 you’ll probably have to work through the details case by case, and it’s probably better to keep it simple and live with some compromises.

    HIH,
    AJ.NET

    Comment by ajdotnet — March 12, 2010 @ 9:26 am

  4. Nice Article,

    Can i get source code for Reference

    Comment by raj — March 30, 2010 @ 6:21 pm

  5. Hi I see this is a little older, but figured in case someone like me came across this they might want to give this a try. Basically, I have a hack work around for the value converter part.

    The idea is within the converter to setup a private nested class and a static instance to return when an invalid conversion occurs. When the value is sent back to the property the value cannot be converted to the source property type so the exception occurs at that stage and as described above the validation handling captures it. I tested this in SL4 nothing earlier but since it is the same value converter issue I assume it should work. The reason for the private nested class is so that you know for sure setting the value on the source will fail. In the example I also include a property on the converter to indicate if I actually want to force an error.Below is an example converter:

    public class TestConverter : IValueConverter
    {
    private static readonly ForcedBindingError ForcedBindingErrorResult = new ForcedBindingError();

    public bool IsErrorRaisedOnFailure
    {
    get;
    set;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
    // Convert to target type
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
    object convertedValue;
    if (!this.InternalConvertBack(value, targetType, parameter, culture, out convertedValue)
    && this.IsErrorRaisedOnFailure)
    {
    // HACK: Return the private type so a binding error occurs when the values is assigned to the source
    return TestConverter.ForcedBindingErrorResult;
    }

    return convertedValue;
    }

    private bool InternalConvertBack(object value, Type targetType, object parameter, CultureInfo culture, out convertedValue)
    {
    convertedValue = //Convert logic
    // return if conversion succeded
    }

    private class ForcedBindingError
    {
    }
    }

    I have setup an abstract base converter implemented like this, it has two abstract methods for the convert methods, the base class implements the converter interface and handles sending the bad data back, so the logic does not need to be duplicated over and over, when a new converter is needed derive it from the base class and implement the two conversion methods. It has worked out pretty well so far. Again it is an obvious hack, but I like this option rather than cluttering my data models with duplicate properties, or having to implement additional logic in my model properties, here it is handled once in the converter.

    Comment by Mike B — January 20, 2011 @ 10:12 pm

  6. Very helpful. Thanks!

    Comment by DeborahK — February 2, 2011 @ 8:32 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: