blog community
Silverlight 4 vs Flex 4: Data Validation

In this post I’m again comparing two features of Silverlight and Flex, this time we’re going to take a look at how data validation is implemented on both platforms. This will be a very interesting comparison, since Flex and Silverlight take entirely different approaches. Which one is better? I can let you know in advance that one of the two is a bit broken. Read on to find out which one…… 

Flex Data Validation

Let’s take a look a the following code:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
   3:                xmlns:s="library://ns.adobe.com/flex/spark" 
   4:                xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="application1_creationCompleteHandler(event)">
   5:     
   6:     <fx:Script>
   7:         <![CDATA[
   8:             import mx.events.FlexEvent;
   9:             
  10:             [Bindable]
  11:             private var _person : Person;
  12:  
  13:             protected function application1_creationCompleteHandler(event:FlexEvent):void
  14:             {
  15:                 _person = new Person();
  16:                 _person.age = 20;
  17:             }
  18:  
  19:         ]]>
  20:     </fx:Script>
  21:     <fx:Declarations>
  22:         <mx:NumberValidator domain="int" minValue="0" source="{_txtAge}" property="text"
  23:                             lowerThanMinError="Age must be larger than 0!"
  24:                              invalidCharError="The provided input is not a number!"
  25:                               integerError="Age can't be a decimal number!"/> 
  26:     </fx:Declarations>
  27:     
  28:     
  29:     <s:TextInput id="_txtAge" x="226" y="204" text="@{_person.age}"/>
  30:     
  31: </s:Application>

 

and the following class:

   1: package
   2: {
   3:     public class Person
   4:     {
   5:         private var _age: int;
   6:         
   7:         
   8:         public function Person()
   9:         {
  10:         }
  11:  
  12:         public function get age():int
  13:         {
  14:             return _age;
  15:         }
  16:  
  17:         [Bindable]
  18:         public function set age(value:int):void
  19:         {
  20:             _age = value;
  21:         }
  22:  
  23:     }
  24: }

I’m going to explain data validation in Flex as simple as possible. The first code snippet is the user interface part. You can see that this is a very simple user interface with just a TextBox in which a user can enter an age. The entered age is passed on to an instance of the Person class shown in the second code snippet. This is done by using the new two way databinding feature in Flex 4, which uses the “@” in front of the databinding expression. At startup the creationComplete event is used to initialize the Person with an age of 20:

image

When the user enters an invalid (negative, decimal or not a number) value the user interface changes to this:

image

This all happens automatically because of the NumberValidator used on line 22. Data validation in Flex is done using the Validator class and it’s different sub classes like NumberValidator. You just configure a validator with a couple of things:

  • source: This is the object which holds the property you want to validate.
  • property: This is the property you want to validate.
  • Validator specific properties: These include error messages of the different validations a validator can do, or for example a regex when using a RegExpValidator.
  • trigger: This is the object which dispatches the event that triggers validation. I don’t set this in the code above, because by default this is the same object as the source property.
  • triggerEvent: The event that triggers the validation, by default this is the valueCommit event. Since the source in the example above is the TextBox and the valueCommit event is used, validation is triggered when the user presses enter or the TextBox loses focus.

There are a couple of things I really like about Flex’ approach. Firstly, these are the built in validators:

  • CreditCardValidator
  • CurrencyValidator
  • StringValidator
  • NumberValidator
  • PhoneNumberValidator
  • DateValidator
  • EmailValidator
  • RegExpValidator
  • ZipCodeValidator
  • SocialSecurityNumberValidator

And if those are not enough, you can create your own validator by inheriting from the Validator class and override the doValidation() method. The second thing I like is that you can easily customize the triggering of the validation:

   1: <mx:NumberValidator domain="int" minValue="0" source="{_txtAge}" property="text"
   2:                             lowerThanMinError="Age must be larger than 0!"
   3:                              invalidCharError="The provided input is not a number!"
   4:                               integerError="Age can't be a decimal number!"
   5:                               triggerEvent="change"/> 

