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