以下のコードの実装を完了するのを手伝ってください。http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.htmlの例に従いました。この例は、多くのブログに掲載されています。
Web API アクションで抽象パラメーターを処理するための再利用可能な方法を見つけようとしています。Fiddler では完全に動作しますが、HttpClient 経由で Get を呼び出そうとすると、返される EntityNote が null になります。ReadJson メソッドが呼び出されることはないので、Create も呼び出されることはありません。ReadJson が呼び出される場所を理解するのに十分な Web API の流れを理解していないと思います。
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 };
}