WebAPI自定义模型绑定复杂的抽象对象

这是困难的一个。 我有一个从JSON绑定模型的问题。 我试图解决多态一致的记录提供的记录,它将解析为(我希望以后能够添加许多记录类型)。 我试图在调用端点时使用以下示例来解析我的模型,但是此示例仅适用于MVC而不适用于Web API应用程序。

我试图使用IModelBinder和BindModel(HttpActionContext actionContext,ModelBindingContext bindingContext)编写它。 但是,我在System.Web.Http命名空间中找不到ModelMetadataProviders的等价物。

感谢任何人都能给予的帮助。

我有一个Web API 2应用程序,它具有以下对象结构。

public abstract class ResourceRecord { public abstract string Type { get; } } public class ARecord : ResourceRecord { public override string Type { get { return "A"; } } public string AVal { get; set; } } public class BRecord : ResourceRecord { public override string Type { get { return "B"; } } public string BVal { get; set; } } public class RecordCollection { public string Id { get; set; } public string Name { get; set; } public List Records { get; } public RecordCollection() { Records = new List(); } } 

JSON结构

 { "Id": "1", "Name": "myName", "Records": [ { "Type": "A", "AValue": "AVal" }, { "Type": "B", "BValue": "BVal" } ] } 

经过一些研究后,我发现WebAPI中不存在元数据提供程序,为了绑定复杂的抽象对象,您必须自己编写。

我开始编写一个新的模型绑定方法,使用自定义类型名称JSon序列化程序,最后我更新了我的端点以使用自定义绑定器。 值得注意的是,以下内容仅适用于正文中的请求,您必须为标题中的请求编写其他内容。 我建议阅读Adam Freeman的专家ASP.NET Web API 2第16章, 了解MVC开发人员和复杂的对象绑定。

我能够使用以下代码从请求正文中序列化我的对象。

WebAPI配置

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Services.Insert(typeof(ModelBinderProvider), 0, new SimpleModelBinderProvider(typeof(RecordCollection), new JsonBodyModelBinder())); } } 

定制模型活页夹

 public class JsonBodyModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof(T)) { return false; } try { var json = ExtractRequestJson(actionContext); bindingContext.Model = DeserializeObjectFromJson(json); return true; } catch (JsonException exception) { bindingContext.ModelState.AddModelError("JsonDeserializationException", exception); return false; } return false; } private static T DeserializeObjectFromJson(string json) { var binder = new TypeNameSerializationBinder(""); var obj = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Binder = binder }); return obj; } private static string ExtractRequestJson(HttpActionContext actionContext) { var content = actionContext.Request.Content; string json = content.ReadAsStringAsync().Result; return json; } } 

自定义序列化绑定

 public class TypeNameSerializationBinder : SerializationBinder { public string TypeFormat { get; private set; } public TypeNameSerializationBinder(string typeFormat) { TypeFormat = typeFormat; } public override void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = null; typeName = serializedType.Name; } public override Type BindToType(string assemblyName, string typeName) { string resolvedTypeName = string.Format(TypeFormat, typeName); return Type.GetType(resolvedTypeName, true); } } 

终点定义

  [HttpPost] public void Post([ModelBinder(BinderType = typeof(JsonBodyModelBinder))]RecordCollection recordCollection) { }