Search code examples
c#xmlserializationabstract-classdatacontractserializer

wcf serialization inherited class error


we have two console application called "Frontend"(FE) and "Backend"(BE),

which are connected by WCF. I need to have a abstract class and some

inherited classes in BE, at runtime I have instantiate an object from one of

the inherited classes by Activator.

whenever I want to return the instantiated object there is error related to

serialization. this is my simplified code

[DataContract]
public abstract class License
{

    [DataMember]
    public int ManagedObjectCount { get; set; }
}

[DataContract]
public class LicenseMay2018 : License
{

    public Frontend.DataTypes.License GetLicenseInfo(xml xml)
    {
                    Frontend.DataTypes.LicenseMay2018 licenseVerified;
        var licXML = nodeData[0].InnerText;
        //Deserialize license
        XmlSerializer _serializer = new XmlSerializer(typeof(LicenseMay2018));
        using (StringReader _reader = new StringReader(licXML))
        {
            licenseVerified = (Frontend.DataTypes.LicenseMay2018)_serializer.Deserialize(_reader);
        }

    }

}

[DataContract]
public class LicenseApril2018 : License
{
}

on the BE side I return by type of the abstract class , expected to return the inherited class, every things works great by Activator and instantiating. The only problem is at the end of the method, when it wants to return to FE, seems to serialize and send back

public Frontend.DataTypes.License ActivateLicense(int LicenseFileId)
{
    // create in instance of inehrited class, no matter licensemay2018 or april2018 
    string assemblyName = "NMS.Common";
    var className = GetLicenseType(nodeVersion[0].InnerText);
    // exaple : className  = licensemay2018
    var handle = Activator.CreateInstance(assemblyName, className);
    var instance = (Frontend.DataTypes.License)handle.Unwrap();
    return instance.GetLicenseInfo(xmlDoc);
}

at run time I do not know about the exact type so I create the instance by type of the parent class, it works and the exact object is created

at the time of returning there will be this error

There was an error while trying to serialize parameter http://tempuri.org/:ActivateLicenseResult. The InnerException message was 'Type 'NMS.Frontend.DataTypes.LicenseMay2018' with data contract name 'LicenseMay2018:http://schemas.datacontract.org/2004/07/NMS.Frontend.DataTypes' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer 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 the serializer.'. Please see InnerException for more details.

I do not know where these comes from: http://tempuri.org and http://schemas.datacontract.org/2004/07 ??


Solution

  • You need to tell the serializer about your inherited types. Add a KnownType attributes for your inhertied classes like this

    [DataContract]
    [KnownType(typeOf(LicenseMay2018))]
    [KnownType(typeOf(LicenseApril2018))]
    public abstract class License
    {
    
        [DataMember]
        public int ManagedObjectCount { get; set; }
    }
    
    [DataContract]
    public class LicenseMay2018 : License
    {
    
        public Frontend.DataTypes.License GetLicenseInfo(xml xml)
        {
            return new licenseMay2018();
        }
    
    }
    
    [DataContract]
    public class LicenseApril2018 : License
    {
    }