Csla light and enum serialization

Csla light and enum serialization

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


kboutsen posted on Tuesday, April 14, 2009

Hello all,

I have a CSLA object library that I also want to use in a Silverlight application. I created a CSLA Silverlight object library and it works. Except for the enums in this library. They don't get serialized.

I read about a solution somewhere, in which you create a new class that inherits from NameValueListBase<,,> and where you use the enum to fill this NameValueListBase<,,> with data.
In this solution the attribute 'RunLocal' is used (not available in the Silverlight CSLA dll), and reflection to get all values from an enum (also not available for Silverlight libraries).

What workaround is there to still be able to use enums in the Silverlight application?

A sample enum/class are:

public enum EnumSample
{
    ENUM_VALUE_1 = 0,
    ENUM_VALUE_2 = 1,
}

[Serializable]
public class ClassSample
{
    // ...

    private static PropertyInfo<EnumSample> EnumSampleProperty =
            RegisterProperty<EnumSample>(typeof(ClassSample), new PropertyInfo<EnumSample>("EnumSample"));
    public EnumSample EnumSample
    {
        get { return GetProperty(EnumSampleProperty); }
        set { SetProperty<EnumSample>(EnumSampleProperty, value); }
    }

   //...
}


The error message that I get is:
Type '***.EnumSample' with data contract name 'EnumSample:http://schemas.datacontract.org/2004/07/***' 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 Windows service that's running the 'Csla.Server.Hosts.IWcfPortal' (for applications that use the regular CSLA .NET objects) and 'Csla.Server.Hosts.Silverlight.IWcfPortal' (for applications that use the Silverlight CSLA .NET objects) services. The Silverlight application uses this service to get the objects.

IanK replied on Tuesday, April 14, 2009

Review post below.

http://forums.lhotka.net/forums/thread/24774.aspx

It may assist you. Its using NVL objects not new class, but does use different code in DataPortal_Fetch

 

Regards

 

kboutsen replied on Tuesday, April 14, 2009

The problem is that the code in that thread also uses the System.Enum.GetValues() function to populate the NVL object. This function is not available in the Silverlight libraries. Maybe there is a workaround?

Kind regards

Peran replied on Tuesday, April 14, 2009

I adapted the code here for the missing System.Enum.GetValues() function in Silverlight

http://dolittle.com/blogs/einar/archive/2008/01/13/missing-enum-getvalues-when-doing-silverlight-for-instance.aspx

RockfordLhotka replied on Tuesday, April 14, 2009

There is a RunLocal equivalent in CSLA .NET for Silverlight. When you create the DataPortal<T> instance, you can specify that it should ignore configuration and run in local-only mode for that request.

kboutsen replied on Wednesday, April 15, 2009

Dear Rocky,

is it possible to give a small code example on this.

What we still don't understand when we are fetching the object at the server side, that we use the enums to fill up the object. Then it gets serialized and at the client side we need to deserialize.
Can it deserialize correctly with your solution?

We also get the errors when we serialize from client side to server side....

Thanks already for  your feedback!

Koen

RockfordLhotka replied on Wednesday, April 15, 2009

I don't know. I don't think we specifically tested using enum values through the MobileFormatter. I've entered a bug so this question/issue doesn't get lost.

http://www.lhotka.net/cslabugs/edit_bug.aspx?id=388

RockfordLhotka replied on Wednesday, April 15, 2009

I guess I should ask a clarifying question though.

Are you saying

  1. A property value of type enum doesn't serialize properly?
  2. A NVL populated with values from an enum doesn't serialize properly?
  3. A custom object of your creation doesn't serialize properly?

