2012-12-10 31 views
0

請有人能幫我完成下面的代碼。我遵循http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.html的例子,這個例子遍佈在很多博客上。Web API抽象參數

我試圖找到一個有點可重用的方式來處理Web API操作中的抽象參數。它在Fiddler中完美工作,但當我嘗試通過HttpClient調用Get時,返回的EntityNote爲null。我發現ReadJson方法永遠不會被調用,所以Create也永遠不會被調用。我想我不明白Web API的流程足以瞭解ReadJson應該被調用的位置。

的Global.asax.cs

config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly; 
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All; 
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter()); 

從鏈路的轉換器(沒人演示如何實現WriteJson)

public abstract class JsonCreationConverter<T> : JsonConverter 
{ 
    protected abstract T Create(Type objectType, JObject jsonObject); 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsSubclassOf(typeof(T)); 
    } 

    //This method never gets called 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var jsonObject = JObject.Load(reader); 
     var target = Create(objectType, jsonObject); 
     serializer.Populate(jsonObject.CreateReader(), target); 
     return target; 
    } 

    //I just kinda guessed at this code 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     if (this.CanConvert(value.GetType())) 
     { 
      serializer.Serialize(writer, value); 
     } 
    } 
} 

EntityNote是一個抽象類PortalProviderRefundNote作爲實現。

public class JsonDeviceConverter : JsonCreationConverter<EntityNote> 
{ 
    //This method never gets called, because ReadJson is never called 
    protected override EntityNote Create(Type objectType, JObject jsonObject) 
    { 
     var typeName = jsonObject["EntityNote"].ToString(); 
     switch (typeName) 
     { 
      case "PortalProviderRefundNote": 
       return new PortalProviderRefundNote() { EntityId = 1 }; 
      default: return null; 
     } 
    } 
} 

的HttpClient - 教程使用JsonConvert.DeserializeObject,但我無法弄清楚如何在這裏適合... ReadAsAsync執行此任務

//simplified **Suggested Edit** 
this.jsonFormatter = new JsonMediaTypeFormatter(); 
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All; 
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
jsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter()); 

new HttpClient().GetAsync("http://localhost/api/EntityNotesController/").Result.Content.ReadAsAsync<EntityType>(new List<MediaTypeFormatter>(){ jsonFormatter }).Result; 

服務控制器

public EntityNote Get(int id) 
{ 
    return new PortalProviderRefundNote() { EntityId = 1 }; 
} 
+0

所以你的轉換器的ReadJson方法永遠不會被客戶端調用? –

+0

我把一個斷點,它永遠不會被調用。就像我說的,我不確定它應該什麼時候被調用,但它永遠不會。 – quitstalin

回答

0

我切換到XML並使用了KnownType屬性。這可以直接使用。我很想知道是否有JSON解決方案,但是這樣做的效果不錯。

1

您需要在客戶端對JsonMediaTypeFormatter進行相同的串行器設置更改:

var jsonFormatter = new JsonMediaTypeFormatter(); 
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All; 
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
jsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter()); 

response.Content.ReadAsAsync<EntityNote>(new MediaTypeFormatter() { jsonFormatter }).Result; 
+0

這是非常有意義的,但是這個增加(如原始問題所示)並未解決問題 – quitstalin