WCF by example is a series of articles that describe how to design and develop a WPF client using WCF for communication and NHibernate for persistence purposes. The series introduction describes the scope of the articles and discusses the architect solution at a high level. The source code for the series is found at CodePlex.
This is a two part chapter that covers the validation in WPF views and the management of business exceptions and warnings in the client side. For the validation topic, we will discuss how to provide comprehensive validation functionality all the way from the UI layers back to the server side, for the warnings and exceptions, the application will provide a customised exception handling mechanism for both client exceptions and business exceptions returned by the server methods; for the business notifications we will put in place a nice and slick notification feature that uses balloon notification messages in the Windows Task Bar.
Validation - DTO Implementation
We haven't covered validation in WPF in the series so far, maybe the reason for so it is to do with the fact that WPF validation is not that straight forward. We are going to describe what we consider to be a comprehensive solution given our application design. The eDirectory's solution is a hybrid one where a rich UI experience is provided but the validation code is not placed in the business entity, instead the DTO class is used for that purposes. In a nutshell, the following is an example of the type of validation functionality that is achieved in this manner:
In order to provide the above functionality, the following steps are required:
- The DTO class needs to inherit from a new base class:
DataAnnotation attributes are added to the DTO properties for validation purposes
- XAML Binding needs to be amended with the following:
Mode = TwoWay
ValidatesOnDataErrors = True
Validation.ErrorTemplate is set to the
- Command buttons can bind to the
IsValid property in the DTO for enabling/disabling purposes
As an example of how the DTOs will look after the above indicated changes, the
CustomerDto looks like:
And the following is a section of the XAML that was changed:
And the last change is in the
ViewModel so the Save button is enabled only when there are no validation errors:
Validation Design Discussion
Before we continue, let's stop for a second to discuss what goals we tried to achieve with the above mentioned solution:
- Follow the DRY principle
- Easy to test
- It should be possible to execute the validation both in the server and the client side
Regarding the DRY principle, on paper, the business entity should be responsible for the business validation, in the case of the eDirectory
Customer class, for example, the First Name field is not nullable and cannot be longer than 50 chars. This is a classic example of validation that should be defined on the entity itself. It is feasible placing this validation on the entity but it generates a sort of crude validation solution where the client needs to call the server to find out if there is validation errors. On some projects, this is acceptable and it may result in being the best approach as it facilitates testing and rapid development.
eDirectory application proposes a solution where simple validation can be declared in the DTO object so WPF validation can be used in the client side, the entity can also use this validation in the server side. We are basing this solution in the following articles:
|Attributes-base Validation in a WPF MVVM
||In this article, the
IDataErrorInfo interface is used in combination with validation attributes in the
ViewModel classes. We used the logic in the back-end to retrieve validation attributes and getters using LINQ queries. This concept was originally covered on the WPF Validation with Attributes and IDataErrorInfo in MVVM post
|Automatically validating business entities in WPF using custom binding and attributes
||This is an interesting article by Sandrino Di Mattia based on the work done by Phillipp Sumi on WPF custom binding. In this solution, a custom WPF binding is used for validation purposes, the
eDirectory solution is very similar but it is developed around standard classes without requiring additional implementation. Still, it is a very good article.
|Validation in Windows Presentation Foundation
||This is a four year old article that still applies, it is surprising how little things have changed since then, maybe Microsoft is trying to say to all of us that is time to move to the mighty Silverlight https://www.codeproject.com/script/Forums/Images/smiley_smile.gif
|Implementing Data Validation in Silverlight with INotifyDataErrorInfo
||This article covers the use of
INotifyDataErrorInfo in Silverlight. It is a good article, discussing the limitations of the
IDataErrorInfo interface and covering some of the internals of how controls interacts with the validation code.
Before we move on, if you are one of those that like DDD and find it frustrating to locate the validation outside the business entities, it may be the time to look at frameworks that resolve this type of issue in a better way:
IDataErrorInfo & Validation Attributes Implementation
The eDirectory solution is based on the proposed idea on the WPF Validation with Attributes and IDataErrorInfo interface in MVVM post and it states:
WPF provides validation infrastructure for binding scenarios through IDataErrorInfo interface. Basically, you have to implement the Item[columnName] property putting the validation logic for each property in your Model (or ModelView) requiring validation. From XAML, you need to set ValidatesOnDataErrors to true and decide when you want the binding invoke the validation logic (through UpdateSourceTrigger). Then idea is to generalize the validation logic in IDataErrorInfo.Item using the validation attributes in System.ComponentModel.DataAnnotations assembly.
So we can have a new base class that inherits from
DtoBase and implements the
IDataErrorInfo interface so the WPF control can be notified if there was a validation error. The base class delegates to an instance of
DataErrorInfo which is responsible for gathering the properties that are tagged with validation attributes and invokes the validation when the
IDataErrorInfo methods are executed.
It is worth noting that both the
DataErrorInfo implement the
IDataErrorinfo interface and that the first one merely delegates into the second class when the methods are invoked.
There is one aspect on this class that can be improved in terms of performance, your Dtos will not change at run time so it probably makes sense to store the validator and property maps the first time that they are created. This will result in a performance improvement although you will have to watch out for synchronization issues and locking.
Server Side Validation
As we indicated at the start of this chapter, one of our goals is to be able to check for validation errors at the server side as well. With the proposed solution, it is relatively easy to achieve this requirement. For example, when the
Customer.Create method is invoked, the following code has been added:
ValidateOperation method is declared in the base class:
EntityBase, this method checks for validation errors in the DTO, throwing a business exception if any error is found:
XAML Error Templates
WPF provides very basic support for validation errors on the views, however with some few changes, we can provide a richer experience. Our solution provides three different mechanisms: red border around the textbox control, validation error symbol and tooltip.
For the red border and the validation error symbol, a control template was created named
validationTemplate, for the tooltip a custom style was created for the
TextBox control. Both declarations were added to
Application.resources at the App.xaml file.
For the tooltip to be shown, no further action is required. However, we need to indicate in each control that we want to use the
validationTemplate in the XAML. You may prefer to move this template to an style instead, the following article explains how to do it: IDataErrorInfo, Error Templates and WPF.
The XAML for the template and style is as follows:
Business Exception Management
We have covered in the previous chapters business warnings and exceptions in the server side, this section of this chapter covers for the client side, specifically how the client application notifies the user of those events. We are going to display a modal screen indicating the user of any exception and ensuring that the client application stops any processing. For the business warnings, instead, a notify icon will be available that will inform the user using info balloons on the Windows taskbar.
Trapping All Exceptions in a WPF Application
It is relatively easy to catch all unhandled exceptions in WPF:
The handler implementation creates a new Notifier view and sets the
Handled property to indicate to the application that the exception was managed.
The view is quite simple, a left section for an image, the right panel is used for displaying the exception details. Couple buttons permit to copy the whole exception and call stack to the clipboard and close the window.
There is nothing special regarding the new view and controller that we haven't seen before:
At this point, we have a new mechanism that ensures all exceptions are well managed, for example, if an exception was to be generated during the client processing, the following screen is displayed:
Business Exceptions - Client Implementation
We need to leverage the new
ExceptionNotifier with the Business Exceptions retrieved from the server responses. In first place, we need to revise the code at the
ServiceAdapterBase class, the
ExecuteCommand is the correct location for adding the new functionality. Currently the method looks like:
We just need to call the new
ExceptionNotifier implementation, a first implementation could be something as follows:
We don't need to explain why an
ExceptionNotifierViewModel instance is created, however the next line is critical in the implementation. Without it, the client does not know that an exception took place when calling the server, throwing an exception ensures that the client processing is halted. The
SuspendProcessException is needed as the following changes are done to the Application Dispatcher Unhandled Exception method:
Dependency Injection - Testing Implementation
After the above changes, if we execute the tests we notice that all of them are passing. The fact is that our coverage is not that good; we need a new test that causes a server business exception. The "
CreateDuplicate" test does exactly so, if the test is executed the following window is displayed:
This is obviously a problem, DI can help to resolve this issue. We need to encapsulate the business exception handling on a sort of abstract service and then provide a different implementation when the tests are executed. We need to take the following steps:
- Create a new interface:
- Amend the
ClientServiceLocator so an instance of the new interface is exposed
- Use the new exposed interface in the
- Create a new implementation of the new interface:
- Add another implementation of the interface on the Test project
- Modify Spring.Net configuration files
ServiceAdapterBase now looks like:
The client implementation then is:
The test implementation then is:
Now, if the tests are executed, all of them pass including the new one:
Business Warning Management
We now have a comprehensive mechanism for managing application and business exceptions, but we also need to work out a way for notifying for business warnings. Having dialog windows for warnings could annoy users, so instead we will use a sort of balloon notification running on the Windows Task Bar. For this purpose, we are using the WPF NotifyIcon project. The following steps are required to provide this functionality:
- Create a new interface:
- Add a new service
WarningManager to the
- Change the
ServiceAdapterBase class so it uses the new service
- Create new
- Amend the Spring.Net configuration file to setup the
BusinesswarningManager implementation is as follows:
It is worth noting how relatively easy is to invoke the
TaskbarIcon in the above code. Then we need to change the
ServiceAdapterBase to invoke the new method in the
When a notification is received on the client side, a notification is automatically displayed on the Windows Taskbar:
As we saw with the exception manager, we need a test implementation of the warning manager:
Validation in WPF could be cumbersome sometimes, in this chapter a comprehensive solution using Validation attributes was presented that permits to execute the same validation both in the client and server side thus providing easy testing even when the validation logic is not located at the business entities.