Friday, 16 October 2009

AOP style WPF validations part 2

In the first part of this series I explained how we tried to do AOP style validations with WPF. I succeeded in doing that with the NetDataContractSerializer and also provided some links that explain why you actually don't want to use that serializer. At the end of my post I wrote that we were going to try to do something with the IDataContractSurrogate.

So let’s continue. I’ll take you through the process step by step. Beware, we were obliged to use VB.NET, but when we see the chance we’ll create C# projects as well. That means this post is going to contain both VB.NET and C#.

We already have a validation framework in place. So, obviously, we want to reuse that. That is however a bit difficult to do in WPF because WPF validation is based on the IDataErrorInfo interface. We did not want to implement that interface on our models. (if you have a look at the interface you’ll know why). That’s why we took another approach. First we put a validation attribute on our WCF datacontract:

   1: <DataMember()> _
   2:         <NotNullOrEmptyValidationConstraint("RequiredField")> _
   3:         Public Overridable Property FamilyName() As String
   4:             Get
   5:                 Return m_FamilyName
   6:             End Get
   7:             Set(ByVal Value As String)
   8:                 m_FamilyName = Value
   9:             End Set
  10:         End Property

Then we need a way to reuse that attribute for WPF validation. That is where DynamicProxy comes into play. (Note: you could also resolve the entity from the Windsor container of course)

Creating an entity

Let’s first cover the use case of creating an Employee. In our presenter we used to new the Employee entity. Now we use a little class called ObjectFactory that creates the employee for us

   1: public static class ObjectFactory
   2:     {
   3:         private static readonly ProxyGenerator _generator = new ProxyGenerator();
   4:  
   5:         public static object CreateWithValidation(Type t)
   6:         {            var interceptors = new IInterceptor[]
   7:                                    {
   8:                                        new EditableBehaviorInterceptor(), new DataErrorInfoInterceptor(),
   9:                                        new PropertyChangedInterceptor()
  10:                                    };
  11:  
  12:             var proxy = _generator.CreateClassProxy(t, new[] { typeof(IDataErrorInfo), typeof(INotifyPropertyChanged),typeof(IProxied) },
  13:                                       new ProxyGenerationOptions(new ValidationProxyGenerationHook()), interceptors);
  14:             return proxy;
  15:         }
  16:  
  17:  
  18:         public static T CreateWithValidation<T>() where T : class
  19:         {
  20:             return (T)CreateWithValidation(typeof(T));
  21:         }        
  22:     }   

The “CreateWithValidation” method creates a proxy with the help of DynamicProxy and adds several interceptors to the proxy. In this post it’s the DataErrorInforInterceptor we care about. We use an adapted version of the one written by the guys of the “Unofficial NHibernate addins” and it looks like this:

   1: public class DataErrorInfoInterceptor : IInterceptor
   2:     {         
   3:         #region IInterceptor Members
   4:  
   5:         public void Intercept(IInvocation invocation)
   6:         {
   7:             if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
   8:             {
   9:                 if ("get_Item".Equals(invocation.Method.Name))
  10:                 {                    
  11:                     var summary = new ValidationSummary();                    
  12:                     Validator.IsValid(invocation.Proxy, ref summary);
  13:                     var invalidValues = summary.Messages.Where(p=> p.PropertyName == Convert.ToString(invocation.Arguments[0])).Select(p => p.Message).ToArray();
  14:                     if (invalidValues.Count() > 0)
  15:                     {
  16:                         invocation.ReturnValue = string.Join(Environment.NewLine, invalidValues);   
  17:                     }
  18:                     else
  19:                     {
  20:                         invocation.ReturnValue = null;   
  21:                         
  22:                     }
  23:  
  24:                     
  25:                 }
  26:                 else if ("get_Error".Equals(invocation.Method.Name))
  27:                 {
  28:                     var summary = new ValidationSummary();
  29:                     Validator.IsValid(invocation.Proxy, ref summary);
  30:                     var invalidValues = summary.Messages.Select(p => p.Message).ToArray();
  31:                     if (invalidValues.Count() > 0)
  32:                     {
  33:                         invocation.ReturnValue = string.Join(Environment.NewLine, invalidValues);   
  34:                     }
  35:                     else
  36:                     {
  37:                         invocation.ReturnValue = null;
  38:                         
  39:                     }
  40:  
  41:                 }
  42:             }
  43:             else
  44:             {
  45:                 invocation.Proceed();
  46:             }
  47:         }
  48:  
  49:         #endregion
  50:     }
  51: }

