资源更新
put:对所有资源进行更新
patch:对部分资源进行更新
put使用方法和post相同,但是put是幂等的。
patch使用
数据样式
patch的6个操作
add:添加字段
remove:删除字段
replace:替换字段数据
move:转移
copy:复制
test:测试
使用步骤
nuget 安装
Microsoft.AspNetCore.JsonPatch
和Microsoft.AspNetCore.Mvc.NewtonsoftJson
更新数据的操作方法
[HttpPatch("{touristRouteId}")] public IActionResult PartiallyUpdateTouristRoute([FromRoute] Guid touristRouteId, [FromBody] JsonPatchDocument<TouristRouteForUpdateDto> patchDocument) { //原始数据 var touristRouteFromRepo = _tourisTouteRepository.GetTourisRoute(touristRouteId); //原始数据转创建dto 需要在profile中设定mapper转换 var touristRouteToPatch = _mapper.Map<TouristRouteForUpdateDto>(touristRouteFromRepo); //JsonPatch修改数据更新到dto上,打补丁,并绑定ModelState patchDocument.ApplyTo(touristRouteToPatch,ModelState); if (!TryValidateModel(touristRouteToPatch))//验证数据 { return ValidationProblem(ModelState); } //JsonPatch已经修改了的更新数据映射到原始数据上 //从 touristRouteToPatch到touristRouteFromRepo _mapper.Map(touristRouteToPatch, touristRouteFromRepo);//此时context中的数据已经被mapper更改 _tourisTouteRepository.Save(); return NoContent(); }
program
builder.Services.AddControllers(opt => { opt.ReturnHttpNotAcceptable = true; }).AddNewtonsoftJson(opt => {//注册 opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); })
前端的body数据
[ { "op": "replace", "path": "/title", "value": "AAAAAAAAA" }, { "op": "replace", "path": "/description", "value": "BBBB" } ]
删除
有选择的删除形式DELETE api/touristRoutes/(1,3,4,5)
控制器的操作方法
[HttpDelete("({touristIds})")] public IActionResult DeleteTouristRoutes([ModelBinder(BinderType = typeof(ArrayModelBinder))][FromRoute]IEnumerable<Guid> touristIds) {//收到touristIds(1,3,4,5)自动转换 if (touristIds == null) { return BadRequest(); } //仓库服务收到的字符串是已经处理好的 var toruistRoutesFromRepo = _tourisTouteRepository.GetTouristRouteByIdList(touristIds); _tourisTouteRepository.DeleteTouristRoutes(toruistRoutesFromRepo); _tourisTouteRepository.Save(); return NoContent(); }
2.模型绑定
public class ArrayModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { // 确定是否是Enumerable类型 if (!bindingContext.ModelMetadata.IsEnumerableType) { bindingContext.Result = ModelBindingResult.Failed(); return Task.CompletedTask; } //通过ValueProvider获得输入的值 var value = bindingContext.ValueProvider .GetValue(bindingContext.ModelName).ToString(); // 如果值为空 if (string.IsNullOrWhiteSpace(value)) { bindingContext.Result = ModelBindingResult.Success(null); return Task.CompletedTask; } //通过反射获得Enumerable的类型并得到一个转换器 var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0]; var converter = TypeDescriptor.GetConverter(elementType); //使用逗号分割,并将所有的值使用转换器进行转换到一个数组中 var values = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries) .Select(x => converter.ConvertFromString(x.Trim())) .ToArray(); //通过反射创建具体的数组,并赋值 var typedValues = Array.CreateInstance(elementType, values.Length); values.CopyTo(typedValues, 0); bindingContext.Model = typedValues; //成功,并传递Model bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); return Task.CompletedTask; } }
Post
在head中携带新插入数据的链接
//控制器中获得信息的方法,定义name以供post使用 [HttpGet("{pictureId}", Name = "GetPictureForTouristRoute")] public async Task <IActionResult> GetPictureForTouristRoute(Guid touristRouteId, int pictureId) { if (!await _tourisTouteRepository.TouristRouteExistsAsync(touristRouteId)) { return NotFound("旅游线路不存在"); } var picture = await _tourisTouteRepository.GetPictureAsync(pictureId); if (picture == null) { return NotFound("照片不存在"); } var pictureDto = _mapper.Map<TouristRoutePictureDto>(picture); return Ok(pictureDto); } //post方法 [HttpPost] public async Task<IActionResult> CreateTouristRoutePicture([FromRoute] Guid touristRouteId, [FromBody] TouristRoutePictureForCreateDto touristRoutePictureForCreationDto) { if (!await _tourisTouteRepository.TouristRouteExistsAsync(touristRouteId)) { return NotFound("旅游线路不存在"); } //从createDto转换为模型数据 var pictureModel = _mapper.Map<TouristRoutePicture>(touristRoutePictureForCreationDto); _tourisTouteRepository.AddTouristRoutePicture(touristRouteId, pictureModel);//插入模型数据 await _tourisTouteRepository.SaveAsync(); //从模型数据转换为视图Dto var pictureToReturn = _mapper.Map<TouristRoutePictureDto>(pictureModel); //目的是在返回的head中携带新插入数据的链接,第一个参数为上面的name,第二个参数是上面方法需要的参数,第三个则是需要返回的信息 return CreatedAtRoute("GetPictureForTouristRoute", new { touristRouteId = pictureModel.TouristRouteId, pictureId = pictureModel.Id }, pictureToReturn); }