我可以传递一个基于接口的对象到MVC 4 WebApi POST

本文关键字:对象 POST WebApi 接口 MVC 于接口 一个 我可以 | 更新日期: 2023-09-27 17:50:20

我想有一个这样的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序列化器不能处理这个问题,但我不清楚如何修复它。

我可以传递一个基于接口的对象到MVC 4 WebApi POST

使用自定义模型绑定器可以很容易地做到这一点。以下是对我有效的方法。(使用Web API 2和JSON。网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选项post一个子类集合

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

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

序列化器需要一个它可以构造的类型,一个具有空(默认)构造函数的类型。由于不能构造接口,因此序列化失败,您将得到一个空值。

两个选择:

    使用POCO (Plain Old Clr Object)和默认构造函数
  1. 使用IActionValueBinder实现你自己的绑定器