我可以将基于接口的对象传递给MVC 4 WebApi POST吗?

我希望有这样的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(); } } 

我得到’包’的空值,所以我想知道可能出错的地方。 我唯一的想法是默认的JSON序列化程序无法处理这个,但我不清楚如何解决它。

您可以使用自定义模型绑定器轻松完成此操作。 这对我有用。 (使用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); 

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

查看TypeNameHandling选项发布子类集合

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

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

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

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

两种选择:

  1. 使用POCO(Plain Old Clr Object)和默认构造函数
  2. 使用IActionValueBinder实现您自己的活页夹