By setting the triggerEvent to “change”, validation is now triggered with every button the user presses instead of when losing focus or pressing enter. There are also things that I don’t like, for example, data validation doesn’t prevent databinding. This means that even when an incorrect value is set in the TextBox, the value is still propagated to the setter of the Person class. If I did a check in the setter and threw an exception, I would have a serious problem because there is no easy place to catch the exception, except for the global error handler. Next to that, certain exceptions are swallowed by the databinding engine and others are not. Lastly, Flex' Validator classes don’t play nice with asynchronous data validation.

 

Silverlight Data Validation

I’ve built the same user interface as in the Flex example. This time, three code snippets because of the code behind model Silverlight uses. First up, the XAML:

   1: <UserControl x:Class="SilverlightValidation.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:     mc:Ignorable="d"
   7:     d:DesignHeight="300" d:DesignWidth="400">
   8:     
   9:     <Grid x:Name="LayoutRoot" Background="White">
  10:  
  11:         <TextBox Height="23" Grid.Row="1" HorizontalAlignment="Left" Margin="114,98,0,0" Name="_txtAge" VerticalAlignment="Top" Width="120"
  12:                  Text="{Binding Age,Mode=TwoWay,ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"/>
  13:     </Grid>
  14: </UserControl>

 

Next up, the code behind:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12:  
  13: namespace SilverlightValidation
  14: {
  15:     public partial class MainPage : UserControl
  16:     {
  17:         private Person _person;
  18:  
  19:         public MainPage()
  20:         {
  21:             InitializeComponent();
  22:             _person = new Person() { Age = 20 };
  23:             DataContext = _person;
  24:             
  25:         }
  26:  
  27:     
  28:     }
  29: }

Lastly, the Person class:

   1: using System;
   2: using System.Net;
   3: using System.Windows;
   4: using System.Windows.Controls;
   5: using System.Windows.Documents;
   6: using System.Windows.Ink;
   7: using System.Windows.Input;
   8: using System.Windows.Media;
   9: using System.Windows.Media.Animation;
  10: using System.Windows.Shapes;
  11: using System.ComponentModel;
  12:  
  13: namespace SilverlightValidation
  14: {
  15:     public class Person : IDataErrorInfo
  16:     {
  17:         public int Age { get; set; }
  18:  
  19:         #region IDataErrorInfo Members
  20:  
  21:         public string Error
  22:         {
  23:             get
  24:             {
  25:                 return null;
  26:             }
  27:         }
  28:  
  29:         public string this[string columnName]
  30:         {
  31:             get
  32:             {
  33:                 switch (columnName)
  34:                 {
  35:                     case "Age":
  36:                         if (Age < 0)
  37:                         {
  38:                             return "Age can't be smaller than 0";
  39:                         } else
  40:                         {
  41:                             goto default;
  42:                         }
  43:                     default:
  44:                             return null;
  45:                 }
  46:             }
  47:         }
  48:         #endregion
  49:     }
  50: }

When you start the application it looks like:

image

And when you enter an invalid value:

image 

 

Silverlight takes a whole different approach to data validation, in Flex validation is the responsibility of the Validator objects, in Silverlight the validation is the responsibility of the domain object to which is data bound. Of course, within this object you can delegate the responsibility as much as you like. As of Silverlight 4, we have three ways of doing data validation:

  • By throwing exceptions in the setters of the property of the data bound object. The message in the exception becomes the validation error message.
  • By implementing the IDataErrorInfo interface, this interface defines two members:
    • An indexer, which is called by the binding engine supplying a property name, if the property with the supplied name is valid, you can return null otherwise the validation error message.
    • An Error property which isn’t used by the binding engine but you can use to get a single error message for the entire object.
  • By implementing the INotifyDataError interface. This interface is like the IDataErrorInfo interface, but has supports for events. With the IDataError interface the Indexer is called every time the value of the property changes through databinding. With the INotifyDataError interface, the bound object is examined for validation errors whenever you fire a specific event. This means that you can contact a server to do the validation and when you receive the response, you can fire the event. In short, INotifyDataError provides support for asynchronous data validation.

