Ever since Silverlight version 1 was announced, I’ve been working with my WPF and .NET back-end libraries to ensure that I could reuse business entity objects between the tiers regardless of the UI technology.
I wrote these demos in NYC while waiting for my flight home. This application takes advantage of the OceanFramework that runs in WPF, Silverlight and .NET 2.0 libraries. The two versions, WPF and Silverlight use the same exact files. I use Project Linker to to keep the two projects in sync. (FYI: The OceanFramework can also be used with Windows Forms applications.)
Using file linking in Visual Studio, I’m sharing the same exact business entity object file, Person.vb between WPF and Silverlight projects.
Validation
Before diving into the application I want to share some thoughts on validation.
Real world business applications use validation libraries to validate their business objects. Validation libraries contain rules and offer one or more techniques for calling their methods. Examples of validation libraries are the Microsoft Patterns and Practices Validation Application Block, Rocky Lhotka’s CSLA, my Ocean library and validation rules written by developers for their projects.
Well designed validation libraries are UI agnostic.
Validation libraries are used to validate business objects in the UI layer, Business Layer and Data Layers.
Follow this simple workflow:
- UI loads Person object
- User edits Person object
- User clicks the Save button
- Person is validated
- If valid, Person passed to Business Layer
- Business Layer checks to ensure the object is valid, if not an exception is thrown
- Business Layer performs computations on Person
- Person is validated again
- If valid Person passed to Data Layer
- Data Layer checks to ensure the object is valid, if not an exception is thrown
- Person passed to data base
- Database performs its own checking then writes the records
From the very simple above example, we can see that validation needed to occur in two layers, UI and Business.
Also very important to note is that when the object was validated in the above example, the same rules were applied against the Person object in both layers.
The italic text steps are the sanity checks performed by each layer as it receives an object. I don’t allow invalid objects to cross a tier boundary.
Another example scenario is a business process that calculates bills for customers. In the case, there is no UI interaction during the process but you know that those objects involved are all validated before being sent to the data base.
Surfacing Validation Errors
- IDataErrorInfo
- Throwing exceptions in property setters
The IDataErrorInfo interface provides a simple way for business objects to surface their validation errors to the UI. WPF and Windows Forms support this interface.
Throwing exceptions from property setters is another way for business objects to surface their validation errors to the UI. Silverlight and WPF support this method.
If you have not read my rant on throwing exceptions from property setters read Fort Knox Business Objects.
Important: When we develop business systems, we must take into consideration the fact that, “business objects must exist and interact with other objects in many different layers of an application.” This is one of the reasons I’m not in favor of throwing exceptions from property setters. Business layer and data layer code would be much harder to write if the object was throwing exceptions when properties are changed. It’s much easier to work with an object, then before the object is allowed to move from one tier to another, validate the object. If valid let it travel to the next tier. If not then either have the layer code attempt to correct it or throw an exception because something exceptional occurred..
Silverlight 3 and Surfacing Validation Errors
I love the new Silverlight 3 default validation states and the UI features when a control is invalid. Nice job Silverlight Controls Team!
I want to use IDataErrorInfo in Silverlight 3, however it currently does not support it.
So on Friday night in NYC, I stayed up and wrote a Silverlight TextBox that cleanly supports IDataErrorInfo. In fact I did a demo of it on Saturday in NYC. On Saturday night I did much more testing and found some edge cases where my implementation could have problems. I even took a stab at using an attached property and attached behavior too. Still always running into a nagging snag.
My solution to the problem was to give the Ocean Validation code the “option” throw an exception in the property setter when the business object is bound to the UI. When it’s not bound to the UI it will not throw an exception.
Using this technique, I can now use the same business objects across the tiers and still play nice with Silverlight 3 and take advantage of all the new Silverlight UI goodness.
Sharing Business Objects
If your validation library is small enough and can be compiled in Silverlight as well as WPF or .NET 2.0, you are ready to go. Currently Ocean for Silverlight weighs in at a very light 56KB.
The above image shows a Person file that is linked to a file in another project.
The above image shows the some of the referenced assemblies. Silverlight can only reference other Silverlight assemblies. I’ve solved the problem by keeping all the code in the OceanFramework and linking all files to the OceanFrameworkSilverlight project.
When the two business entity objects are compiled, they provide objects that can travel across the tiers while utilizing the same exact business object files and exhibiting the same logical behavior in all tiers.
The above MissingSilverlightInterfaces project contains the Sytem.ComponentModel.IDataErrorInfo interface since it’s not currently part of the Silverlight runtime.
Silverlight Application
The above image shows the UI surfacing a validation error. Profession is a required field. Notice that the Save button is disabled. This is accomplished with a data binding to the business object’s base class.
When a person is selected the Person Details form will animate into position.
The below image shows the code for this validation rule.
The above Ocean StringLengthValidator requires a string length at least 1 and no more that 30 characters.
The CharacterCasingFormatting attribute causes the business layer to case correct this field. This works in WPF and Silverlight.
I like applying rules this way because the code is very easy to read and generate.
Ocean provides many validation rules and case correcting rules. Rules can be applied using attributes or adding them in code.
WPF Application
In the above image, Profession is empty but is a required field. The * denotes an invalid field. Notice the button is disabled. Again, a simple data binding to the business objects base class.
The above image shows the details form in a valid state. The button is enabled and the record can be saved.
I used this project in the WPF Line of Business Tour in the Layout session. I showed how to use a WrapPanel as the ItemsPanel in a ListBox. Then when the GridSplitter is used to give the ListBox more horizontal space, the WrapPanel kicks in.
Download
The download contains a single folder with the the 4 projects and an additional folder that contains the Ocean frameworks. I’ve only supplied the Ocean frameworks in .dll format for this demo. I’m in the process of updating the libraries and do not want anyone to have version problems.
Also I wanted to keep this application simple so that the “code sharing” would be the focus and readers not getting lost in a solution with too many projects.
FYI: I’ll be posting another application soon that shows all the layers in action including the WCF projects that move the data back and forth.
For now, understanding that you “can easily” shared business objects and their validation rules across the tiers, is good news!
After downloading the code, change the file extension from .doc to .zip. This is a requirement of WordPress.com.
Sharing Entity Objects Download (158KB)
Have a great day,
Just a grain of sand on the worlds beaches.
Posted by Karl Shifflett
Posted by Karl Shifflett
Posted by Karl Shifflett



