简体   繁体   English

ASP.NET Core Web API自动JSON参数反序列化不起作用

[英]ASP.NET Core Web API Automatic JSON Parameter Deserialization Not Working

I've a simple controller that takes one parameter from the POST request body. 我有一个简单的控制器,它从POST请求主体中获取一个参数。 Normally it should automatically deserialize it from JSON to the object type but it fails. 通常,它应该自动将其从JSON反序列化为对象类型,但失败。 When I try to deserialize it myself it works withot problems. 当我自己尝试反序列化时,它会遇到很多问题。 Here is some code: 这是一些代码:

The controller (the documentCommand variable is null): 控制器(documentCommand变量为null):

public async Task<IActionResult> Create([FromBody]CreateDocumentCommand documentCommand)
{
    if (documentCommand == null)
    {
        return StatusCode(403); //Deserialization fails, documentCommand is null
    }
    //we have to reach this :(
    return Json(documentCommand.Document.Id);
}

Here is how I serialize it and how I test if it will be able to deserialize it: 这是我如何序列化它以及如何测试它是否可以反序列化它:

JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
{ 
    TypeNameHandling = TypeNameHandling.Auto,
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore
};
string serialized = JsonConvert.SerializeObject(item, jsonSerializerSettings);
CreateDocumentCommand deserialized = JsonConvert.DeserializeObject<CreateDocumentCommand>(serialized, jsonSerializerSettings);

In my CreateDocumentCommand class I have an interface property and when I remove the TypeNameHandling = TypeNameHandling.Auto it fails in the second example too. 在我的CreateDocumentCommand类中,我有一个接口属性,当我删除TypeNameHandling = TypeNameHandling.Auto时,它在第二个示例中也会失败。

Is there a way yo tell the MVC deserializer to take the TypeNameHandling into account? 有没有办法告诉MVC解串器考虑TypeNameHandling It seems to me that it skips it. 在我看来,它跳过了它。

EDIT Some more code: 编辑更多代码:

public class CreateDocumentCommand : Command, ICreateDocumentCommand
{
    public CreateDocumentCommand()
    {

    }

    public IDocument Document { get; set; }
}

MY SOLUTION: Added that ConcreteTypeConverter which I found at the link provided by Babak Naffas and made some changes because I was getting some circular reference exeptions. 我的解决方案:添加了我在Babak Naffas提供的链接中找到的ConcreteTypeConverter,并进行了一些更改,因为我得到了一些循环参考实例。 Also Added the [JsonConverter(typeof(ConcreteTypeConverter))] beefore the CreateDocumentCommand class. 还添加了[JsonConverter(typeof(ConcreteTypeConverter))]增强CreateDocumentCommand类。

public class ConcreteTypeConverter<T> : JsonConverter
{
    static bool read = false;

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        serializer.TypeNameHandling = TypeNameHandling.Auto;
        serializer.NullValueHandling = NullValueHandling.Ignore;
        serializer.MissingMemberHandling = MissingMemberHandling.Ignore;
        return serializer.Deserialize<T>(reader);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override bool CanWrite
    {
        get
        {
            return false;
        }
    }

    public override bool CanRead
    {
        get
        {
            read = !read;
            return read;
        }
    }
}

Your issue is the IDocument interface, which can't be deserialized out of the box as the deserializer can't know which concrete class to use. 您的问题是IDocument接口,由于解串器无法知道要使用哪个具体类,因此无法直接对它进行反序列化。

Also, make sure to create a unit test that takes the raw JSON that you'd be passing to your controller method and make sure it can be deserialized. 另外,请确保创建一个单元测试,该单元测试将要传递给控制器​​方法的原始JSON并确保可以反序列化。

If you want global setting then you can specify JsonSerializerSetting at application level using AddJsonOptions extension. 如果需要全局设置,则可以使用AddJsonOptions扩展名在应用程序级别指定JsonSerializerSetting Read it about here . 在这里阅读。

services.AddMvc()
.AddJsonOptions(opt =>
{
    if (opt.SerializerSettings != null)
    {
            opt.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto,
            opt.SerializerSettings.NullValueHandling = NullValueHandling.Ignore,
            opt.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore
    }
});

AddJsonOptions is defined in Microsoft.AspNetCore.Mvc.Formatters.Json nuget package. AddJsonOptions在Microsoft.AspNetCore.Mvc.Formatters.Json nuget包中定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM