2012-12-19 9 views
5

Angenommen POST habe ich ein Modell:Wie in ASP.NET Web API mit Modell Eigenschaft als Schnittstelle

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

IMenuCommand könnten unterschiedliche Implementierungen haben, wie:

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

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

Und ich möchte POST Menüs mit verschiedenen Befehlen für den ASP.NET-Web-API-Dienst. Wie kann ich das machen?

Die Anfrage unten wird ein Objekt mit dem angegebenen Name erstellen, aber Next Befehl null sein wird:

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

Standard-API Bindemittel können meine Anfrage params auf die benötigte C# Typ nicht Karte - natürlich ist es schwieriger Teil. Kann ich ein Attribut vom Typ "Bekannter Typ" für schnittstellenbasierte Eigenschaften verwenden oder gibt es einen anderen Ansatz, um diesen Fall zu bearbeiten, wahrscheinlich ein benutzerdefiniertes Modellbinder?

Antwort

5

Ich denke, was Sie suchen, ist die Unterstützung von Json.NET für die Handhabung von Typnamen. Sie können den zu deserialisierenden Typ durch Hinzufügen des JSON-Tags "$ type" angeben. Sie können diesen Code ausprobieren, um zu sehen, wie es funktioniert:

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

Sie werden den Namensraum ersetzen und Montage mit Ihrem eigenen Namen, aber man sollte die NextStepCommand sehen korrekt deserialisiert wird.

In WebAPI, müssen Sie Ihre Anfrage zwicken die „$ Typ“ Typinformationen hinzuzufügen, und Sie werden TypeNameHandling so aktivieren müssen:

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

für mich gearbeitet, wenn ich 'TypeNameHandling gesetzt .Auto 'für Web API JSON Serializer und schickte eine Anfrage mit benötigtem" $ type "eines Befehls. Kann ich die Funktion "TypeNameHandling" nur für die Deserialisierung aktivieren? Weil ich jetzt zu viel Müll in JSON-Ausgabe in GET-Diensten habe. – whyleee

+6

Gefunden, dass es möglich ist, '[JsonProperty (TypeNameHandling = TypeNameHandling.All)]' 'für bestimmte Modelleigenschaften zu verwenden (aus [Json.NET Blog] (http://james.newtonking.com/archive/2010/08/13/ json-net-3-5-release-8-3-5-final.aspx)). Mit Web-API überprüft - es funktioniert. Viel besser jetzt. – whyleee

+0

@Youssef Moussaoui - Irgendwelche Ideen zu dieser Frage: http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types ... Mit etwas nichts Glück haben! – amcdnl