MobileDictionary Serialization Exception

MobileDictionary Serialization Exception

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


trives posted on Wednesday, October 12, 2011

My application is running CSLA 4.1.0 (110118), and I have a command object that includes a property of type MobileDictionary<K, V>.  K is int, and V is a type that implements IMobileObject, call it MyApp.SimpleBusinessObject.  When calling Execute on the command object from a Silverlight client, I am getting a SerializationException. 

'MyApp.SimpleBusinessObject' with data contract name ‘SimpleBusinessObject:http://schemas.datacontract.org/2004/07/MyApp’ is not expected. Consider using a DataContractResolver or 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.

The exception appears to be caused by the cloning, which uses the default BinaryFormatter, that occurs server-side in the DataPortal.Update<T> and the subsequent serialization by the MobileFormatter just prior to the command returning to the Silverlight client.  It's this last serialization that throws the exception.

Here is a unit test that should generate the exception:

 [TestMethod]
public void TestMethod1()
{
    // Instantiate a simple business object (i.e. MobileObject).
    var simple = SimpleBusinessObject.NewObject();
    simple.Id = 5;

    // Instantiate a MobileDictionary and add the simple business object to it.
    var dictionary = new MobileDictionary<string, SimpleBusinessObject>();
    dictionary.Add(
"test", simple);

    // Clone the dictionary using the default BinaryFormatter.
   
var clone = ObjectCloner.Clone(dictionary) as MobileDictionary<string, SimpleBusinessObject>;

    // Serialize the cloned MobileDictionary using the MobileFormatter.
    var formatter = new MobileFormatter();
    using (var stream = new MemoryStream())
    {
        // This should cause a SerializationException.
        formatter.Serialize(stream, clone);
    }
}

 [Serializable]
public class SimpleBusinessObject : BusinessBase<SimpleBusinessObject>
{
    public static readonly PropertyInfo<int> IdProperty = RegisterProperty<int>(x => x.Id);
    public int Id { get { return GetProperty(IdProperty); } set { SetProperty(IdProperty, value); } }

   
private SimpleBusinessObject() { }

    public
static SimpleBusinessObject NewObject()
    {
        return DataPortal.Create<SimpleBusinessObject>();
    }
}

I believe the problem is that the BinaryFormatter can't serialize the private fields in MobileDictionary.  Since MobileDictionary inherits from Dictionary<K, V>, which implements the custom serialization interface ISerialize, doesn't MobileDictionary also need to override GetObjectState in order to add _keyIsMobile and _valueIsMobile to SerializationInfo?  Alternatively, what I found works is just calling DetermineTypes in the constructor overload that is used for binary serialization.

protected MobileDictionary(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
:
base(info, context)
{
    DetermineTypes();
}

It seems that if _valueIsMobile doesn't have the correct value, then the MobileFormetter can't serialize the dictionary without throwing an exception.

Assuming I've assessed the problem correctly, would it be possible to fix this in a future version?

Thanks!

RockfordLhotka replied on Wednesday, October 12, 2011

I see what you are talking about. I'll add this as a bug to be fixed.

Copyright (c) Marimer LLC