2016-05-17 108 views
3

這是一個棘手的問題。我有一個從JSON綁定模型的問題。我試圖解決多態的記錄提供了它將解決的記錄類型(我希望能夠在將來添加多種記錄類型)。我試圖在調用端點時使用following example來解析我的模型,但是此示例僅適用於MVC而不適用於Web API應用程序。複雜抽象對象的WebAPI自定義模型綁定

我試圖用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<ResourceRecord> Records { get; } 

    public RecordCollection() 
    { 
     Records = new List<ResourceRecord>(); 
    } 
} 

JSON結構

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

的[網頁API模型綁定和多態傳承]可能的複製(http://stackoverflow.com/questions/17277578/web-api-model-binding-and-polymorphic-inheritence ) – Kamo

+2

這是我在我的問題中使用的示例。爲這個問題提供的答案是MVC模型綁定,我需要Web API模型綁定。 – garyamorris

回答

10

經過一番研究,我發現,元數據提供不中的WebAPI存在,以綁定到你必須寫自己的複雜的抽象對象。

我開始寫一個新的模型綁定方法,使用自定義類型名稱JSon序列化程序,最後我更新了我的端點以使用自定義綁定器。值得注意的是,以下內容僅適用於正文中的請求,您必須在標題中爲請求寫入其他內容。我會建議閱讀Adam Freeman的Expert ASP.NET Web API 2 for MVC Developers的第16章和複雜的對象綁定。

我能夠使用下面的代碼從請求的主體序列化我的對象。

的WebAPI配置

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

自定義模型粘合劑

public class JsonBodyModelBinder<T> : 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<T>(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 recordCollection) 
    { 
    } 
+0

不是'BindModel'實現不可達代碼中的最後一個'return false;'語句嗎? – bump