6

假设我有一个模型:

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# 类型——当然这是一个棘手的部分。我可以为基于接口的属性使用一些“已知类型”属性,还是有任何其他方法来处理这种情况,可能是自定义模型绑定器?

4

1 回答 1

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 中,您需要调整您的请求以添加“$type”类型信息,并且您需要像这样启用 TypeNameHandling:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
于 2012-12-19T03:23:34.640 回答