We are using .NET Core 3.1, Microsoft.AspNetCore.JsonPatch 3.1.27 and AutoMapper 12.0.1.
We are developing a REST API. It exposes some endpoints for updating entities with HTTP PATCH verb. These controller actions accept JSON patch document of DTO classes, ex. JsonPatchDocument<RestApiRequest>
.
[HttpPatch]
public IActionResult UpdateCustomer(JsonPatchDocument<RestApiRequest> req)
{
return Ok();
}
public class RestApiRequest
{
public string CustomerName { get; set; }
public string CompanyAddress { get; set; }
}
Our 2 database models look like this (simplified):
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Address { get; set; }
}
We configured AutoMapper like this:
// RestApiRequest.CompanyAddress is mapped to Address
CreateMap<RestApiRequest, Company>()
.ForMember(x => x.Address, x => x.MapFrom(y => y.CompanyAddress));
// RestApiRequest.CustomerName is mapped to Name
CreateMap<RestApiRequest, Customer>()
.ForMember(x => x.Name, x => x.MapFrom(y => y.CustomerName));
CreateMap<JsonPatchDocument<RestApiRequest>, JsonPatchDocument<Company>>();
CreateMap<JsonPatchDocument<RestApiRequest>, JsonPatchDocument<Customer>>();
CreateMap<Operation<RestApiRequest>, Operation<Company>>();
CreateMap<Operation<RestApiRequest>, Operation<Customer>>();
When a client sends a HTTP request to one of the controller actions, we get an object like the one in patch
variable. Then, we try to map it from JsonPatchDocument<RestApiRequest>
to JsonPatchDocument<Customer>
and save it to mappedPatch
variable:
var patch = new JsonPatchDocument<RestApiRequest>()
.Replace(x => x.CustomerName, "New customer name")
.Replace(x => x.CompanyAddress, "New company address");
var mappedPatch = _mapper.Map<JsonPatchDocument<RestApiRequest>, JsonPatchDocument<Customer>>(patch);
However, path
s in JsonPatchDocument.Operations
are not mapped. Both patch
and mappedPatch
have the same paths, which is not correct:
[
{
"value":"New customer name",
"path":"/CustomerName",
"op":"replace"
},
{
"value":"New company address",
"path":"/CompanyAddress",
"op":"replace"
}
]
I would expect that mappedPatch
's paths would be /Name
and /Company/Address
.