【问题标题】:Web API Abstract ParametersWeb API 抽象参数
【发布时间】:2012-12-10 19:27:27
【问题描述】:

拜托拜托有人可以帮我完成下面的代码。我按照http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.html 的示例进行了操作,此示例已发布在许多博客上。

我正在尝试找到一种可重用的方法来处理 Web API 操作中的抽象参数。它在 Fiddler 中完美运行,但是当我尝试通过 HttpClient 调用 Get 时返回的 EntityNote 为空。我发现 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 };
}

【问题讨论】:

  • 所以你的转换器的 ReadJson 方法永远不会在客户端被调用?
  • 我在它上面放了一个断点,它永远不会被调用。就像我说的,我不确定什么时候应该调用它,但它永远不会。

标签: asp.net-web-api abstract-class json.net


【解决方案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;

【讨论】:

  • 这很有意义,但是这个添加(如原始问题所示)并没有解决问题
【解决方案2】:

我切换到 XML 并使用 KnownType 属性。这是开箱即用的。我很想知道是否有使用 JSON 的解决方案,但这已经足够好了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-08
    • 2016-07-18
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多