如何使用model属性作为接口在ASP.NET Web API中进行POST

why*_*eee 5 c# json model-binding asp.net-web-api

假设我有一个模型:

public class Menu
{
    public string Name { get; set; }
    public IMenuCommand Next { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

IMenuCommand 可以有不同的实现,如:

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

public class VoiceCommand : IMenuCommand
{
    public string Message { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想将具有不同命令的菜单POST到ASP.NET Web API服务.我怎样才能做到这一点?

下面的请求将创建一个指定的对象Name,但Next命令将为null:

POST http://localhost/api/menus: {"name":"bob","next":{"step":1}}
Returns 201: {"Name":"bob","Next":null}
Run Code Online (Sandbox Code Playgroud)

默认Web API绑定器无法将我的请求参数映射到所需的C#类型 - 当然这是一个棘手的部分.我可以为基于接口的属性使用一些"known-type"属性,还是有其他方法来处理这种情况,可能是自定义模型绑定器?

You*_*oui 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);
Run Code Online (Sandbox Code Playgroud)

您必须使用自己的命名空间替换命名空间和程序集名称,但您应该看到正确反序列化NextStepCommand.

在WebAPI中,您需要调整您的请求以添加"$ type"类型信息,并且您需要启用TypeNameHandling,如下所示:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
Run Code Online (Sandbox Code Playgroud)

  • 发现可以使用`[JsonProperty(TypeNameHandling = TypeNameHandling.All)]`来获取特定的模型属性(来自[Json.NET blog](http://james.newtonking.com/archive/2010/08/13/json) -net-3-5释放-8-3-5-final.aspx)).检查Web API - 它的工作原理.现在好多了. (6认同)