2012-12-19 11 views
5

Supponiamo che io sono un modello:Come Share ASP.NET Web API con proprietà modello come interfaccia

public class Menu 
{ 
    public string Name { get; set; } 
    public IMenuCommand Next { get; set; } 
} 

IMenuCommand potrebbero avere diverse implementazioni, come:

public class NextStepCommand : IMenuCommand 
{ 
    public int Step { get; set; } 
} 

public class VoiceCommand : IMenuCommand 
{ 
    public string Message { get; set; } 
} 

E voglio postare menu con comandi diversi al servizio API Web ASP.NET. Come lo posso fare?

La richiesta di seguito creerà un oggetto con specificato Name, ma Next comando sarà nullo:

POST http://localhost/api/menus: {"name":"bob","next":{"step":1}} 
Returns 201: {"Name":"bob","Next":null} 

Web predefinito leganti API non può mappa La mia richiesta params al tipo necessario C# - ovviamente si tratta di un parte difficile. Posso utilizzare un attributo "tipo noto" per le proprietà basate su interfaccia o esiste un altro approccio per gestire questo caso, probabilmente un modello personalizzato?

risposta

5

Penso che quello che stai cercando sia il supporto di Json.NET per la gestione del nome. Permette di specificare il tipo di deserializzazione aggiungendo il tag json "$ type". Si può provare questo codice per vedere come funziona:

Console.WriteLine(JsonConvert.DeserializeObject<Menu>(
    @"{ 
     ""name"":""bob"", 
     ""next"": 
     { 
      ""$type"" : ""ConsoleApplication.NextStepCommand,ConsoleApplication"", 
      ""step"" : 1 
     } 
    }", 
    new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }).Next); 

Dovrete sostituire lo spazio dei nomi e il montaggio il nome con il proprio, ma si dovrebbe vedere il NextStepCommand essere correttamente deserializzato.

In WebAPI, è necessario modificare la vostra richiesta di aggiungere il "$ tipo" informazioni sul tipo, e avrete bisogno di abilitare TypeNameHandling in questo modo:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; 
+0

Ha lavorato per me quando ho impostato 'TypeNameHandling .Auto' for Web API JSON serializer e ha inviato una richiesta con il necessario "$ type" di un comando. Ma posso attivare la funzione 'TypeNameHandling' solo per la deserializzazione? Perché ora ho troppa spazzatura nell'output JSON nei servizi GET. – whyleee

+6

Trovato che è possibile usare '[JsonProperty (TypeNameHandling = TypeNameHandling.All)]' per specifiche proprietà del modello (da [blog Json.NET] (http://james.newtonking.com/archive/2010/08/13/ jSON-net-3-5-release-8-3-5-final.aspx)). Controllato con Web API - funziona. Molto meglio ora. – whyleee

+0

@Youssef Moussaoui - Qualche idea su questa domanda: http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types ... Non avere fortuna con niente! – amcdnl