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?

2
  • Did you migrate 2.2 to 3.0 as per the official documentation ? I tested it and it worked well . Could you share a demo that can reproduce the issue ? Commented Oct 25, 2019 at 9:14
  • I didn´t get the right package. It was not clear to me, that I had install a new package, beside the call of AddNewtonsoftJson(). in startup. But thank you anyway for looking at this! Commented Oct 25, 2019 at 11:27

2 Answers 2

9

I struggle with a similar issue. I was going to get rid of Newtonsoft at all, but in that case the patch with JsonPatchDocument was not working.

According to https://learn.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#jsonnet-support you should:

  1. Add a package reference to Microsoft.AspNetCore.Mvc.NewtonsoftJson

  2. Change code in the startup adding MVC to services.AddMvc().AddNewtonsoftJson();

You did the second step, but what about the first? This helped me.

Unfortunatelly, I do not know how to make JsonPatchDocument work without .AddNewtonsoftJson()

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much! Installing the package solved my issue
There won´t be a possibility to get rid of newtonsoft, because JsonPatchDocument relies on newtonsoft internally. Maybe they replace this package as well in future releases.
Thank you this solved my problem with [FromBody] in a post action setting the model to null.After installing the package it works perfectly.
3

As of .NET 5, it seems that JsonPatchDocument depends on the JsonSerializers from NewtonsoftJson. That is to say, in the source code for JsonPatchDocument, there is

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

where the JsonConverter attribute is from the Newtonsoft Json Namespace.

I think I am able to define a JsonConverter so that it works in System.Text.Json. Something like this

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

And then in Startup.cs,

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

... OR alternatively, inherit JsonPatchDocument and define the attribute there

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

    }
}

and then use the JsonPatchDocument subclass so that the JsonConverter from the attribute is picked up by System.Text.Json

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.