Ultimate ASP.NET CORE 6.0 Web API --- 读书笔记(10 - 12)
10 Working With DELETE Requests
本文内容来自书籍: Marinko Spasojevic - Ultimate ASP.NET Core Web API - From Zero To Six-Figure Backend Developer (2nd edition)
需要本书和源码的小伙伴可以留下邮箱,有空看到会发送的
11 Working With PUT Requests
需要给PUT API提供一个新的DTO,虽然内容是一样的,不过还是需要区分开比较好,这个原因会在模型验证的章节说明
两种情况的更新
- 有关联的更新,有关联指的是查询数据和更新数据是在同一个
Context
中,因此,如果查询的数据(已经被跟踪)被修改了,那么状态会变成Modified
,然后直接调用Save
方法,就会产生Update SQL
- 无关联的更新,指的是查询和更新的操作不在同一个
Context
中进行,也就是说你需要更新的这个实体,是没有被当前的Context
所跟踪的,而且这个实体是具有Id
的,这样的没有被跟踪的实体,需要先是将它加入Context
或者说被跟踪,然后再设置状态为Modified
,然后Save
的时候,就会有Update SQL
,不过有一个问题,就是,即使只是更新了其中一个字段,也会有全字段的更新
12 Working With PATCH Requests
PUT 负责全更新
PATCH 部分更新
但是这个不是它们两者之间的唯一区别,请求体也不一样
- PATCH的请求体是:
[FromBody]JsonPatchDocument<Company>
,格式是
[
{
"op": "replace",
"path": "/name",
"value": "new name"
},
{
"op": "remove",
"path": "/name"
}
]
一共有六种不同的操作
// 赋值
{
"op": "add",
"path": "/name",
"value": "new name"
},
// 赋值
{
"op": "replace",
"path": "/name",
"value": "new name"
},
// 赋值(默认值)
{
"op": "remove",
"path": "/name"
},
// 将from的值赋给path
{
"op": "copy",
"from": "/name",
"path": "/title"
},
// 将from的值赋给path
{
"op": "move",
"from": "/name",
"path": "/title"
},
// 测试特定字段是否有特定值
{
"op": "test",
"path": "/name",
"value": "new name"
}
- PUT的请求体是:
[FromBody]Company
media type
也不一样
- PATCH的是:
application/json-patch+json
,虽然直接用application/json
也是能用的,不过建议是用这种 - PUT的是:
application/json
那么在ASP.NET Core中,需要安装相应的包实现
在主项目中,安装Microsoft.AspNetCore.Mvc.NewtonsoftJson
,用以支持请求体转换成PatchDocument
在Presentation
中安装Microsoft.AspNetCore.JsonPatch
,用以支持JsonPatchDocument
在控制器中使用
在主项目的配置中,如果直接使用AddNewtonsoftJson
,那么它会替换System.Text.Json formatters
,然后是全局替换,所有的JSON序列化工作都被转移了,但是作者不希望这样做,只希望在局部使用这个JSON包,所以在Program.cs
中
// 添加一个本地方法
NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter() =>
new ServiceCollection()
.AddLogging()
.AddMvc()
.AddNewtonsoftJson()
.Services.BuildServiceProvider()
.GetRequiredService<IOptions<MvcOptions>>().Value.InputFormatters
.OfType<NewtonsoftJsonPatchInputFormatter>()
.First();
builder.Services.AddControllers(config =>
{
config.RespectBrowserAcceptHeader = true;
config.ReturnHttpNotAcceptable = true;
config.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
})
.AddXmlDataContractSerializerFormatters()
.AddCustomCsvFormatter()
.AddApplicationPart(typeof(AssemblyReference).Assembly);
自动映射,可以正向和反向一起,这样就不用重复写
CreateMap<EmployeeForUpdateDto, Employee>().ReverseMap();
[HttpPatch("{id:guid}")]
public IActionResult PartiallyUpdateEmployeeForCompany(Guid companyId, Guid id,
[FromBody] JsonPatchDocument<EmployeeForUpdateDto>? patchDoc)
{
if (patchDoc is null)
return BadRequest("patchDoc object sent from client is null.");
var result = _service.EmployeeService.GetEmployeeForPatch(companyId, id,
compTrackChanges: false,
empTrackChanges: true);
patchDoc.ApplyTo(result.employeeToPatch);
_service.EmployeeService.SaveChangesForPatch(result.employeeToPatch,
result.employeeEntity);
return NoContent();
}
然后可以看到,在请求体的接受上,与PUT
方法是不一样的,然后处理方式是先查询出原有的对象,然后将JSONdoc转换为DTO,然后调用Save方法,内部会将DTO转换为Entity,由于前面查询Entity是有跟踪的,所以在修改了Entity之后,模型状态就是Modified
了,直接保存就会有Update SQL
了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?