2012-12-19 42 views
5

假設我有一個模型:如何處理ASP.NET Web API與模型屬性出任接口

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

IMenuCommand可以有不同的實現方式,如:

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

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

我要發佈具有對ASP.NET Web API服務不同命令的菜單。我怎樣才能做到這一點?

下請求將創建一個對象與指定Name,但Next命令將是無效的:

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

默認Web API粘結劑可以不是我的請求參數映射到所需的C#類型 - 當然這是一個棘手的部分。我可以爲基於接口的屬性使用一些「已知類型」屬性,還是有任何其他方法來處理這種情況,可能是自定義模型綁定器?

回答

5

我想你要找的是Json.NET對類型名稱處理的支持。它允許您通過添加「$ type」json標籤來指定要反序列化的類型。你可以試試這個代碼出來,看看它是如何工作的:

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

你必須更換命名空間和裝配用自己的名字,但你應該看到NextStepCommand被正確地反序列化。

在的WebAPI,你需要調整你的請求添加「$型」類型的信息,你將需要啓用TypeNameHandling這樣的:

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

爲我工作,當我設置'TypeNameHandling .Auto'用於Web API JSON序列化程序,併發送帶有所需「$ type」命令的請求。但是我可以打開'TypeNameHandling'功能僅用於反序列化?因爲現在我在GET服務中的JSON輸出中有太多垃圾。 – whyleee

+6

發現可以使用'[JsonProperty(TypeNameHandling = TypeNameHandling.All)]'爲特定的模型屬性(來自[Json.NET博客](http://james.newtonking.com/archive/2010/08/13/) JSON淨3-5釋放-8-3-5-final.aspx))。使用Web API檢查 - 它可以工作。現在好多了。 – whyleee

+0

@Youssef Moussaoui - 對這個問題的任何想法:http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types ...沒有任何運氣與任何東西! – amcdnl