July 2004 - Posts

Serialization of Interfaces and/ or abstract classes via web services..... Objects vs data elements !

So - working on the latest and greatest solution. Great stuff - win forms app - lots (for us) of developers, I have had proper development practice/ time to plan etc so far.. I feel great about the current architecture. One thing is getting my goat and it seems to be something that i have a specific example of -but many have griped about in general. Objects vs data elements - We are basically using a rich domain model along with an MVC pattern - business tier lies behind a web service - so the web service facade is basically the business tier. In essence -we are passing around these 'model types' or 'entity types' between our client tier and our business tier -  which again I mentioned is a web service. This pattern is great and enables the application in just about every way.

The 1st hurdle to overcome - I found very little written about. So -- we have some assmblies that contain (amoungst other things) some 'model types'. The client tier uses these model types - the business tier does. We XML serialize these model types to communicate between the two. This 1st issues was how to declare our model types on the client side using references NOT WEB REFERENCES. We want to add a reference to the library and then use the class - then just pass it across the wire to the business tier (web services). The web services use the SAME library, deserialize the class and KNOW it is the same type as ITS locally referenced class.

Every example out there - you declare any 'model types' as though they belong to the web service- and this is fine for the trivial example, BUT in an application where you are using shared libraries - you WANT the behaviour I am describing. References to assemblies - use your classes - send them to the web service and they stars align.

The answer is dumb. Make your 'model types' in your library assembly XML serializable. You can add some simple attributes like:


[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/FooConcreteA.xsd)]

[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/FooConcreteA.xsd", IsNullable=false)]

public class FooConcreteA : AbstractFooBase


You can also get deeper (you will want to) and assign more granular XML serialization attributes. You can add references to this library assembly to your client project as well as to your web service project. This is the dumb part. Now - make a method that returns a model type and build. Now add a web reference to your client project and build. You get - under the 'web service' reference node in your project a 'Reference.map' - under that is a 'Reference.cs' file. See how your web service proxy is created and a new serializable class with the same name as your original class is created (somewhere near the bottom)? - Comment out that class and add a using your library statement on the top of this class. Now - you are apples to apples - you are referencing the SAME class that is from your library - not this new ghost class that was created for you. So - you can simply use your locally referenced class and hand it to the web service :) (PS - remember that each time you update your web reference the Reference.cs file is destroyed)

Problem 2 - Now we have our nice - rich domain mode. We have objects that contain other objects etc. The issue now is...Objects vs data elements. We have some interfaces and/ or abstract classes. When you make a local reference to a class - you 'have' all of it's methods/ properties - you just need to cast to get pointers to the interface/ class members. When you serialize an abstract class - you get the serialized base information only. For example:


WindowsApplication1.WebService1.Service1 svs = new WindowsApplication1.WebService1.Service1();

//HelloWorld() returns AbstractFooBase - like a factory

AbstractTest.FooConcreteA fooConcreteA = (FooConcreteA)svs.HelloWorld();


This type of thing just does not work. You cannot use any object inheritence (as I can see it) via web service. So - when you have a class that contains a collection of abstract types - you need to manage them EACH BY THEIR INDIVIDUAL CONCRETE TYPE - thereby killing the usefullness of objects.

Still workin' on our incarnation of an answer ....

<Chris/>