3

I have a AspNetCore-WebApi-Project with several patch-operations, which worked fine with Core 2.2. After migration to Core 3 the [FromBody] JsonPatchDocument<T> is null. My Get/Post-Methods are still functioning as expected.

This is one part of my Startup:

    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();

This is my Action:

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

This is the body-content:

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

Does anyone have an idea what is goung wrong here?

4

2 回答 2

9

我在一个类似的问题上挣扎。我打算完全摆脱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();

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

不幸的是,我不知道如何让 JsonPatchDocument 工作.AddNewtonsoftJson()

于 2019-10-25T10:52:59.447 回答
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)
{
于 2021-10-03T06:44:11.813 回答