Input Validation with Silverlight

I miss ASP.NET. With the 2.0 Microsoft had the world best technology for creating applications of all kind. Small or large, ASP.NET 2.0 have features for all. Now several years later we have Silverlight 2 (no 2.0) and should be good as ASP.NET 2.0!? I don't think so- Silverlight have some great advantages but even more missing features. And some of them essential and important.

For me user input validation is one of them. To get the right data from user in correct format is a huge challenge and costs a lot of development time. ASP.NET have rich and easy validator controls to do the job. Silverlight have not.

But Input validation must done, so how? I will show you my approach. First of all, where to validate?

  • Database
  • Data Layer
  • UI Layer
  • User Interface
  • Nowhere

I don't like typing things several times. I hate to make data access and type field name 10 times in table, properties and UI. I like the drag and drop stuff and get declaration of where and how my data comes. (no dataset at all ;-)).  Silverlight doesn't have that by design and by architecture. The design part comes from Microsoft they have not enough resources to implement every feature within some weeks.

Second problem with data validation comes from loosely connected systems. The user interface is fare fare away from database. Sometimes thousands of km/ miles are between them. Proxy server, hubs, switches even different protocols and ports. So from that view it doesn't make sense to get data schema each time from table and reuse it in UI.

Input validation rules must be declared physical narrow to user interface. The closest thing I can imaging is within the same memory address space.

The practice

Cause of disliking typing code I use a ADO.NET Entity model and a ADO.NET Dataservice to get the data. Visual Studio 2008 creates a proxy class (reference.vb) for the Silverlight project. Database is northwind with table customer. The goal is a input dialog. Phone number is limited to 20 characters. Error is shown as tooltip (zu lange). Textfield is marked as read. Tabbing out will do the validation.

First of all I create the rule set. I do that in the created proxy class (reference.vb) and check the length and throw an exception.

Public Property Phone() As String
        Get
                Return Me._Phone
        End Get
        Set
                If Len(value) > 20 Then
                    Throw New Exception("zu lange")
                End If
                Me.OnPhoneChanging(value)
                Me._Phone = value
                Me.OnPhoneChanged()
        End Set
End Property

Not the best solution. If somebody is updating service reference, your code will be overwritten.

The databinding in the Textbox must have twoway binding and two additional attributes set. That is necessary to get a special event in error case (exception) which will defined in next step

<TextBox Margin="8,8,144,8" Grid.Column="1" Grid.Row="3" 
Text="{Binding Phone,Mode=TwoWay,NotifyOnValidationError=true,  
ValidatesOnExceptions=true}"/>

Then we can create the code for the event BindingValidationError of the grid, named Layoutroot. I decided to show the exception message as tooltip and to change backcolor of Texbox. eventargs gives reference to Textbox and also to eventaction (Added, Removed)

Private Sub LayoutRoot_BindingValidationError(ByVal sender As System.Object, 
ByVal e As System.Windows.Controls.ValidationErrorEventArgs)
     If e.Action = ValidationErrorEventAction.Added Then
            CType(e.OriginalSource, TextBox).Background = _
New SolidColorBrush(Colors.Red)
            ToolTipService.SetToolTip(CType(e.OriginalSource, TextBox), _
e.Error.Exception.Message)
     Else
            CType(e.OriginalSource, TextBox).Background = _
New SolidColorBrush(Colors.White)
     End If
End Sub

Full code for completion

Partial Public Class page29
    Inherits UserControl
    Dim cust As ServiceReference1.NorthwindEntities = _
New ServiceReference1.NorthwindEntities(New Uri("WebDataService1.svc", UriKind.Relative)) Public Sub New InitializeComponent() End Sub Private Sub page29_Loaded(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded cust.BeginExecute(Of ServiceReference1.Customers)_
(New Uri("Customers", UriKind.Relative), AddressOf fertig, cust) End Sub Public Sub fertig(ByVal result As IAsyncResult) LayoutRoot.DataContext = _
cust.EndExecute(Of ServiceReference1.Customers)(result).First End Sub Private Sub LayoutRoot_BindingValidationError(ByVal sender As System.Object,
ByVal e As System.Windows.Controls.ValidationErrorEventArgs) If e.Action = ValidationErrorEventAction.Added Then CType(e.OriginalSource, TextBox).Background = _
New SolidColorBrush(Colors.Red) ToolTipService.SetToolTip(CType(e.OriginalSource, TextBox),
e.Error.Exception.Message) Else CType(e.OriginalSource, TextBox).Background = _
New SolidColorBrush(Colors.White) End If End Sub Private Sub Button_Click(ByVal sender As System.Object,
ByVal e As System.Windows.RoutedEventArgs) Dim o As ServiceReference1.Customers = LayoutRoot.DataContext cust.UpdateObject(o) cust.BeginSaveChanges(AddressOf saveFertig, o) End Sub Public Sub saveFertig(ByVal result As IAsyncResult) cust.EndSaveChanges(result) End Sub End Class

3 Comments

Comments have been disabled for this content.