一、概述
PUT
和 PATCH
方法用于更新现有资源。 它们之间的区别是,PUT 会替换整个资源,而 PATCH 仅指定更改。
在 ASP.NET Core Web API 中,由于 C# 是一种静态语言(dynamic
在此不表),当我们定义了一个类型用于接收 HTTP Patch 请求参数的时候,在 Action
中无法直接从实例中得知客户端提供了哪些参数。
比如定义一个输入模型和数据库实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class PersonInput { public string? Name { get; set; }
public int? Age { get; set; }
public string? Gender { get; set; } }
public class PersonEntity { public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; } }
|
再定义一个以 FromForm
形式接收参数的 Action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| [HttpPatch] [Route("patch")] public ActionResult Patch([FromForm] PersonInput input) { var config = new MapperConfiguration(cfg => { cfg.CreateMap<PersonInput, PersonEntity>()); }); var mapper = config.CreateMapper();
var entity = new PersonEntity { Name = "姓名", Age = 18, Gender = "我可能会被改变", };
mapper.Map(input, entity);
return Ok(); }
|
1 2
| curl --location --request PATCH 'http://localhost:5094/test/patch' \ --form 'Name="foo"'
|
如果客户端只提供了 Name
而没有其他参数,从 HttpContext.Request.Form.Keys
可以得知这一点。如果不使用 AutoMapper,那么就需要使用丑陋的判断:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| [HttpPatch] [Route("patch")] public ActionResult Patch([FromForm] PersonInput input) { var keys = _httpContextAccessor.HttpContext.Request.Form.Keys.Select(m => m.ToLower()); var entity = new PersonEntity { Name = "姓名", Age = 18, Gender = "我可能会被改变", };
if (keys.Contains("name")) { entity.Name = input.Name!; } if (keys.Contains("age")) { entity.Age = input.Age!.Value; } return Ok(); }
|
本文提供一种方式来简化这个步骤。