Now the only thing that is left to do is to add “ValidatesOnDataErrors” on your binding in XAML.

   1: <TextBox x:Name="txtLastName" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="1"
   2:                              Text="{Binding Path=Intern.InternInfo.FamilyName,ValidatesOnDataErrors=true}" 
   3:                              MinWidth="50"  Margin="0,2" Style="{StaticResource UpperCaseTextBox}" />

When you run the WPF application now, you will get those nice red borders around your textboxes when you do someting wrong.

Modifying an entity

It gets more complicated when you want to do the same thing when modiying the same Employee again. We use WCF on this particular project which means we have to find a way to give a proxy that implements IDataErrorInfo to the client. It turns out that the extensibility of WCF can help us here. WCF allows you to hook in the (de) serialization process and you can do that by implementing to IDataContractSurrogate interface.

   1: Public Class ValidationDataContractSurrogate
   2:        Implements IDataContractSurrogate
   3:  
   4:        Private m_TypesToProxy() As Type
   5:  
   6:        Public Property TypesToProxy() As Type()
   7:            Get
   8:                Return m_TypesToProxy
   9:            End Get
  10:            Set(ByVal value As Type())
  11:                m_TypesToProxy = value
  12:            End Set
  13:        End Property
  14:  
  15:        Public Sub New(ByVal proxyTypes As Type())
  16:            TypesToProxy = proxyTypes
  17:        End Sub
  18:  
  19:  
  20:        Public Function GetDataContractType(ByVal type As Type) As Type Implements IDataContractSurrogate.GetDataContractType
  21:            Return type
  22:        End Function
  23:  
  24:        Public Function GetObjectToSerialize(ByVal obj As Object, ByVal targetType As Type) As Object Implements IDataContractSurrogate.GetObjectToSerialize            
  25:            Return obj
  26:        End Function
  27:  
  28:        Public Function GetDeserializedObject(ByVal obj As Object, ByVal targetType As Type) As Object Implements IDataContractSurrogate.GetDeserializedObject
  29:            If (TypesToProxy.Contains(obj.GetType)) Then
  30:                Dim destination = ObjectFactory.CreateWithValidation(obj.GetType)
  31:                PropertyCopy.Copy(obj, destination)
  32:                Return destination
  33:            End If
  34:  
  35:            Return obj
  36:        End Function
  37:  
  38:        Public Function GetCustomDataToExport(ByVal memberInfo As MemberInfo, ByVal dataContractType As Type) As Object Implements IDataContractSurrogate.GetCustomDataToExport
  39:            Throw New NotImplementedException()
  40:        End Function
  41:  
  42:        Public Function GetCustomDataToExport(ByVal clrType As Type, ByVal dataContractType As Type) As Object Implements IDataContractSurrogate.GetCustomDataToExport
  43:            Throw New NotImplementedException()
  44:        End Function
  45:  
  46:        Public Sub GetKnownCustomDataTypes(ByVal customDataTypes As Collection(Of Type)) Implements IDataContractSurrogate.GetKnownCustomDataTypes
  47:            Throw New NotImplementedException()
  48:        End Sub
  49:  
  50:        Public Function GetReferencedTypeOnImport(ByVal typeName As String, ByVal typeNamespace As String, ByVal customData As Object) As Type Implements IDataContractSurrogate.GetReferencedTypeOnImport
  51:            Throw New NotImplementedException()
  52:        End Function
  53:  
  54:        Public Function ProcessImportedType(ByVal typeDeclaration As CodeTypeDeclaration, ByVal compileUnit As CodeCompileUnit) As CodeTypeDeclaration Implements IDataContractSurrogate.ProcessImportedType
  55:            Throw New NotImplementedException()
  56:        End Function
  57:  
  58:    End Class