I could see 1, as that's what we didn't test (I don't think).

If the problem is 2, then that's almost certainly a bug in your code, because I know NVL objects serialize just fine - I use them all the time.

If the problem is 3, then we need to talk about how you created the custom object. The MobileFormatter has very strict requirements around what objects it will and won't serialize, and if you want to pass any custom object through the data portal you have to create the object exactly right. CSLA has base classes you should inherit from, but the easiest solution, by far, is to use one of the normal business object base classes with managed backing fields - otherwise you'll have to do some extra work.

kboutsen replied on Wednesday, April 15, 2009

It's problem 1. A property value of type enum doesn't serialize.

The sample code that I posted was:
public enum EnumSample
{
    ENUM_VALUE_1 = 0,
    ENUM_VALUE_2 = 1,
}

[Serializable]
public class ClassSample
{
    // ...

    private static PropertyInfo<EnumSample> EnumSampleProperty =
            RegisterProperty<EnumSample>(typeof(ClassSample), new PropertyInfo<EnumSample>("EnumSample"));
    public EnumSample EnumSample
    {
        get { return GetProperty(EnumSampleProperty); }
        set { SetProperty<EnumSample>(EnumSampleProperty, value); }
    }

   //...
}

I had a managed backing field of type enum. I re-wrote it now, so I have a regular property of type enum and a managed backing field of type int. The enum property gets and sets it's value according to the int backing field. This field can be serialized and on the client we can re-construct the enum using this int. By marking this int managed backing field 'private', the user of this code doesn't see this field and uses the regular enum property.

The new code for the class becomes:

[Serializable]
public class ClassSample
{
    // ...

    /* This property is used on client side, it is constructed by using the
     * int property below
     */
    public EnumSample EnumSample
    {
        get { return (EnumSample)EnumSampleInt; }
        set
        {
            EnumSampleInt = (int)value;
        }
    }

    private static PropertyInfo<int> EnumSampleIntProperty= RegisterProperty<int>(typeof(ClassSample), new PropertyInfo<int>("EnumSampleInt"));
    /* This property is used for serializing
     * This property is also used for constructing the enum property above
     */
    private int EnumSampleInt
    {
        get { return GetProperty(EnumSampleIntProperty); }
        set { SetProperty<int>(EnumSampleIntProperty, value); }
    }

    // ...
}


Thanks a lot for your feedback. I hope my solution can be a solution for others too (until there is a better one).

Kind regards,
Koen

RockfordLhotka replied on Wednesday, April 15, 2009

Thanks for the detailed explanation, that helps a lot.

Hopefully we can figure out a solution. The process of serializing values to/from Silverlight and .NET is complex because they are two different platforms, so there are no common types between them. Even what we see as the "same type" is actually not the same type at all...

stuart.bale replied on Saturday, March 13, 2010

Hi,

I'm just wondering what the final outcome of this was?

I see the 'bug' is closed as resolved, however when I try and use enums in a Silverlight/.Net mixed environment, I still receive the serialize error.

Is there an attribute i need to set on the enum to make this work???

Stuart

 

 

RockfordLhotka replied on Saturday, March 13, 2010

It sure looks like the fix was applied in April 2009:

http://www.lhotka.net/cslacvs/viewvc.cgi/core/trunk/Source/Csla.core/Serialization/Mobile/MobileFormatter.cs?r1=3787&r2=3934

Based on the code, I can't see how a special attribute or anything would be required - the serializer is just locating anything of type enum and is converting it to the underlying type.

stuart.bale replied on Saturday, March 13, 2010

Hi Rocky,

Thanks for the awesomely quick reply!

I've looked through all your CSLA light samples, and I can't see anywhere at all that you have ever used an enum as property type.

I've already converted all my PropertyInfo to now use <int>, but I'll make up a quick project later today to get the exact error that occurs.  (It was a few hours ago, and my memory doesn't span that far back ;-).)

Will post here later today.

Stuart

RockfordLhotka replied on Saturday, March 13, 2010

There's a unit test for this: BusinessObjectWithEnum() in the Silverlight serialization tests.

skagen00 replied on Monday, March 15, 2010

Just wanted to mention that I am using the latest and I seem to be having an issue with enums as well. Using the very latest CSLA.

Type '<mytype>' with data contract name '<enumtype>:http://schemas.datacontract.org/2004/07/<ns>' 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'm just going to use an integer for the property as I know that works, but just thought I'd mention this too.

 

RockfordLhotka replied on Monday, March 15, 2010

We will have to re-open that bug then. This is odd though, since there is a unit test covering the scenario and it passes on both SL and .NET. The one thing the test doesn't cover is actually sending the value through the data portal, but technically that shouldn't matter if clone works on both sides. Obviously it does matter though Tongue Tied

stuart.bale replied on Tuesday, March 16, 2010

Yes, that's the error I receive too, in the Silverlight client, when I attempt a save on the CslaDataProvider.

I am using Csla 3.8.2.  (I haven't had time to replicate into a separate project.)

Stuart

RockfordLhotka replied on Thursday, March 25, 2010

This is a confirmed bug btw, and Sergey is working on a fix.

It actually has to do with n-level undo, because the serialization used there isn't the same as the serialization used by the data portal...

CalvaryLogic replied on Tuesday, March 30, 2010

RockfordLhotka

If the problem is 3, then we need to talk about how you created the custom object. The MobileFormatter has very strict requirements around what objects it will and won't serialize, and if you want to pass any custom object through the data portal you have to create the object exactly right. CSLA has base classes you should inherit from, but the easiest solution, by far, is to use one of the normal business object base classes with managed backing fields - otherwise you'll have to do some extra work.

Hi Rocky,

This caught my eye as I am trying to send a custom criteria object through the data portal.  I'm using CSLA Light 3.8.2.  My custom criteria object inherits from Csla.CriteriaBase.  I've tagged the class as Serializable using the Csla.Serialization.SerializableAttribute.  I declare my criteria class with a single generic type T.  The custom criteria class has 2 properties... Name (string) and Value (object).  BeginFetch is called with this criteria, from my ELRB based list class.  The criteria property values look good going in to the call, but in the DataPortal_Fetch on the server side, both property values are null.  What else do I need to do to ensure proper serialization of a custom criteria object?

Thanks,
Matt

RockfordLhotka replied on Tuesday, March 30, 2010

You need to either use managed properties or you need to override OnGetState() and OnSetState() to put your private field values into the serialization stream.

CalvaryLogic replied on Wednesday, March 31, 2010

RockfordLhotka

You need to either use managed properties or you need to override OnGetState() and OnSetState() to put your private field values into the serialization stream.

Ah yes, rookie mistake... forgot to configure my properties as managed.  I did that and it works now.  Thanks!

Matt

RockfordLhotka replied on Wednesday, March 31, 2010

fwiw, in CSLA 4 this will get easier because CriteriaBase is generic, so the same RegisterProperty() syntax used in a business object will work in a criteria object (and a command object and an identity object).

skagen00 replied on Wednesday, March 31, 2010

I'm glad to hear that. I've lately found myself using readonlybase type objects for criteria objects.

Look forward to hearing all about it at Code Camp on Apr 10th.

 

RockfordLhotka replied on Wednesday, March 31, 2010

skagen00

Look forward to hearing all about it at Code Camp on Apr 10th. 

I am hoping that I can show the new business rules subsystem. That's what I'm working toward anyway Big Smile

Copyright (c) Marimer LLC