You have the specify which of the above options you want to use in the binding expression. When you take a look at line 12 in the first code snippet, you can see that I use two of above features, namely the IDataError interface and the exceptions option. If I wanted to use the INotifyDataError interface, I should have supplied the “ValidatesOnNotifyDataErrors = True” option in the binding expression. Take a look at the Person class, you can see that it implements the IDataError interface, but doesn’t throw any exceptions in a setter. So why the ValidatesOnExceptions option in the binding expression? I’ll come back to that later :).

So how does the IDataErrorInfo interface work? Every time the binding engine updates the property value, it calls the indexer on line 29 of the last code snippet afterwards, supplying the name of the property it has just updated.  I’ve implemented the indexer on line 29 as if I had multiple properties. When you return a string, it’s a sign to the binding engine that a validation error has occurred and the returned string becomes the error message. When the binding engine get’s a sign that a validation error has occurred, it transitions the bound control, in this case the TextBox to the “InvalidFocusedState” or the “InvalidUnFocused” state. So the control template of a control determines how a control looks when a data validation error occurs. If you want to adjust this look, you have to retemplate the control and define your own look for the invalid states.

There are a couple of things I like about Silverlight’s data validation model. The first is that there is support for asynchronous data validation. The second thing is that this data validation model works really well in a MVVM environment, with the View having all the knowledge it needs to change itself when a data validation error occurs. If you want to customize it, just retemplate the view, while in Flex you have to write some actionscript code. The difficult thing is, where are you going to put this code in a MVVM scenario?

So for me (because I really like MVVM and asynchronous data validation) Silverlight would have been the winner. I deliberately say “would have been”, because I’m going to make a bold statement here…I think that Silverlight’s data validation system is a bit broken… There I’ve said it… but before the flaming begins, let me elaborate.  

 

Silverlight’s broken validation system

I said that I would come back to the “ValidatesOnExceptions” option in the binding expression on line 12 in the first code snippet. The reason i have it there is that this is the only way I can get a notification when a user enters a string that can’t be converted to an integer. It turns out that Silverlight’s binding system does some pre-validation before it supplies the value to the bound object, if this validation fails, the value never reaches the bound object. This happens when I enter a string that can’t be converted to a number:

image

It's somewhat logical that the binding engine does some pre-conversion. The problem is, that the message shown can’t be customized! I’ve tried  a couple of possible solutions:

  1. Create my own IValueConverter which does the string to integer conversion and supply my own message. The problem with this approach is that exceptions in the IValueConverter don’t trigger Silverlight’s validation system, only exceptions in property setters can do that. This means that the IValueConverter can’t let the system know that validation fails. How can this be you ask? Clearly the default converter triggers the validation system? This is because the default converter throws a ValidationException, this exception get’s recognized by the binding engine and gets a special treatment so that it triggers validation. But if you want to throw this exception from your own IValueConverter, you’re in for a surprise because the constructor is internal, which essentially means that only Microsoft code can throw this exception.
  2. Catch the FocusLost event of the TextBox, manually set the error messages of the control and manually transition the control to an InValid state using the VisualStateManager. While you can manually transition a control to an InValid state, you can’t set a controls error messages. This “Errors” property which contains the messages for a control is an attached property from the Validation class. You guessed it…the required setter to manually set the error messages is internal.

