Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement HttpPatch action method in ASP.NET Core 6 Web API without using NewtonSoft

Yesterday I upgraded my ASP.NET Core 5 Web API to .Net 6. Today I thought I'd also migrate from Newtonsoft.Json to System.Text.Json.

The first thing I did was to remove the Microsoft.AspNetCore.Mvc.NewtonsoftJson package from my project. I also removed the .AddNewtonsoftJson() statement from the services.AddControllers() part of Startup.cs.

I then renamed all using Newtonsoft.Json; to using System.Text.Json;, all [JsonProperty] decorators to [JsonPropertyName], etc, etc.

I'm almost error-free now, but I've hit a stumbling block with my HttpPatch action methods. The "ModelState" class seems to be a member of Microsoft.AspNetCore.Mvc.NewtonsoftJson, which I removed. I could re-add it, as well as re-add .AddNewtonsoftJson() to services.AddControllers() in Startup.cs, but that would seem a step backward in what I'm trying to achieve (which is to completely cut off from Newtonsoft.Json).

This is the error VS is showing:

Error CS1503 Argument 2: cannot convert from 'Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary' to 'System.Action<Microsoft.AspNetCore.JsonPatch.JsonPatchError>'

Any ideas on how I can make HttpPatch work without depending on Newtonsoft.Json?

My HttpPatch action method looks like this:

[HttpPatch("{id:int}")]
public async Task<ActionResult<DocGroup>> PatchDocumentGroup([FromRoute] int id, [FromBody] JsonPatchDocument<DocGroup> patchDoc)
{
    if (patchDoc == null)
        return BadRequest(ModelState);

    var documentGroup = await _context.DocGroups.FindAsync(id);

    if (documentGroup == null)
    {
        return NotFound();
    }

    patchDoc.ApplyTo(documentGroup, ModelState);

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    await _context.SaveChangesAsync();

    return new ObjectResult(documentGroup);
}
like image 695
Fabricio Rodriguez Avatar asked Oct 23 '25 06:10

Fabricio Rodriguez


1 Answers

Currently, ASP.NET Core doesn't support JSON Patch without Newtonsoft.Json, take a look at this issue from the official repo. On the other hand, you can use this approach to add support for JSON Patch using Newtonsoft.Json, while leaving the other input and output formatters unchanged:

builder.Services.AddControllers(options =>
{
    options.InputFormatters.Insert(0, MyJPIF.GetJsonPatchInputFormatter());
});
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Options;

namespace JsonPatchSample;

public static class MyJPIF
{
    public static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter()
    {
        var builder = new ServiceCollection()
            .AddLogging()
            .AddMvc()
            .AddNewtonsoftJson()
            .Services.BuildServiceProvider();

        return builder
            .GetRequiredService<IOptions<MvcOptions>>()
            .Value
            .InputFormatters
            .OfType<NewtonsoftJsonPatchInputFormatter>()
            .First();
    }
}

That way, NewtonsoftJsonPatchInputFormatter will process the JSON Patch requests, and the existing System.Text.Json-based input and formatters will process all other JSON requests and responses.

like image 55
Luiz Lelis Avatar answered Oct 25 '25 22:10

Luiz Lelis