Polymerization of WCF deserialization does not work

I created the following classes. one base class IObject and 2 derived classes A and B.

[KnownType(typeof(B))]
[KnownType(typeof(A))]
[DataContract(Name = "IObject")]
public class IObject
{
}

[DataContract(Name="A")]
public class A : IObject
{
    [DataMember]
    public string s1 { get; set; }     // Tag Name as it will be presented to the user

}

[DataContract(Name="B")]
public class B : IObject
{
    [DataMember]
    public string s2 { get; set; }         

}

I also created the following service:

    [ServiceKnownType(typeof(B))]
    [ServiceKnownType(typeof(A))]
    public void GetR(IObject obj)
    {

        B other = (B)obj;
    }

What I want to do is get an instance of A or B, but I don’t know which one I will get, so I expect to get an IObject and later list it either A or B, as shown in the example that I set.

What happens when I send a json string containing the s2 string, it is that I get an IObject instance, not an instance B. What is wrong with the code?

Example client that I use:

    var url = serviceURL;
    var data = {s2: "Data"};
    var json = JSON.stringify(data);

    $.ajax({
      type: "POST",
      url: url,
      data: data,
      contentType: "application/json",
      dataType: 'json'
    });

Edited: I downloaded the sample code on gitHub at the following link: https://github.com/AlgoEitan/27588144

The client is a C # client (I tried it with both C # and javascript - a web browser client)

+4
1

DataContractJsonSerializer , , . , :

public static class DataContractJsonSerializerPolymorphismTest
{
    public static void Test()
    {
        var a1 = new A() { s1 = "A" };
        var b1 = new B() { s2 = "B" };

        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IObject));

        var jsona1 = DataContractJsonSerializerHelper.GetJson(a1, serializer);
        var jsonb1 = DataContractJsonSerializerHelper.GetJson(b1, serializer);

        Debug.WriteLine(jsona1);
        Debug.WriteLine(jsonb1);

        var newa1 = DataContractJsonSerializerHelper.GetObject<IObject>(jsona1, serializer);

        Debug.Assert(newa1.GetType() == a1.GetType()); // No assert
    }
}

JSON:

{"__type":"A:#Tile.DataContractJsonSerializerPolymorphism","s1":"A"}
{"__type":"B:#Tile.DataContractJsonSerializerPolymorphism","s2":"B"}

Tile.DataContractJsonSerializerPolymorphism CLR . , , JSON __type. , DataContractJsonSerializerHelper , , . JSON.stringify(), . , "__type":"DataContractName:DataContractNamespace" .

. ( __type, Google.)

FYI, -, :

public static class DataContractJsonSerializerHelper
{
    private static MemoryStream GenerateStreamFromString(string value)
    {
        return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
    }

    public static string GetJson<T>(T obj, DataContractJsonSerializer serializer) where T : class
    {
        using (var memory = new MemoryStream())
        {
            serializer.WriteObject(memory, obj);
            memory.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(memory))
            {
                return reader.ReadToEnd();
            }
        }
    }

    public static string GetJson<T>(T obj) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetJson(obj, serializer);
    }

    public static T GetObject<T>(string json) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetObject<T>(json, serializer);
    }

    public static T GetObject<T>(string json, DataContractJsonSerializer serializer) where T : class
    {
        T obj = null;
        using (var stream = GenerateStreamFromString(json))
        {
            obj = (T)serializer.ReadObject(stream);
        }
        return obj;
    }
}
+2

Source: https://habr.com/ru/post/1568509/


All Articles