Static field disappears on WCF

I spent 10+ hours on this problem, ‘Specified cast is not valid’ on a CSLA library deployed onto WCF host. I figured out this is caused by inherited properties in BO were lost. The propertyInfo list is different between server and client, one side (server) doesn’t contain those properties from baseBO.

More details, BO can be retrieved from WCF, change one of it’s property, save BO, then this problem occured. Debug turns out before saving, the client side still had a full list of properties including inherited ones, but after serilizing-deserilizing, the one transfered to server side magically lost those base properties should inherite from ancestor!

We know that by adding a dummy static field can fix the similar problem, but that only works in non-WCF mode. Why not in WCF mode? Somewhere CSLA and WCF/dotNet static fields doesn’t like each other, again.

I am tired of this kind of issues, fortunatelly, I found a work around.

Always keep a non-RunLocal DataPortal_Create method in BO, and create a NewYourBO() factory method calling this DataPortal_Create(). When you get this ‘Specified cast is not valid’ problem, just try to add this NewYourBO factory method right before your fetch operation. For a collectionBO, it should be in GetYourBOCollection()

internal static YourBOColleciton()
{
if (Csla.ApplicationContext.DataPortalProxy.Contains(“WcfProxy”)) YourBO.NewYourBO();
return DataPortal.FetchChild<YourBOCollection>();
}

For a non-collection BO, it should be in GetYourBO():

internal static GetYourBO()
{
if (Csla.ApplicationContext.DataPortalProxy.Contains(“WcfProxy”)) NewYourBO();
return DataPortal.FetchChild<YourBO>();
}

Looks like my extra code are doing a initialize work, setting up on both server and client side to make sure both side have the full property list ready.

Someday I will come back with a explaination.

Most of my problemic BOs are child type. I tried using DataPortal_CreateChild instead of DataPortal_Create, it failed. Perhaps the CreateChild one doesn’t return anything to client side.

There is a similar problem when moving multi-level inheritance to WCF host. The properties in middle level also be lost when fetching data down to client side. Similar workaround is to call the local constructor right before retrieve.

internal static GetYourBO()
{
if (Csla.ApplicationContext.DataPortalProxy.Contains(“WcfProxy”)) {
new YourBO(); // to trigger static field in local contrustctor
// Or Activator.CreateInstance(typeof(YourBO<T>), true);
NewYourBO(); // to trigger static field in remote constructor
}
return DataPortal.FetchChild<YourBO>();
}

Update:

Bought the newest eBook from Rocky, the solution is in OnDeserialized. We had to added base.OnDeserialized(context) because we are doing multi-level inheritance. Thanks Kevin, Thanks Rocky.

private static int _init; // This must be a private type, even protected type won’t work.
protected CommentBOBase()
{
_init = 0;
}

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)
{
base.OnDeserialized(context);
_init = 0;
}

My experience is, we only need to add this piece of hacking code to those base classes with static fields declared. The inherited class doesn’t need to do this trick.

Related posts:

http://forums.lhotka.net/forums/thread/24472.aspx
http://forums.lhotka.net/forums/post/26822.aspx
http://forums.lhotka.net/forums/thread/26849.aspx

Advertisements

4 thoughts on “Static field disappears on WCF

  1. I seem to remember Rocky saying somewhere although I cannot find it, that you need to add OnSerializing/OnDeserializing to your BO and touch the dummy static there too. I’m not keen on any of these touching hacks, but???

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s