Another example of the problem: what if an user could enter an address in a TextField in a specified format (street and number) and the bound business object expected an Address object. I would use an IValueConverter to do the conversion from string to Address, which is the whole purpose of value converters. But the converter could never ever let the user know that he / she entered the address in a wrong format. This is why the validation mechanism in Silverlight is broken and if you want to fix it, you have to resort to a whole custom solution and can’t  make use of the built in InValid states all the Silverlight controls have, because you can’t specify the error message to show. This means that you have to do everything yourself for all the pre-validation that the binding engine does, if the error message doesn’t suit your needs. What can Microsoft do to fix this? Very simple:

  1. Make the constructor of the ValidationException public.
  2. Or let all exceptions in an IValueConverter trigger the validation system.
  3. Make the attached property setters in the Validation class public, so that when you resort to a whole custom solution, you can still make use of the built in InvalidStates.

 

Conclusion

Phew, This post has become a little longer than I first suspected. When I develop a Flex application, I notice that having these built in validators really speed up the development. When I develop a Silverlight application, I notice that trying to work around the quirks in the validation system slows me down to a point that I choose a whole custom solution. Don’t get me wrong, I really think that Silverlight’s validation system is on the right track: it integrates beautifully with the MVVM pattern and has support for asynchronous validation. But the issues outlined above need to be fixed. When they are fixed, I think Silverlight’s validation system could surpass Flex’ validation system, certainly in MVVM scenario’s. But for now, Flex’ data validation system is more useful to me.


Posted 01-02-2010 9:24 by Alex van Beek

Comments

Servefault.com wrote Silverlight 4 vs Flex 4: Data Validation - Alex van Beek
on 01-02-2010 10:01

Thank you for submitting this cool story - Trackback from Servefault.com

DotNetKicks.com wrote Silverlight 4 vs Flex 4: Data Validation
on 01-02-2010 10:02

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetShoutout wrote Silverlight 4 vs Flex 4: Data Validation - Alex van Beek
on 01-02-2010 10:04

Thank you for submitting this cool story - Trackback from DotNetShoutout

Pieter wrote re: Silverlight 4 vs Flex 4: Data Validation
on 01-02-2010 23:49

Interesting post! What about DataAnnotations for doing validation in Silverlight?                      

willemm wrote re: Silverlight 4 vs Flex 4: Data Validation
on 02-02-2010 9:20

After a talk with Jeff Handley (programmanager WCF RIA services) I'm convinced that the validation subsystem with the exceptions in Silverlight is a no go. Jeff has been working hard on getting IDataErrorInfo working with validation and I suspect it will become part of silverlight either through WCF RIA services or in the RTM release of silverlight 4.

Alex van Beek wrote re: Silverlight 4 vs Flex 4: Data Validation
on 02-02-2010 10:01

I'm also not fond of validating with exceptions, but it's the only way to get notified if a user enters something that can't be converted by the binding engine. That's the problem I'm illustrating above :).

The IDataErrorInfo interface is allready confirmed as being part of Silverlight 4, not RIA services, but the issues outlined above really need to be fixed.

Alex van Beek wrote re: Silverlight 4 vs Flex 4: Data Validation
on 02-02-2010 10:05

Hi Pieter,

The DataAnnotations rely on the "ValidatesOnExceptions=true" option in the binding expression, and exhibit the same problem as outlined above. When you enter something that can't be converted correctly, the value never reaches the validation done by the DataAnnotations and that pesky generic validation error is shown.

silverlightchina wrote re: Silverlight 4 vs Flex 4: Data Validation
on 03-02-2010 18:27

Great topic!

Rob wrote re: Silverlight 4 vs Flex 4: Data Validation
on 03-02-2010 19:42

The solution to your validation/conversion issue is easy to fix.  Instead of making the property on your VM a number, make it a string.  Then, in your validation logic, do the conversion and raise the error if conversion fails.  If it succeeds, then check to see if it the number meets the proper criteria.  If it doesn't publish a different error.  This is easy to do with a VM.  You could even create a custom data attribute which does this in a generic way by using IConvertible under the covers. Remember that a VM is designed to make representing UI state easy, not necessarily representing domain model state exactly as is.  That said, I do think it's a bit of a pain. It would be nice if Miccrosoft provided a custom attribute for this, so that we could have the datatype as we want and just provide the type conversion error message.

