移动:{“op”: "move", "from": "/xxx", "path": "/yyy"},把源属性的值赋值给目标属性,并把源属性删除或设成默认值。
测试:{“op”: "test", "path": "/xxx", "value": "xxx"},测试目标属性的值和指定的值是一样的。
注意,path属性可能具有层级结构,而value属性也不必非得是字符串。
看下代码:
传递进来的body参数需要使用JsonPatchDocument<T>这个类型,在这里我把它叫做patchDoc。首先要把EFCore的City映射成CityUpdateResource,这样这个CityUpdateResource就有了该City在数据库里最新的属性值。然后通过patchDoc.ApplyTo()这个方法把patchDoc的操作依次附加给这个CityUpdateResource,这时候所有需要更新的值都体现在CityUpdateResource里了,而该对象其它的属性值则是数据库里的最新值,也就是不需要更新的值。最后再把它的值映射给EFCore的City,进行更新就可以了。最后EFCore做的操作肯定是整体更新,但是之前我们把最新值都放在CityUpdateResource里了,所以就相当于只做了局部更新。
测试:
请求的Content-Type应该是"application/json-patch+json",但是如果之写成application/json好像也可以。
结果:
(为了更好的测试,我又为City添加了Description属性)
下面remove的测试:
反查:
在测试一下多个操作:
结果就不看了,都是OK的。
PATCH用来局部更新或创建资源
可以修改相关代码来支持局部更新或创建资源的操作:
这个我就不测试了,自增Id不适合这种操作。
HTTP方法适用总结
常用的5中HTTP方法都介绍了,下面总结一下:
GET(获取资源):
GET api/countries,返回200,集合数据;找不到数据返回 404。
GET api/countries/{id}, 返回200,单个数据;找不到返回 404.
DELETE(删除资源)
DELETE api/countries/{id},成功204;没找到资源 404。
DELETE api/countries,很少用,也是204或者404.
POST (创建资源):
POST api/countries, 成功返回 201 和单个数据;如果资源没有创建则返回 404
POST api/countries/{id},肯定不会成功,返回 404或409.
POST api/countrycollections,成功返回 201 和集合;没创建资源则返回 404
PUT (整体更新):
PUT api/countries/{id}, 成功可以返回200,204;没找到资源则返回 404
PUT api/countries,集合操作很少见,返回 200,204或404
PATCH(局部更新):
PATCH api/countries/{id},200单个数据,204或者404
PATCH api/countries, 集合操作很少见,返回 200集合,204或404.
验证
为了进行输入验证(不验证输出),我们需要做以下三方面工作:
定义验证规则
检查验证规则
把验证错误信息发送给API的消费者
之前的文章也提到的ASP.NET Core里面定义验证规则的方式:
Data annotations 数据注解,就是那种在属性上面的中括号样式的属性标签
如何数据注解无法满足要求,则可以使用自定义的验证方式
可以自定义数据注解
也可以让被验证类实现IValidatableObject接口
也可以使用像FluentApi这样的第三方验证库
检查验证规则的方式:
使用 ModelState
它是一个字典,包含了Model的状态以及Model所绑定的验证
对于提交的每个属性,它都包含了一个错误信息的集合
ModelState.IsValid(),如果出现任何一个错误,ModelState.IsValid属性就会变成false。
报告验证错误信息:
返回的状态吗应该是 422 Unprocessable Entity (上文讲过,422表示请求的格式没问题,但是语义有错误,例如实体验证错误)
除了状态码之外,还需要把验证错误信息在响应的body里面带回去
为EFCore的Model添加约束