18

我想要一个这样的API:

public class RelayController : ApiController
{
    // POST api/values
    public void Post([FromBody]IDataRelayPackage package)
    {
        MessageQueue queue = new MessageQueue(".\\private$\\DataRelay");
        queue.Send(package);
        queue.Close();
    }
}

我得到了 'package' 的空值,所以我想知道可能出了什么问题。我唯一的想法是默认JSON序列化程序无法处理此问题,但我不清楚如何修复它。

4

4 回答 4

18

您可以使用自定义模型绑定器轻松完成此操作。这对我有用。(使用 Web API 2 和 JSON.Net 6)

public class JsonPolyModelBinder : IModelBinder
{
    readonly JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var content = actionContext.Request.Content;
        string json = content.ReadAsStringAsync().Result;
        var obj = JsonConvert.DeserializeObject(json, bindingContext.ModelType, settings);
        bindingContext.Model = obj;
        return true;
    }
}

Web API 控制器如下所示。(注意:也应该适用于常规的 MVC 操作——我之前也为它们做过类似的事情。)

public class TestController : ApiController
{
    // POST api/test
    public void Post([ModelBinder(typeof(JsonPolyModelBinder))]ICommand command)
    {
        ...
    }
}

我还应该注意,当您序列化 JSON 时,您应该使用相同的设置对其进行序列化,并将其序列化为接口以使 Auto 启动并包含类型提示。像这样的东西。

    JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
    string json = JsonConvert.SerializeObject(command, typeof(ICommand), settings);
于 2014-03-09T06:36:56.817 回答
5

您正在尝试反序列化到接口。除非被告知,否则序列化程序不会知道要实例化什么类型。

看一下 TypeNameHandling 选项Posting a collection of subclasses

或者看看创建一个自定义的 JsonConverter。看看这个问题如何在 JSON.NET 中实现自定义 JsonConverter 以反序列化基类对象的列表?

于 2013-01-02T15:08:52.773 回答
3

Json.NET(ASP.NET Web API 的默认 Json 序列化程序)可以处理这种情况。您需要做的就是更改序列化程序设置,并将 TypeNameHandling 设置为 All(或 Objects)。这将为您的 json 添加一个“$type”-json 属性,其中包含您的实例的类型名称。另一方面,它会尝试再次反序列化为这种类型。

我们自己使用它,将抽象基类作为类型。

于 2013-01-02T15:31:11.013 回答
0

序列化程序需要一种可以构造的类型,一种具有空(默认)构造函数的类型。由于无法构造接口,因此序列化失败并且您得到一个空值。

两种选择:

  1. 使用带有默认构造函数的 POCO(普通旧 Clr 对象)
  2. 使用 IActionValueBinder 实现您自己的活页夹
于 2013-01-02T15:09:16.870 回答