根据请求内容类型,您必须决定要实例化哪个具体类。让我们举个例子application/json
。对于这种开箱即用的内容类型,Web API 使用 JSON.NET 框架将请求正文有效负载反序列化为具体对象。
因此,您必须连接到该框架才能实现所需的功能。这个框架中一个很好的扩展点是编写一个自定义的JsonConverter
。假设您有以下课程:
public abstract class ProductBase
{
public string ProductType { get; set; }
}
public class ConcreteProduct1 : ProductBase
{
public string Foo { get; set; }
}
public class ConcreteProduct2 : ProductBase
{
public string Bar { get; set; }
}
以及以下操作:
public HttpResponseMessage Post(ProductBase product)
{
return Request.CreateResponse(HttpStatusCode.OK, product);
}
让我们编写一个自定义转换器来处理这种类型:
public class PolymorphicProductConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ProductBase);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JObject.Load(reader);
ProductBase product;
var pt = obj["productType"];
if (pt == null)
{
throw new ArgumentException("Missing productType", "productType");
}
string productType = pt.Value<string>();
if (productType == "concrete1")
{
product = new ConcreteProduct1();
}
else if (productType == "concrete2")
{
product = new ConcreteProduct2();
}
else
{
throw new NotSupportedException("Unknown product type: " + productType);
}
serializer.Populate(obj.CreateReader(), product);
return product;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
最后一步是在WebApiConfig
:
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
new PolymorphicProductConverter()
);
差不多就是这样了。现在您可以发送以下请求:
POST /api/products HTTP/1.1
Content-Type: application/json
Host: localhost:8816
Content-Length: 39
{"productType":"concrete2","bar":"baz"}
服务器将正确反序列化该消息并响应:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
Date: Sat, 25 Jan 2014 12:39:21 GMT
Content-Length: 39
{"Bar":"baz","ProductType":"concrete2"}
如果您需要处理其他格式,例如application/xml
您可以执行相同的操作并插入相应的序列化器。