将带有Postman的PATCH发送到Asp.net Core webapi时出错

问题描述:

我有一个模特,

public class Order
{
    public Guid Id { get; set; }
    public IEnumerable<string> ItemIds { get; set; }
    public string Currency { get; set; }
}

和一个存储库

public interface IOrderRepository
{
    IEnumerable<Order> Get();
    Order Get(Guid id);
    void Add(Order order);
    void Update(Guid id, Order order);
    // other irrelevant code has been deleted for simplicity
}

public class MemoryOrderRepository : IOrderRepository
{
    private readonly IList<Order> _orders = new List<Order>();
    public IEnumerable<Order> Get() => _orders;

    public Order Get(Guid id) => _orders.FirstOrDefault(o => o.Id == id);
    public void Add(Order order) => _orders.Add(order);

    public void Update(Guid id, Order order)
    {
        var target = _orders.FirstOrDefault(o => o.Id == id);
        if (target != null) target.ItemIds = order.ItemIds;
    }
    // other irrelevant code has been deleted for simplicity
}

已在Startup.cs中注册的

如下.

that have been registered in Startup.cs as follows.

    public void ConfigureServices(IServiceCollection services) =>
        services.AddSingleton<IOrderRepository, MemoryOrderRepository>()
                .AddControllers()
                .AddNewtonsoftJson();

其他相关的nuget软件包已经如下安装.

Additional relevant nuget packages are already installed as follows.

<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />

测试控制器如下.

[Route("api/[controller]")]
[ApiController]
public class OrderController : ControllerBase
{
    private readonly IOrderRepository repo;

    public OrderController(IOrderRepository repo)
    {
        this.repo = repo;
    }

    [HttpGet]
    public IActionResult Get() => Ok(repo.Get());

    [HttpGet("{id:guid}")]
    public IActionResult Get(Guid id) => Ok(repo.Get(id));

    [HttpPost]
    public IActionResult Post(Order order)
    {
        Order target = new Order()
        {
            Id = Guid.NewGuid(),
            ItemIds = order.ItemIds
        };

        repo.Add(target);

        return CreatedAtAction(nameof(Get), new { id = target.Id }, null);
    }

    [HttpPatch("{id:guid}")]
    public IActionResult Patch(Guid id, JsonPatchDocument<Order> order)
    {
        Order target = repo.Get(id);
        if (target == null)
            return NotFound(new { Message = $"Item with id {id} does not exist." });


        order.ApplyTo(target);
        repo.Update(id, target);
        return Ok();
    }

    // other irrelevant code is deleted for simplicity
}

使用邮递员,我成功地创建了一个新订单,方法是先将POST动词发送到服务器,然后通过发送GET动词来确认结果,如下所示.

Using Postman, I successfully created a new order by sending POST verb to the server first and then confirming the result by sending GET verb as follows.

我尝试使用以下内容部分更新订单,但失败了.

I attempted to partially update the order with the following but failed.

错误消息是

JSON补丁文档格式错误,无法解析.

The JSON patch document was malformed and could not be parsed.

哪里出了问题以及如何解决?

What is wrong and how to fix it?

代替

{
    "ItemIds": ["xyz","123"]
}

我也尝试过

{
    "op":"replace",
    "path":"/ItemIds",
    "value": ["xyz","123"]
}

两者都无济于事.

根据

According to the docs for json patch you need to pass an array of operations instead of single object, like so

[
  {
    "op":"replace",
    "path":"/ItemIds",
    "value": ["xyz","123"]
  }
]