Sunday 20 January 2013

Serialization and Deserialization woes in WCF

WCF is a great technology at getting a service up and running in quick time on any kind of transport. Another great thing about WCF is that it is ultra extensible. You can replace almost every default implementation - Authorization, Serialization, Validation, etc.
 
I ran into an interesting situation recently. I had WSDL and XSD schema files which had already been shared with consumers of the WCF service. Due to the way WSDL and XSD were written (I guess hand coded), svcutil.exe and wsdl.exe were not able to generate appropriate proxy. Then XSD.exe came to rescue. I created the C# classes for all the types defined in XSD schema files and manually created the [ServiceContract] and [OperationContract]. All good till now.
 
As I started testing the application using SoapUI, I ran into following problems (in the below specified order):
 
1. "SOAP Action not supported". After a bit of troubleshooting it became clear that WCF service was expecting a default SOAP action for each method as hand coded [ServiceContract] and [OperationContract] was using default options.
 
To resolve the problem, I found the expected SOAP action from the WSDL file and updated the OperationContract to include the action. e.g. [OperationContract(Action="ExpectedAction")]
 
2. Input parameters to the WCF service were null. It turned out that the deserialization process was not working properly.
 
To resolve the issue, I had to manually update the DataCotnract classes as well. Apparently the SOAP message body was not expected to the wrapped and the default implementation is to wrap request and response. I changed the data contracts to use [MessageContract[IsWrapped=false)] to fix the problem.
 
And while I was doing the above, re-learned a few things about XmlSerialization.
1. If a class has an optional value type property, then it is expected that you add a Boolean property named [PropertyName]Specified and decorate it with [XmlIgnore]. This companion property is used to find out if value needs to be considered during serialization and deserialization. e.g.
[XmlElement]
public int Age { get { return _age;}  set { _age = value, AgeSpecified= true;} }
[XmlIgnore]
public bool AgeSpecified { get; set;}
2. How do you send empty string for fields that have data type like DateTime or an Enum. Simple - Add additional properties of String data type to the class and decorate those with XmlElement (with desired name) and mark the actual fields with XmlIgnore. e.g.
[XmlElement("BirthDate"]
public string BirthDateTimeString { get; set;}
[XmlIgnore]
public DateTime BirthDate { get; set;}

Tuesday 15 January 2013

ASP.NET MVC with ViewModel

Many a times I have seen a team member get obsessed with a particular design pattern and implement it in its purest form. And then that slowly, in a few months, leads to problems because requirements keep getting added to the pile and the team tries to implement new requirements without violating the pattern and conformity. Those are the times when you need to think of mixing patterns and assess if that helps in keeping the implementation flexible and understandable.

One such case if MVC. As the UI screens keep getting complex, strongly typed views require changes in the underlying model. I think in such cases, MVC with ViewModel is a very good solution. It allows us to keep UI complexity in ViewModel without affecting the Model which is a good thing because the core business entities and domain model change at a much slower rate than the rate at which UI and services changes. It is pretty effective when we use strongly typed views in ASP.NET MVC applications.

Below are couple of nice articles that explain the advantage of using ViewModel in ASP.NET MVC applications.

http://nerddinnerbook.s3.amazonaws.com/Part6.htm

http://www.highoncoding.com/Articles/659_Implementing_ViewModel_in_ASP_NET_MVC_Application.aspx

This gives a fresh perspective into how we should look to mix and match different design patterns and find a hybrid pattern that best solves the given problem. Once you do that you ought to document it in detail too so that it does not create any confusion in the head of a new team member.