Closed Vincent-Lz-Zhang closed 1 year ago
Hi @Vincent-Lz-Zhang, which example request produced the error?
@fiyazbinhasan
[ { "op": "add", "path": "/customerName", "value": "Barry" }, { "op": "add", "path": "/orders/-", "value": { "orderName": "Order2", "orderType": null } } ]
For your information, the JsonConverter for JSON Patch Document does not work either in my own ASP.NET Core Web API project (also based on NET 6.0) after following the tutorial. And that motivated me to test this example.
Ok...I'll take a look at it ASAP. Will prepare a sample and modify the docs if necessary. Thanks for reporting 😊
@Vincent-Lz-Zhang, I've found the issue you are facing. If I'm correct, you are not correctly setting the Content-Type
. For a patch, the Content-Type
should be application/json-patch+json
instead of the regular application/json
for other HTTP methods.
It is documented in the Get the code
@Rick-Anderson the placement of this mandatory information needs to be better. Would you like me to point this out somewhere else in the doc?
@fiyazbinhasan yes, after line 310, add:
JsonPatch requires setting the Content-Type Header to application/json-patch+json
Yes, it works. Thank you very much. @fiyazbinhasan
@fiyazbinhasan
Actually, while waiting for the reply, I have already implemented a simplified version of JsonConverter for JsonPatchDocument
However, the challenge for me is not over yet. I modified the example code as below:
New class EditCustomerDto added, it wraps JsonPatchDocument
using Microsoft.AspNetCore.JsonPatch;
namespace JsonPatchSample.Models;
public class EditCustomerDto
{
public JsonPatchDocument<Customer> Changes { get; set;}
public string ChangeComments { get; set; }
}
And I changed the controller's 3rd method to:
[HttpPatch]
public IActionResult JsonPatchWithoutModelState([FromBody] EditCustomerDto editDto)
{
var customer = CreateCustomer();
editDto.Changes.ApplyTo(customer);
return new ObjectResult(customer);
}
In Postman, I specified the following body:
{
"changes": [
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
],
"ChangeComments": "Editor's comments"
}
It does not work. I got error:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "00-5e328a3c8afdfbf69632424ccb6025d3-5ca0caaabb40e9f4-00", "errors": { "patchDoc": [ "The patchDoc field is required." ], "$.changes": [ "The JSON value could not be converted to Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1[JsonPatchSample.Models.Customer]. Path: $.changes | LineNumber: 1 | BytePositionInLine: 16." ] } }
So, is there a way to make it work when having JsonPatchDocument
I just have some new findings.
First, if I call AddNewtonsoftJson(), changing the Content-Type would not be necessary. The example in the doc still works with Content-Type being application/json.
Second, if I call AddNewtonsoftJson(), with Content-Type being application/json, it also works with my wrapper class EditCustomerDto.
Then here comes my question: I understand application/json-patch+json is specified by the RFC6902 standard, though, is it really the essential cause to the problem I raised?
@Vincent-Lz-Zhang, the reason why you are not using AddNewtonsoftJson()
is that it replaces the defauft System.Text.Json
input /output formatter. The idea behind MyJPIF.GetJsonPatchInputFormatter
is to use the System.Text.Json
while adding support for only the JSON patch using Microsoft.AspNetCore.Mvc.NewtonsoftJson
. We yet don't have support for Json patch in System.Text.Json. See this issue
To address your comment earlier,
{
"changes": [
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
],
"ChangeComments": "Editor's comments"
}
As you can see, this is not a valid JSON patch document. I would instead suggest you go with the following approach,
public class EditCustomerDto
{
public string? CustomerName { get; set; }
public List<Order>? Orders { get; set; }
public string ChangeComments { get; set; }
}
[HttpPatch]
public IActionResult JsonPatchWithDto([FromBody] JsonPatchDocument<EditCustomerDto> editDto)
{
var customerDto = CreateCustomerDto();
editDto.ApplyTo(customerDto);
return new ObjectResult(customerDto);
}
private EditCustomerDto CreateCustomerDto()
{
return new EditCustomerDto
{
CustomerName = "John",
Orders = new List<Order>()
{
new Order
{
OrderName = "Order0"
},
new Order
{
OrderName = "Order1"
}
},
ChangeComments = "Comments"
};
}
You can specify multiple operations in a patch. The following body replaces the value of ChangeComments
to Editor's comments
.
[
{
"op": "replace",
"path": "/changeComments",
"value": "Editor's comments"
},
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
You can use some mapper library to map to and from between EditCustomerDto
and Customer
I checked out the source code in this folder: https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/jsonpatch/samples/6.x/api
Before started my testing, I went through this document: https://learn.microsoft.com/en-us/aspnet/core/web-api/jsonpatch?view=aspnetcore-6.0, so the sample HTTP request body I used was taken from it.
I built and ran the Web API project, and with Postman, I sent a PATCH request to: http://localhost:63971/jsonpatch/JsonPatchWithoutModelState
I got error:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "00-125d7abfba57ccb4a038cd738bbc7544-ec252f112ed656d1-00", "errors": { "$": [ "The JSON value could not be converted to Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1[JsonPatchSample.Models.Customer]. Path: $ | LineNumber: 0 | BytePositionInLine: 1." ], "patchDoc": [ "The patchDoc field is required." ] } }
The error suggests that the JsonConverter for JsonPatchDocument does not work at all. I'm on Windows 10 Pro, OS build: 19045.2604 And Visual Studio 2022 Community Version 17.3.0
Document Details
⚠ Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.
Associated WorkItem - 69047