When deserializing we create the proxy in the same way we did for a new Employee and we copy the object we receive in the parameter of that method to the proxy. To copy the properties we use a little class from Jon Skeet. Now we need to tell WCF to use our surrogate. We do that with the help of a OperationBehavior:

   1: Public Class AddValidationDataContractSerializerOperationBehavior
   2:         Inherits DataContractSerializerOperationBehavior
   3:  
   4:         Private m_TypesToProxy() As Type
   5:  
   6:         Public Property TypesToProxy() As Type()
   7:             Get
   8:                 Return m_TypesToProxy
   9:             End Get
  10:             Set(ByVal value As Type())
  11:                 m_TypesToProxy = value
  12:             End Set
  13:         End Property
  14:  
  15:         Public Sub New(ByVal description As OperationDescription, ByVal proxyTypes As Type())
  16:             MyBase.New(description)
  17:             TypesToProxy = proxyTypes
  18:         End Sub
  19:  
  20:         Public Overloads Overrides Function CreateSerializer(ByVal type As Type, ByVal name As XmlDictionaryString, ByVal ns As XmlDictionaryString, ByVal knownTypes As IList(Of Type)) As XmlObjectSerializer
  21:             'maxItemsInObjectGraph
  22:             'ignoreExtensionDataObject
  23:             'preserveObjectReferences
  24:             'dataContractSurrogate
  25:             Return New DataContractSerializer(type, name, ns, knownTypes, &H7FFF, False, _
  26:                                               True, New ValidationDataContractSurrogate(TypesToProxy))
  27:         End Function
  28:  
  29:     End Class
   1: ''' <summary>
   2:     ''' Attribute to be put on an operation in the service contract. You need to pass the types that
   3:     ''' need to be proxied.
   4:     ''' </summary>
   5:     ''' <remarks></remarks>
   6:     Public Class AddValidationToDataContractAttribute
   7:         Inherits Attribute
   8:         Implements IOperationBehavior
   9:  
  10:         Private m_TypesToProxy() As Type
  11:  
  12:         Public Property TypesToProxy() As Type()
  13:             Get
  14:                 Return m_TypesToProxy
  15:             End Get
  16:             Set(ByVal value As Type())
  17:                 m_TypesToProxy = value
  18:             End Set
  19:         End Property
  20:  
  21:         Public Sub New(ByVal types() As Type)
  22:             TypesToProxy = types
  23:         End Sub
  24:  
  25:  
  26:         Public Sub AddBindingParameters(ByVal description As OperationDescription, ByVal parameters As BindingParameterCollection) Implements IOperationBehavior.AddBindingParameters
  27:         End Sub
  28:  
  29:         Public Sub ApplyClientBehavior(ByVal description As OperationDescription, ByVal proxy As System.ServiceModel.Dispatcher.ClientOperation) Implements IOperationBehavior.ApplyClientBehavior
  30:             Dim innerBehavior As IOperationBehavior = New AddValidationDataContractSerializerOperationBehavior(description, TypesToProxy)
  31:             innerBehavior.ApplyClientBehavior(description, proxy)
  32:         End Sub
  33:         Public Sub ApplyDispatchBehavior(ByVal description As OperationDescription, ByVal dispatch As System.ServiceModel.Dispatcher.DispatchOperation) Implements IOperationBehavior.ApplyDispatchBehavior
  34:  
  35:         End Sub
  36:  
  37:         Public Sub Validate(ByVal description As OperationDescription) Implements IOperationBehavior.Validate
  38:  
  39:         End Sub
  40:     End Class

Then the only thing left to do is to add our attribute to the operation in the service contract:

   1: <OperationContract()> _
   2:     <TransactionFlow(TransactionFlowOption.Allowed)> _
   3:     <AddValidationToDataContract(New Type() {GetType(InternInfo), GetType(FrameRealInfo)})> _
   4:     Function GetIntern(ByVal id As Integer) As InternInfo

That’s it. Now we also have validation for entities that already exist. There is one important remark here. As you can see I have put the attribute on a method that returns 1 instance of a DataContract and there is a pretty good reason for that. In the implementation of IDataContractSurrogate you have seen that we copy the properties to the proxy. That’s something you can do for 1 instance, but when you do that for a large collection of objects it takes way too much time. All in all I think this is a pretty elegant way of dealing with validation in WPF.

Monday, 31 August 2009

AOP style WPF validations and Automapper

We have been working on a WPF application since june now and it's about time we add some validation to it. A solution would be to implement IDataErrorInfo on our WCF datacontracts since we are using those WCF datacontracts for databinding as well. Unfortunately implementing the IDataErrorInfo interface is cumbersome and error prone especially when you already have an attribute based validation framework in place.

Luckily I stumbled on a post on NHForge that explained how you could accomplish the same using a DynamicProxy interceptor. You basically add the IDataErrorInfo implementation via an interceptor. I adapted the interceptor a little bit so that it worked with our own validation framework. There were a couple of problems left though. First of all we are using the great AutoMapper framework to create our DTOs from our domain entities, but now our DTOs needed to be created by our Windsor container and then filled by AutoMapper. Some googling aroud learned me that you can actually do that now. When creating the mapping you can tell AutoMapper which constructor to use:

   1: Mapper.CreateMap<Foo, Bar>().ConstructUsing(foo => new Bar()); 

This means you can also do something like this:

   1: Mapper.CreateMap<Foo,Bar>()
   2:       .ConstructorUsing(foo ==> ServiceLocator.GetService<Bar>());

Now I have my datacontract including the interceptor for validation. I am telling you this because I think it could be a very interesting feature of AutoMapper. In my case however I still had a problem. I need to be able to send my datacontract to the client. I managed to do this using the NetDataContractSerializer as explained in this post. After that I did some more research on the NetDataContractSerializer and

got me thinking that it is probably not the best solution.

So tomorrow I will see whether I can find a better approach using IDataContractSurrogate. I actually don't need the interceptor server side and I want to try to add it to the datacontract when deserializing it. Could be interesting.

Anyway, although I did not find the ideal solution yet, I did discover a pretty interesting feature of AutoMapper ;-)

Tuesday, 25 August 2009

Castle WCF facility and bit of channel reconnection

Ever since my previous project we are using the WCF facility to be able to use dependency injection on WCF services. It's a wonderful piece of software but there is not much written on it. The main contributor of the WCF facility is Craig Neuwirt, the guy that received the first Hostile Blogging award. Since then he has a blog, but since he also has three kids he does not have much time to write blog posts. I only have two (a 3yr old boy and a 2 months old boy) but I can definitely understand that he does not have much time to write blog posts. As a matter of fact, I'll probably have to stop writing this one because the youngest is about to get hungry, and he does not accept: "Daddy is writing a blog post" as an answer.

All right, back to the WCF facility. I was saying there is not much documentation, but there is some interesting stuff out there that certainly can get you started:

  1. The Castle page dedicated to the facility
  2. Mike Hadlow wrote six posts on the WCF facility

Those two sources definitely should get you started. When you start with it, don't make the same mistake we did. We only thought we could use it on the service provider side so that our WCF services were created by the service host factory from the WCF facility and had immediate DI support. We did not see that we could also greatly benefit from the WCF facility on the service consumer side. The WCF facility allows you to register your WCF service in the Windsor container and then use them as any other component you have registered in Windor.

   1: public class SomePresenter
   2: {
   3:     private ISomeService _someService;
   4:  
   5:     public SomePresenter(ISomeService someService)
   6:     {
   7:         _someService = someService;
   8:     }
   9:  
  10:     public void DoSomePresenterThing()
  11:     {
  12:         _someService.DoIt;
  13:     }
  14: }

One more thing to finish of. If you would experience channel connection issues, you get for example communication exceptions. There is an easy solution for that in the WCF facility. You just need to register the ChannelReconnectPolicy. This policy will reconnect the proxy and the service host in case certain exception occur. The "CanRecoverFromCommunicationExceptionOnEndpoint" test in the WCFClientFixture demonstrates how you register this policy.

And now it's time to feed the hungry baby ;-)

Thursday, 13 August 2009

How to take advantage of Horn in your project

In most of the projects we do we have a lot of dependencies on open source libraries and when you have to upgrade one of those libraries to a newer version, that's where you start feeling the pain. The Scottish ALT.NET group wants to provide a solution for this. It's called Horn and there is a great introductory post by Alex Henderson here. I gave it a try and it just worked.

That's why I wanted to take it one little step further and actually create a small BOO script to build our internal framework which depends on Castle, NHibernate, Fluent NHibernate, Moq, and Automapper. I'm probably forgetting some now ;-)

The first thing to do is to locate the package tree in your user profile:C:\Users\Bart\.horn. There you add a new folder of your own and the easiest thing to do is to copy one of the *.BOO files that come with Horn itself. Adapt the *.BOO file to your needs by for example adding the depencies you have in your project and you're done.

My Horn *.BOO script now looks as follows:

   1: install cap:
   2:     description "The Capgemini Belgian .NET framework"
   3:     get_from svn("https://scm-coconet.capgemini.com/svn/repos/belgianadf")
   4:     build_with msbuild, buildfile("Capgemini.Adf/trunk/Capgemini.Adf.sln"), FrameworkVersion35                
   5:  
   6:     with:
   7:         tasks clean,release,platformNet35
   8:  
   9:     shared_library "Capgemini.Adf/trunk/References"
  10:     build_root_dir "bin/net-3.5/release"        
  11:     
  12: dependencies:
  13:     depend "castle.tools"        >> "Castle.Core"    
  14:     depend "castle.tools"         >> "Castle.DynamicProxy2"
  15:     depend "castle.windsor"      >> "Castle.MicroKernel"
  16:     depend "castle.windsor"      >> "Castle.Windsor"    
  17:     depend "nhibernate"             >> "2.1" >> "NHibernate"     
  18:     depend "nhibernate"             >> "2.1" >> "NHibernate.ByteCode.Castle"
  19:     depend "nhibernate"          >> "2.1" >> "Iesi.Collections"
  20:     depend "nhibernate.caches"   >> "NHibernate.Caches.SysCache"
  21:     depend "fluentnhibernate"    >> "FluentNHibernate"
  22:     depend @log4net              >> "1.2.10" >>  "log4net"    
  23:     depend "automapper"             >> "AutoMapper"
  24:     depend "moq"                >> "Moq"
  25:  

Just run it in your command line: horn -install:cap

Tuesday, 21 July 2009

The end of the traditional use case

I have been writing use cases for several years now and although I always was quite comfortable with them, something felt wrong somehow. Recently I gave it some more thought and that made me conclude the traditional use case does not fulfill the needs of modern software development anymore.

What is a traditional use case anyway? For me it is the use case as it is being used in the RUP. That means a great deal of effort is being put into using the right template in the right way and making sure you play by the RUP use case rules. Sometimes more effort is spent in getting the document right according to someone's interpretation of the standards than in actually finding out what the customer wants. That just does not feel right to me. I realize there are advantages when everyone is using the same document templates in the same way but it really should not become the ultimate goal.

I am not saying we should not write documents that describe the functionalities of the system being built. I only think there must be an easier less time consuming way to do that. Something that adheres more to the "Simplest thing that can possibly work" principle.

In my current project we are using Targetprocess again as our lightweight agile project management tool. Together with the product owner we work on the backlog that contains user stories. A user story is a much less formal way of describing requirements and consequently a lot less time is spent in writing them. I personally also believe they are easier to read and understand for a product owner. Because user stories are easier to write I also don't mind creating them when something pops up which is of course really good for the completeness of the requirements. With use cases that somewhat different. If you want to play by the rules, you first have to find out whether it really is a use case or part of another use case or a non functional requirement or even something else. Then you need to create a complete document based on a template that is not always easy to work with, and then you can ask the product owner to review it.

In modern software development we want to be agile and that also applies to the requirements. The traditional use case is far from being agile and that's why it will probably fade away or evolve to something less formal and easier to work with.

Monday, 6 July 2009

It is time to mention Caliburn

I have been on a new project since the end of may now and as I already explained in my last post it concerns a WPF project. I must admit I was a bit sceptic at first but now that I know WPF somewhat better I actually start to like it.

It helps of course that we are using Caliburn because I recognise a lot of the things I knew from Monorail and ASP.NET MVC. Next to that there is also a pretty active community behind Caliburn. I don't think it is that big, but they certainly have been a tremendous help to us in the last month.

Today for example I wanted to show a "Loading..." dialog when the system was busy doing something. One of the Caliburn samples also had this and I started to implement it in our solution as well. For some reason however the "Loading..." dialog was only shown after my presenter action while I called it in the beginning of my presenter action.

I realized that was happening because my presenter action was synchronous and it kept the UI thread busy until the action was completed. I did not know however how to solve that one. Luckily there were other people that did know how to tackle it: http://caliburn.codeplex.com/Thread/View.aspx?ThreadId=61568

I ended up creating a "pre" and "post action" filter and applied that one to my base presenter. In that way I have my loading screen for every presenter and every action and I do not have to write tedious hourglass code ;-)

Thursday, 18 June 2009

The next project: embracing the rich client

It has been a while since my last post. That does not mean it has been a calm period. I had a very interesting 3 days at Progressive.NET where I especially liked the sessions of David Laribee.

After that I started on a new project, at least new to me. They were just starting the real development (it was about time in my humble opinion) and it was my first encounter with WPF. The rest of the stack is pretty much the same as my last project: WCF, NHibernate, and Castle Windsor but we added some new libraries such as Fluent NHibernate and AutoMapper. I have been involved in the project for about a month now, and I must say that I really start to like WPF. It has some great features, and the split between UI design and the rest of the code is really great.

I needed to choose a pattern for the client side development. That was less easy than with web development in ASP.NET MVC. Apparently I could choose between MVVM, MVP and MVC... We started out with MVVM but after a couple of days I felt it complicated things more than it made it easy. That's why we went for MVP using Caliburn. Until now I don't regret that decision. Many of the things that I knew from Monorail and ASP.NET MVC  and that made life easier in the web world, are also used in Caliburn, and that just feels comfortable.

In my previous project we did not succeed in getting good test coverage, and that is a understatement. I felt that I needed to do better in this new project and you of course you need to do that from the beginning on. That's why I went for TDD and I must say it delivers. Actually the only way to get good test coverage is to start with writing tests. If you don't do that, you just deliver a piece of functionality and you move on, because of course you have challenging deadlines. I also discovered TestDriven.Net and it is just wonderful.

Hopefully I find some time the next few weeks to write some posts on how we are designing this project.