ServiceKnownType client side issue

252 Views Asked by At

Server side:

Service details:

[ServiceKnownType("GetKnownTypes", typeof(Helper))]
[ServiceContract]
public interface IAppConfigurationManager
{
    [OperationContract]
    object ChangeObjectProperty(object myCustomObject);
}

Implementation:

public class AppConfigurationManager : IAppConfigurationManager
{
    public object ChangeObjectProperty(object myCustomObject)
    {
        foreach (Type type in Globals.MyCustomTypes)
        {
            if (type == myCustomObject.GetType())
            {
                foreach (PropertyInfo Property in myCustomObject.GetType().GetProperties())
                {
                    if(Property.Name == "ID")
                    {
                        int oldValue = Convert.ToInt32(Property.GetValue(myCustomObject));
                        Property.SetValue(myCustomObject, oldValue + 1);
                        break;
                    };
                };                    
            }
        }

        return myCustomObject;
    }
}

Helper class is used for collecting of KnownTypes:

public static class Helper
{
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
    {
        Globals.MyCustomTypes = new List<Type>();

        System.Collections.Generic.List<System.Type> knownTypes =
            new System.Collections.Generic.List<System.Type>();

        Assembly assembly = Assembly.LoadFrom(@"D:\WCF\RuntimeManagement\bin\Debug\RuntimeManagement.dll");

        foreach (Type type in assembly.GetTypes())
        {
            if (type.Name.Contains("Customer") || type.Name.Contains("Account"))
            {
                knownTypes.Add(type);
                Globals.MyCustomTypes.Add(type);
            };
        };

        return knownTypes;
    }
}

Classes:

[DataContract]
public class Customer 
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string Name { get; set; }
}

[DataContract]
public class Account
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public Customer AccountOwner { get; set; }
}

Client side:

Before invoking the service, trying to register KnownTypes at client side also:

private void fmMain_Load(object sender, EventArgs e)
{
    MyCustomTypes = new List<Type>();

    Assembly assembly = Assembly.LoadFrom(@"D:\WCF\RuntimeManagement\bin\Debug\RuntimeManagement.dll");

    foreach (Type type in assembly.GetTypes())
    {
        if (type.Name.Contains("Customer") || type.Name.Contains("Account"))
        {
            MyCustomTypes.Add(type);

            if (type.Name == "Customer")
            {
                CustomerType = type;
            };

            foreach (var operation in Globals.AppConfigMgrClient.Endpoint.Contract.Operations)
            {
                operation.KnownTypes.Add(type);
            };
        };
    };

    object myCustomerObject = Activator.CreateInstance(CustomerType);

    foreach (PropertyInfo Property in myCustomerObject.GetType().GetProperties())
    {
        if (Property.Name == "ID")
        {
            Property.SetValue(myCustomerObject, 111);
            break;
        };
    };

    myCustomerObject = Globals.AppConfigMgrClient.ChangeObjectProperty(myCustomerObject);

    foreach (PropertyInfo Property in myCustomerObject.GetType().GetProperties())
    {
        if (Property.Name == "ID")
        {
            Debug.WriteLine(Property.GetValue(myCustomerObject).ToString());
            break;
        };
    };
}

Got error here:

myCustomerObject = Globals.AppConfigMgrClient.ChangeObjectProperty((RuntimeManagement.CatalogManagement.Customer)myCustomerObject);

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:myCustomObject. The InnerException message was 'Element 'http://tempuri.org/:myCustomObject' contains data from a type that maps to the name 'http://tempuri.org/:Customer'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'Customer' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

May be long post, hope you got idea what I am trying to do here:

  1. Adding Customer and Account classes to ServiceKnownType at server side helper class.
  2. On load event of client side, trying to register KnownTypes from the same assembly where Customer and Account exists.
  3. Then creating instance of Customer type, set it's ID property to 111, send it OperationContract called ChangeObjectProperty. After successful execution, it should increment ID.

Thanks for your time.

0

There are 0 best solutions below