如何正确使用HttpPatch和JsonPatchDocument

问题描述

在Powershell中应用此请求后,我遇到错误

Invoke-RestMethod http://localhost:5000/api/suppliers/1 -Method PATCH -ContentType "application/json"
-Body '[{"op":"replace","path":"City","value":"Los Angeles"}]'

错误消息:

Invoke-RestMethod:{“错误”:{“”:[“非空请求正文为 必需。“]},”类型“:” https://tools.ietf.org/html/rfc7231#section-6.5.1“,”标题“:”一个 或更多验证错误 “,”状态“:400,” traceId“:” | c647c045-47f3a2d0bb2bc29c。“}在 行:1字符:1

  • Invoke-RestMethod http:// localhost:5000 / api / suppliers / 1-方法补丁...
  •   + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod],WebExc
    

肽 + FullyQualifiedErrorId:WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand -Body:术语“ -Body”不被视为cmdlet,函数,脚本文件或可运行程序的名称。检查拼写 名称,或者是否包含路径,请验证路径是否正确,以及 再试一次。在第2行:char:1

  • -正文'[{“ op”:“ replace”,“ path”:“ City”,“ value”:“ Los Angeles”}]''
  •   + CategoryInfo          : ObjectNotFound: (-Body:String) [],CommandNotFoundException
      + FullyQualifiedErrorId : CommandNotFoundException
    
@H_404_35@

我该如何解决

启动课程:

public class Startup {

    public Startup(IConfiguration config) {
        Configuration = config;
    }

    public IConfiguration Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services) {
        services.AddDbContext<DataContext>(opts => {
            opts.UsesqlServer(Configuration[
                "ConnectionStrings:ProductConnection"]);
            opts.EnableSensitiveDataLogging(true);
        });

        services.AddControllers().AddNewtonsoftJson();
        services.Configure<MvcNewtonsoftJsonoptions>(opts =>
        {
            opts.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
        });
    }

    public void Configure(IApplicationBuilder app,DataContext context) {
        app.UseDeveloperExceptionPage();
        app.UseRouting();
        app.UseMiddleware<TestMiddleware>();
        app.UseEndpoints(endpoints => {
            endpoints.MapGet("/",async context => {
                await context.Response.WriteAsync("Hello World!");
            });
            endpoints.MapControllers();
        });
        SeedData.SeedDatabase(context);
    }
}

供应商类别:

public class supplier {

    public long supplierId { get; set; }
    public string Name { get; set; }
    public string City { get; set; }

    public IEnumerable<Product> Products { get; set; }
}

suppliersController:

[ApiController]
[Route("api/[controller]")]
public class suppliersController : ControllerBase
{
    private DataContext context;

    public suppliersController(DataContext ctx)
    {
        context = ctx;
    }

    [HttpGet("{id}")]
    public async Task<supplier> Getsupplier(long id)
    {
        supplier supplier = await context.suppliers
            .Include(s => s.Products)
            .FirstAsync(s => s.supplierId == id);

        foreach (Product p in supplier.Products)
        {
            p.supplier = null;
        }
        return supplier;
    }

    [HttpPatch("{id}")]
    public async Task<supplier> Patchsupplier(long id,JsonPatchDocument<supplier> patchDoc)
    {
        supplier s = await context.suppliers.FindAsync(id);
        if (s != null)
        {
            patchDoc.ApplyTo(s);
            await context.SaveChangesAsync();
        }
        return s;
    }
}

enter image description here

github中的源代码https://github.com/Apress/pro-asp.net-core-3/tree/master/20%20-%20Advanced%20Web%20Services%20Features

解决方法

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type","application/json")

$body = "[{`"op`":`"replace`",`"path`":`"City`",`"value`":`"Los Angeles`"}]"

$response = Invoke-RestMethod 'http://localhost:5000/api/suppliers/1' -Method 'PATCH' -Headers $headers -Body $body
$response | ConvertTo-Json

邮递员打电话时,它会正常返回。

enter image description here

如果您需要PowerShell中的访问代码,则可以在Postman中自动生成。

enter image description here

PowerShell中测试

enter image description here