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);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With