Web Api模型绑定和多态继承

时间:2013-06-24 14:10:13

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

我在问是否有人知道是否有可能将一个从抽象类继承的具体类传递给Web Api。

例如:

public abstract class A{
    A();
}

public class B : A{

}

[POST("api/Request/{a}")]
public class Request(A a)
{
}

目前我已经环顾四周,大多数解决方案似乎都说使用TypeNameHandling会起作用。

JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
            jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

然而事实并非如此。我的模型也从控制台应用程序传递到webapi。我已经读过,我可能能够反序列化json对象,在尝试了几次之后,我认为这不会起作用。

我已经考虑过创建一个客户模型绑定器,但是,我不想让我的应用程序变得更加复杂。目前我继承了3个模型的抽象类,但将来可能会扩展它。您可能会注意到添加自定义模型绑定器可能需要多个绑定器,除非有一种方法可以为所有类型的抽象类创建一个通用绑定器。

要在我的控制台应用程序中对此进行扩展,我已经实例化了类b,然后将其传递给ObjectContent,然后发布到我的webapi

item = B();

//serialize and post to web api
MediaTypeFormatter formatter;
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
formatter = jsonFormatter;

_content = new ObjectContent<A>(item, formatter);
var response = _client.PostAsync("api/Request", _content).Result;

当调用webapi操作时,对象为空

4 个答案:

答案 0 :(得分:1)

这可以通过默认的模型绑定来实现。检查以下方法。

public abstract class RequestBase
{
    public int ID { get; set; }
}

public class MyRequest : RequestBase
{
    public string Name { get; set; }
}



[RoutePrefix("api/home")]
public class HomeController : ApiController
{
    [HttpPost]
    [Route("GetName")]
    public IHttpActionResult GetName([FromBody]MyRequest _request)
    {
        return Ok("Test");
    }
}

enter image description here

答案 1 :(得分:0)

正如LiamK指出的那样,他的解决方案不适用于WebAPI。 WebAPI使用IModelBinder接口进行绑定,而ModelMetadataProviders将不存在这些模型。

我在这里提供了解决这个问题的方法;

WebAPI Custom Model binding of complex abstract object

答案 2 :(得分:0)

如果您真的想实现问题中的要求,则可以使用一种自定义的方式来实现。

首先,创建一个自JsonConverter继承的自定义json转换器,在其中选择目标类并反序列化实例。

然后,在您的WebApiConfig.Register中,将新的转换器添加到config.Formatters.JsonFormatter.SerializerSettings.Converters中,并享受这种怪异的作用。

您应该这样做吗?否

了解如何使用此类API不会给任何新用户带来欢乐,对其进行记录并不容易,而且最重要的是-以这种方式实现它没有任何好处。如果输入类型不同,则应使用具有不同URL的单独API方法。如果只有几个不同的属性,则将它们设为可选。

为什么该示例不起作用? TypeNameHandling来自Json.NET,Web API对此一无所知,并且类型信息也不是JSON规范的一部分,因此没有解决此特定问题的标准方法。

答案 3 :(得分:0)

请将 [POST("api/Request/{a}")] 更改为 [POST("api/Request")]。 您的参数来自正文,而不是路线。