【问题标题】:JsonPatchDocument is null after migration to .Net Core 3迁移到 .Net Core 3 后,JsonPatchDocument 为空
【发布时间】:2019-10-24 13:11:48
【问题描述】:

我有一个带有多个补丁操作的 AspNetCore-WebApi-Project,它在 Core 2.2 上运行良好。迁移到 Core 3 后,[FromBody] JsonPatchDocument<T> 为空。我的 Get/Post-Methods 仍然按预期运行。

这是我创业的一部分:

    services.AddDbContext<MyContext>(options => options
                    .UseLazyLoadingProxies()
                    .UseNpgsql(Configuration.GetConnectionString("MyConnectionString"), 
                        opt => opt.UseNodaTime()));

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My-API", Version = "v1" });
    });
    services.AddControllers()
        .AddNewtonsoftJson();

这是我的行动:

[HttpPatch("{id}")]
public async Task<IActionResult> Patch(Guid id, 
                            [FromBody] JsonPatchDocument<MyViewModel> patchDocument)
{
    await this.service.HandlePatchAsync(id, patchDocument);
    return NoContent();
}

这是正文内容:

[   
    {
        "op": "replace",
        "path": "/name",
        "value": "New Name" 
    },
    {
        "op": "replace",
        "path": "/country",
        "value": "Germany" 
    }
]

有人知道这里出了什么问题吗?

【问题讨论】:

  • 您是否按照official documentation 将 2.2 迁移到 3.0?我对其进行了测试,效果很好。你能分享一个可以重现问题的演示吗?
  • 我没有得到正确的包裹。我不清楚,除了调用 AddNewtonsoftJson() 之外,我已经安装了一个新包。在启动中。不过还是谢谢你看这个!

标签: asp.net-core .net-core json.net .net-core-3.0 json-patch


【解决方案1】:

我也遇到过类似的问题。我打算完全摆脱Newtonsoft,但在这种情况下,带有JsonPatchDocument 的补丁不起作用。

根据https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#jsonnet-support,你应该:

  1. 添加对Microsoft.AspNetCore.Mvc.NewtonsoftJson的包引用

  2. 在启动时更改代码添加MVC到services.AddMvc().AddNewtonsoftJson();

你做了第二步,但第一步呢? 这对我有帮助。

不幸的是,如果没有.AddNewtonsoftJson(),我不知道如何使 JsonPatchDocument 工作

【讨论】:

  • 非常感谢!安装包解决了我的问题
  • 不可能摆脱 newtonsoft,因为 JsonPatchDocument 内部依赖于 newtonsoft。也许他们在未来的版本中也会替换这个包。
  • 谢谢,这解决了我在将模型设置为 null 的后期操作中使用 [FromBody] 的问题。安装软件包后,它可以完美运行。
【解决方案2】:

从 .NET 5 开始,JsonPatchDocument 似乎依赖于 NewtonsoftJson 的 JsonSerializers。也就是说,在JsonPatchDocument的源码中,有

[JsonConverter(typeof(JsonPatchDocumentConverter))]
public class JsonPatchDocument : IJsonPatchDocument
{

JsonConverter 属性来自 Newtonsoft Json 命名空间。

我想我可以定义一个 JsonConverter 以便它在 System.Text.Json 中工作。 像这样的

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json.Serialization;

namespace MyProject
{
    public class JsonPatchDocumentConverter : JsonConverter<JsonPatchDocument>
    {
        public override JsonPatchDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var result = JsonSerializer.Deserialize<List<Operation>>(ref reader, options);
            return new JsonPatchDocument(result, new DefaultContractResolver());
        }

        public override void Write(Utf8JsonWriter writer, JsonPatchDocument value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }
    }
}

然后在 Startup.cs 中,

        services.AddControllersWithViews().AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.Converters.Add(new JsonPatchDocumentConverter());
        });

... 或者,继承 JsonPatchDocument 并在那里定义属性

namespace MyProject        
{
    [System.Text.Json.Serialization.JsonConverter(typeof(JsonPatchDocumentConverter))]
    public class JsonPatchDocument : Microsoft.AspNetCore.JsonPatch.JsonPatchDocument
    {

    }
}

然后使用 JsonPatchDocument 子类,以便 System.Text.Json 拾取属性中的 JsonConverter

public async Task<IActionResult> Patch(Guid id, 
                            [FromBody] MyProject.JsonPatchDocument patchDocument)
{

【讨论】:

    猜你喜欢
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    相关资源
    最近更新 更多