2012-12-19 7 views
5

Załóżmy, że mam model:Jak odpowiedzieć w ASP.NET Web API z modelu własności jako interfejs

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

IMenuCommand mogą mieć różne implementacje, jak:

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

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

I chcę POST menu z różnymi poleceniami do usługi ASP.NET Web API. Jak mogę to zrobić?

Żądanie poniżej utworzyć obiekt z określonym Name, ale komenda Next będzie null:

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

Domyślnie Web API spoiwa nie można odwzorować moją prośbę params do potrzebnej C# typu - oczywiście jest to trudna część. Czy mogę użyć atrybutu "znanego typu" dla właściwości opartych na interfejsie, czy istnieje inne podejście do obsługi tego przypadku, prawdopodobnie niestandardowy model spoiwa?

Odpowiedz

5

Myślę, że to, czego szukasz, to obsługa Json.NET w zakresie obsługi nazw typów. Pozwala określić typ do deserializacji poprzez dodanie znacznika json "$ type". Można spróbować ten kod, aby zobaczyć, jak to działa:

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

Musisz wymienić nazw i montaż wymienić z własną rękę, ale powinieneś zobaczyć NextStepCommand jest prawidłowo rozszeregować.

W WebAPI, musisz dostosować swoją prośbę dodać „$ typu” informacje o typie i trzeba włączyć TypeNameHandling takiego:

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

pracował dla mnie kiedy ustawić 'TypeNameHandling .Auto' for Web Serial JSON serializer i wysłał żądanie z potrzebnym "$ type" polecenia. Ale czy mogę włączyć funkcję 'TypeNameHandling' tylko do deserializacji? Ponieważ teraz mam zbyt dużo śmieci w wynikach JSON w usługach GET. – whyleee

+6

Ustalono, że możliwe jest użycie '[JsonProperty (TypeNameHandling = TypeNameHandling.All)]' dla określonych właściwości modelu (od [blog Json.NET] (http://james.newtonking.com/archive/2010/08/13/ json-net-3-5-release-8-3-5-final.aspx)). Sprawdzono za pomocą Web API - działa. Znacznie lepiej teraz. – whyleee

+0

@Youssef Moussaoui - Wszelkie pomysły na to pytanie: http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types ... Nie mając szczęścia z niczym! – amcdnl