P32 局部更新 PATCH
path是某一个属性的路径,value是要替换的值。
把它的值从qux改成boo
把foo这个属性删除。
一共有6种
add:向一个资源对象里面添加一个值,或者是像数组里面添加一个元素。在向数组里面添加元素的时候也可以指定它的index
比如下面的这里index是1就表示它要在索引为1的前面插入一个元素。
![](https://img2020.cnblogs.com/blog/87548/202012/87548-20201207234755521-1866265425.png)
replace:替换,先把它删掉,然后再做一个add操作。先做remove再做add
![](https://img2020.cnblogs.com/blog/87548/202012/87548-20201207234755878-1808132483.png)
copy:复制,对象里面某个值,从一个地方复制到另外一个地方,
![](https://img2020.cnblogs.com/blog/87548/202012/87548-20201207234756224-152057405.png)
move:把这个值从这个属性移动到另外一个属性,
![](https://img2020.cnblogs.com/blog/87548/202012/87548-20201207234756593-1917815053.png)
test:验证的意思。验证对象里面这个路径,这个属性,它的值是否是这个,如果值不为这个的话,那么他所在的请求的JSON Path document就认为是不合理的。
![](https://img2020.cnblogs.com/blog/87548/202012/87548-20201207234756927-149495197.png)
json patch文档可能有多个操作,如果有一个操作失败了,那么这整个请求就相当于失败了。
写代码
需要安装一个库
按照提示选取,进行安装
安装完成这里就变成绿色的
这是新增的post方法
为什么选EmployeeUpdateDto呢 因为它里面没有id这个属性。有id这个属性就有可能被更改,
先来检查CompanyId和EmployeeId为空的情况。
应用PatchDocument
先把entity转换为UpdateDto
映射文件的添加。从Employee映射到UpdateDto
applyTo这句话执行的过程中,它可能会出现错误,比如patchDocument中有个add操作,它add一个属性,这个属性在C#类里面并不存在,这时候就会报错。或者它要修改一个只读的属性,这些都会报错。所以说我们需要处理这块。
这里待会再写
把dtoToPath映射到Entity上。
然后更新,保存。返回204 NoContent
先来运行测试下。改成put请求。
header改成-patch+json
body里面修改。里面是个数组,数组里面包含若干个操作。
先来写一个更新的操作
返回422,说明验证有错误。
这是dotnet.core3.0开始使用的json库是一个比较新的json库,但是这个json库只实现了一些比较核心的功能。很多功能它还没有实现。那么这些功能谁实现了呢?就是我们原来用过的json.net
使用json.net库替换默认的json转换。
然后在startUp里面注册,并做一些配置
再次发送这个请求
再做一下查询employeeNo确实更改了。出现的问题查询结果变成了xml格式的。
写上accept的header就可以了。但是如果没有写accept的header为什么返回了xml格式的数据呢?
先添加的xml,后添加的json。所以默认的就会先采用xml,后采用json
那么我们就把xml的移到json的后面。
这样默认返回的就是json了
再加一个操作
返回204
查询下 ,确实被更新了。
remove
年龄被换成了默认的值就是 001年所以 年龄这里就返回了2019岁。
再加上复制操作,把employeeNo的值复制给lastName
查询结果。
处理验证错误的逻辑
这里remove字段employeeNo。在数据库 EFCore 这块 employeeNo字段是必填的。我们要看一下是否会走APIController的这块验证。如果走了这块验证那么就应该返回422.
如果没有走controller的验证,而是走的数据库的验证。那么返回的应该就是500.
返回了500.也就是在controller model绑定的时候并没有走。
为什么这里没走呢?因为这里的类型是JsonPatchDocument类型。而不是updateDto类型。所以在下面我就需要手动的进行验证。
如果验证错误,就会返回false。验证错误信息也会放在modelState这个对象里面。
返回了400
为什么返回的不是422呢?现在我们验证的是UpdateDto
这里也可能出错,比如我们要删除一个不存在的属性
测试删除一个不存在的属性。返回了500,说明服务器端发生了异常。这里返回500应该不对,因为这是客户端的错误,应该返回4开头的错误。
处理错误
加一个参数,传入ModelState。如果这个patchDocument里面有任何的错误,就会把validate设置为false,把错误信息放在ModelState里面,
400
处理返回的是400,而不是422
这里是我们手动返回的
在startUp里面我们自定义了错误格式。但是上面的代码并没有采用我们下面startUp里面配置的错误。
Model绑定的时候采用了这个配置
修改返回的格式
方法的重写。
最后我们return的不是默认的base.ValidationProblem
我们要采用startUp里面的配置
再次发送请求
讨论话题
传进来的id如果有资源就做更新,没有就做新增。
new一个UpdateDto。然后传入patchDocument做验证
测试
id改成最后4个9
复制header的location
可以获取到这个资源
结束