I have a ASP.NET MVC Web API controller that returns public IEnumerable<IMessage> Get()
It throws exception that I need to register types that derive from IMessage
in known types collection passed to DataContractSerializer
.
How to register "Known Types" for using with DataContractSerializer
and DataContractJSONSerializer
in MVC Web API project?
KnownType attribute cannot be placed on interface.
You need to put the KnownTypeAttribute
on your IMessage
implementations:
public interface IMessage
{
string Content { get; }
}
[KnownType(typeof(Message))]
public class Message : IMessage {
public string Content{ get; set; }
}
[KnownType(typeof(Message2))]
public class Message2 : IMessage
{
public string Content { get; set; }
}
So when calling the following action:
public IEnumerable<IMessage> Get()
{
return new IMessage[] { new Message { Content = "value1" },
new Message2 { Content = "value2" } };
}
The result will be this:
<ArrayOfanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<anyType xmlns:d2p1="http://schemas.datacontract.org/2004/07/MvcApplication3.Controllers" i:type="d2p1:Message">
<d2p1:Content>value1</d2p1:Content>
</anyType>
<anyType xmlns:d2p1="http://schemas.datacontract.org/2004/07/MvcApplication3.Controllers" i:type="d2p1:Message2">
<d2p1:Content>value2</d2p1:Content>
</anyType>
</ArrayOfanyType>
But this will only work one "way". So you cannot post back the same XML.
In order to the following action should work:
public string Post(IEnumerable<IMessage> messages)
You need to register the known types globally, with configuring a DataContractSerializer
and setting up in the GlobalConfiguration.Configuration.Formatters
GlobalConfiguration.Configuration
.Formatters
.XmlFormatter.SetSerializer<IEnumerable<IMessage>>(
new DataContractSerializer(typeof(IEnumerable<IMessage>),
new[] { typeof(Message), typeof(Message2) }));
With using the configuration you don't need the KnownTypeAttribute
on your implementation types.