2013-01-25 16 views
6

Ho un controller Web API ASP.NET MVC che restituisce public IEnumerable<IMessage> Get()Come registrarsi Tipi conosciuti per la serializzazione quando si utilizza ASP.NET MVC Web API

Getta eccezione che ho bisogno di registrare i tipi che derivano da IMessage nel noto collezione di tipi passati a DataContractSerializer.

Come registrare "Tipi noti" per l'utilizzo con DataContractSerializer e DataContractJSONSerializer nel progetto MVC Web API?

L'attributo KnownType non può essere inserito nell'interfaccia.

risposta

7

Hai bisogno di mettere il KnownTypeAttribute sul tuo IMessage implementazioni:

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; } 
} 

Così quando si chiama la seguente azione:

public IEnumerable<IMessage> Get() 
{ 
    return new IMessage[] { new Message { Content = "value1" }, 
          new Message2 { Content = "value2" } }; 
} 

il risultato sarà questo:

<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> 

Ma questo funzionerà solo in un "modo". Quindi non puoi postare lo stesso XML.

Per all'azione seguente dovrebbe funzionare:

public string Post(IEnumerable<IMessage> messages) 

È necessario registrare i tipi noti globalmente, con la configurazione di un DataContractSerializer e la creazione in GlobalConfiguration.Configuration.Formatters

GlobalConfiguration.Configuration 
        .Formatters 
        .XmlFormatter.SetSerializer<IEnumerable<IMessage>>(
         new DataContractSerializer(typeof(IEnumerable<IMessage>), 
          new[] { typeof(Message), typeof(Message2) })); 

Con utilizzando la configurazione non è necessario il KnownTypeAttribute sui tipi di implementazione.

+0

Eh? mettere [KnownType (Type)] su un Type stesso mi sembra strano, ma ci provo. –

+0

Strano, ma funziona davvero, ma solo da un lato. Ho un post pubblico ([FromBody] IEnumerable messaggi) metodo a cui poi passerò il flusso, e i messaggi sempre nulli, sto usando Fiddler per questo forse la mia richiesta post non è corretta, o serializzatore non può leggere cosa ha scritto. –

+0

Sì, non funziona quando si registra lo stesso xml. Immagino a causa di 'ArrayOfanyType' e' anyType'. Attualmente sto armeggiando con esso. Tornerò da te se trovo qualcosa. – nemesv

Problemi correlati