ReadOnlyBase and WCF

ReadOnlyBase and WCF

Old forum URL: forums.lhotka.net/forums/t/6899.aspx


rcollette posted on Tuesday, May 05, 2009

I was trying to return a ReadOnlyBase object as part of a WCF JSON service and realized that my properties cannot be readonly for WCF to work.

From Rocky's book, I understand the philosophy that BusinessObjects should be copied to WCF specific objects (DTOs?).  I understand the reasoning for doing so.

Regardless of the philosophy, how is it that DataPortal is capable of transferring a ReadOnlyBase using WCF whereas I am not?  I know, I should trace it but don't have time to set up a test case at the moment.

At the moment, I am making the properties read and write and throwing a not suppported execption in the setter.  I know someone is going to have issue with that but until something more elegant is presented, that is where I am at.

RockfordLhotka replied on Tuesday, May 05, 2009

The data portal uses a different serializer that is designed for rich client/server communication, not contract-based public service communication.

The data portal uses either the BinaryFormatter or the NetDataContractSerializer (depending on technology and configuration choices on your part). Both of these serializers work at the field level, not the property level, and are capable of serializing compex .NET types that can't necessarily be represented by SOAP or JSON.

The XmlSerializer, DataContractSerializer, JsonDataContractSerializer and all the similar variants are absolutely not designed for the rich communciation model required by the data portal. They are all designed to support public contract-based interface models, which is an entirely different scenario from the data portal.

You will really regret exposing your business objects through a public contract-based interface, and I strongly recommend you do the right thing as I discuss in Chapter 21. Obviously it is your choice - I'm just making sure I'm in a position to say "I told you so" when it fails later :)

rcollette replied on Tuesday, May 05, 2009

Now I understand what is going on.  And thank you for the prompt response!  

So if the object is only going to be used to return read only data to a client via JSON, perhaps I should not be constructing a BusinessObject at all.  In this particular scenario I am not using any of the features of a BO and the purpose is more just a DTO.

I realize that by implementing a BO, I give myself the option in the future of doing data binding in another client type perhaps.  However, one of the design priniciples I've come across is not to implement unused functionality.  In this case I would be contructing a BO and a DTO when a simple DTO would suffice.

Code to requirements vs future proofing.  Which does experience tell you to lean towards?   I know this is a situation I would have to be able to justify to peers.

Finally, is there a list or easy way to tell which CSLA.NET objects are serializable via DataContractSerializer and variants thereof and which are not?  I was able to pass a NameValueList to the CascadingDropDown ms ajax toolkit control no problem but I am finding that ReadOnlyBase does not serialize, resulting in the error:

'Csla.Core.FieldManager.FieldData`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' with data contract name 'FieldDataOfstring:http://schemas.datacontract.org/2004/07/Csla.Core.FieldManager' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.

I have a feeling I am going to have a proliferation  BO-DTO mappings when implementing a primarily AJAX client.   Is the unneasy feeling I have about that unjustified?






rcollette replied on Wednesday, May 06, 2009

I tried the following in terms of creating a "lightweight" DTO and it seems to work well.

Extract an interface from the BO
Create a service specific DTO that implements the interface
Pass in the BO to the constructor of the DTO and store in a member variable
Delegate the properties in the DTO to the BO

This way, I am only allocating a single object reference for each BO within the DTO and WCF doesn't complain about any non-serializable members.  Still a bit of work especially if you have a deep object hierarchy but at least this way it's not doing a ton of memory allocation and data copying to construct the DTOs.

Copyright (c) Marimer LLC