NoCarrier
NoCarrier

Reputation: 2588

WebAPI serializes classes that derive from abstract type properly when returning JSON, but not XML

my model:

    public abstract class BaseClass
    {
        public string id { get; set; }    
    }

    [KnownType(typeof(BaseClass))]
    public class ChildClass1 : BaseClass
    {
        public string shape { get; set; }
    }

    [KnownType(typeof(BaseClass))]
    public class ChildClass2: BaseClass
    {
        public string color { get; set; }
    }

    public class Widget
    {
        public List<BaseClass> Contents { get; set; }
        public Widget()
        {
            Contents = new List<BaseClass>();
        }    
    }

my web api endpoint:

        [HttpGet]
        public Widget Get()
        {
            Widget widget = new Widget();
            ChildClass1 cc1 = new ChildClass1();
            cc1.id = "1234";
            cc1.shape = "round";
            ChildClass2 cc2 = new ChildClass2();
            cc2.id = "4321";
            cc2.color = "red";
            widget.Contents.Add(cc1);
            widget.Contents.Add(cc2);
            return widget;
        }

When requesting output as XML, it's having problems serializing my derived classes.

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

Type 'WebApplication1.Models.ChildClass1' with data contract name 'ChildClass1:http://schemas.datacontract.org/2004/07/WebApplication1.Models' 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.

Upvotes: 2

Views: 700

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236228

You should add KnownType attributes to Widget class and specify all possible types which could be passed as BaseClass instances of Contents list:

[KnownType(typeof(ChildClass1))]
[KnownType(typeof(ChildClass2))]
public class Widget
{        
    public List<BaseClass> Contents { get; set; }
    public Widget()
    {
        Contents = new List<BaseClass>();
    }
}

Serialized response:

<Widget xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://schemas.datacontract.org/2004/07/YourNamespace">
    <Contents>
        <BaseClass i:type="ChildClass1">
            <id>1234</id>
            <shape>round</shape>
        </BaseClass>
        <BaseClass i:type="ChildClass2">
            <id>4321</id>
            <color>red</color>
        </BaseClass>
    </Contents>
</Widget>

Upvotes: 3

Related Questions