2012-12-19 43 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