首页 > 解决方案 > 如何正确使用 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 : {"errors":{"":["需要非空请求正文。"]},"type":"https://tools.ietf.org/html/rfc7231#section-6.5 .1","title":"出现一个或多个验证错误。","status":400,"traceId":"|c647c045-47f3a2d0bb2bc29c."} At line:1 char:1

  • 调用-RestMethod http://localhost:5000/api/suppliers/1 -Method PATCH ...
  •   + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
    

eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand -Body : 术语“-Body”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确并重试。在行:2 字符:1

  • -Body '[{"op":"replace","path":"City","value":"Los Angeles"}]'
  •   + CategoryInfo          : ObjectNotFound: (-Body:String) [], CommandNotFoundException
      + FullyQualifiedErrorId : CommandNotFoundException
    

我该如何解决?

启动类:

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; }
}

供应商控制器:

[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;
    }
}

在此处输入图像描述

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

标签: jsonasp.net-corejson.netasp.net-core-3.1

解决方案


$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

Postman调用时,正常返回。

在此处输入图像描述

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

在此处输入图像描述

测试PowerShell

在此处输入图像描述


推荐阅读