Alex van Beek wrote re: Silverlight 4 vs Flex 4: Data Validation
on 04-02-2010 7:53

Hi Rob,

Great point, you're absolutely right  that the VM is there to make respresenting UI state easy. That being said, the fact that you have to resort to a VM to work with Silverlight validation, tells me that there is something wrong with the validation system, most certainly when I have to type all of it's members as a string to make the validation work. If you ask yourself the question "Why am I typing all my members as a string?" and the answer is "To make data validation work", then it can't be a productivity boosting validation system...

Louis wrote re: Silverlight 4 vs Flex 4: Data Validation
on 21-02-2010 22:51

Great post, I agree with you 100%. The validation framework must evolve. It's seem very difficult to create a complex application validation with the current Setter/Getter design. MS should let us tap into the control invalid state for some custom validation without requiring us some binding black magic.

Alex van Beek wrote Silverlight 4 vs Flex 4: Accessing the Clipboard
on 22-02-2010 10:17

In this post I’m comparing Flex 4 and Silverlight 4’s clipboard access abilities. Accessing the clipboard should be an interesting comparison, since both Flash 10 and Silverlight 4 take different approaches. I deliberately said "Flash

drhender wrote re: Silverlight 4 vs Flex 4: Data Validation
on 25-02-2010 5:10

I really like the fact that Silverlight allows the validation to be part of the model and not part of the UI as it is in Flex.  If I am reusing a model with several different UIs, there shouldn't be a need to write validation code more than once.  

Having said that, Silverlight's inability to allow the validation code to deal with conversion failures is a show-stopper.  It would be nice to be able to override the conversion code that is built into the framework.  Instead of the framework attempting the conversion, which then requires it to deal with the failure, it should call into a type converter provided by the model class.

AM wrote re: Silverlight 4 vs Flex 4: Data Validation
on 19-03-2010 22:20

In response to your comment of "If you ask yourself the question "Why am I typing all my members as a string?" and the answer is "To make data validation work", then it can't be a productivity boosting validation system..." I would say that you are incorrect. The reason why your properties are strings in your VM is because your view is using string based input controls (such as a textbox) to display and accept input.

If you use a custom numeric textbox or an int-based input control then you won't have this problem in the first place. Your viewmodel can then expose those properties as their model data type.

I think Silverlight's behavior is correct in this context. The error does not lie with validation but with the way you are choosing to allow the user to enter data. If you absolutely must give your users the option of entering a value for a type not constrained by the input control then it is your responsibility to make the necessary conversion before it hits your viewmodel and, as a consequence, your validator. I would suggest a custom control that inherits from TextBox or attaching a behavior to the textbox so that it can only accepts numbers.

If you want users to be able to input non-numeric characters and validate that the input is numeric then your viewmodel must have a string property since you are allowing users to enter a string in the first place.

Alex van Beek wrote re: Silverlight 4 vs Flex 4: Data Validation
on 20-03-2010 11:33

"The reason why your properties are strings in your VM is because your view is using string based input controls (such as a textbox) to display and accept input."

Yeah..... but what if don't want to use a ViewModel? Your next sentence says it all:  "before it hits your viewmodel and, as a consequence, your validator." I guess I have a problem with the data validation mechanism being so tightly coupled with MVVM. A lot of (smaller) applications don't use MVVM but still need to use the validation mechanism. If I use MVVM, I want to make that decision myself, and not be forced by the data validation mechanism. Take for example Flex' validators, they're flexible enough to work with MVVM, but also pure declaratively in MXML and even without using databinding at all.

Bill wrote re: Silverlight 4 vs Flex 4: Data Validation
on 20-03-2010 12:51

While I certainly understand where AM is coming from, I fully agree with Alex on this one. The data validation in Silverlight should work with you, and not force you on a MVVM path you otherwise would't take...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Enter code (required)
Powered by Community Server (Commercial Edition), by Telligent Systems