0

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, paths 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.

Sam Carlson
  • 1,891
  • 1
  • 17
  • 44

0 Answers0