【问题标题】:How to POST in ASP.NET Web API with model property as interface如何使用模型属性作为接口在 ASP.NET Web API 中发布
【发布时间】:2012-12-19 01:17:56
【问题描述】:

假设我有一个模型:

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

【问题讨论】:

    标签: c# json asp.net-web-api model-binding


    【解决方案1】:

    我认为您正在寻找的是 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;
    

    【讨论】:

    • 当我为 Web API JSON 序列化程序设置 TypeNameHandling.Auto 并发送带有所需“$type”命令的请求时为我工作。但是我可以只为反序列化打开TypeNameHandling 功能吗?因为现在我在 GET 服务中的 JSON 输出中有太多垃圾。
    • 发现可以对特定模型属性使用[JsonProperty(TypeNameHandling = TypeNameHandling.All)](来自Json.NET blog)。使用 Web API 检查 - 它有效。现在好多了。
    • @Youssef Moussaoui - 关于这个问题的任何想法:stackoverflow.com/questions/20252027/… ... 没有任何运气!
    • @youssef - “您需要调整您的请求以添加“$type”类型信息”--> 请详细说明如何在 WEB API 中实现这一点?
    • 我为我的 Asp.Net 项目将 TypeNameHandling.Auto 添加到我的 WebApiConfig 中,但我认为它不起作用。但是,使用此设置使用 JsonConverter 进行了测试,它确实有效。我错过了什么?
    猜你喜欢
    • 2016-12-21
    • 2017-03-27
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 2012-12-14
    • 2020-02-03
    • 2017-12-09
    • 2015-12-04
    相关资源
    最近更新 更多