需要在 startup 类中的 ConfigureService 方法中进行配置 示例:
// 注册 控制器服务
services.AddControllers(configure: setup =>
{
setup.ReturnHttpNotAcceptable = true;
//setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
//setup.OutputFormatters.Insert(index: 0, new XmlDataContractSerializerOutputFormatter());
})
// 配置处理数据的格式,默认只支持 json,配置后可以支持XML 数据格式
.AddXmlDataContractSerializerFormatters()
// 配置错误警告信息,自定义警告信息
.ConfigureApiBehaviorOptions(setup => {
// 配置 InvalidModelStateResponseFactory 信息
setup.InvalidModelStateResponseFactory = context =>
{
// 传入匿名方法,并且配置错误警告的详细信息
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Type = "https://www.baidu.com",
Title = "error",
Status = 422,
Detail = "please look detail message",
Instance = context.HttpContext.Request.Path
};
// 设置traceid 信息
problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
// return 这个类,它实现了IActionResult 接口,符合InvalidModelStateResponseFactory 的FUnc委托的要求。
return new UnprocessableEntityObjectResult(problemDetails)
{
ContentTypes = { "application/problem+json" }
};
};
})
;
http 提供 的put 方法 一般用于整体的资源更新, 示例:
// 使用 HttpPut 标注
[HttpPut("{employeeId}")]
public async Task<IActionResult> UpdateEmployeeForCompany(Guid companyId, Guid employeeId, EmployeeUpdateDto employee)
{
// 先检验公司是否存在合法
if (!await _companyRepository.CompantExistsAsync(companyId))
{
return NotFound();
}
// 检验员工信息是否存在
var employeeEntity = await _companyRepository.GetEmployeeAsync(companyId, employeeId);
// 如果查询为空,则不是执行更新操作。而是执行新增操作
if (employeeEntity == null)
{
// 借助automapper,将EmployeeUpdateDto 类型映射成 Employee类型
var employeeToAddEntity = _mapper.Map<Employee>(employee);
employeeToAddEntity.Id = employeeId;
// 新增employee
_companyRepository.AddEmployee(companyId, employeeToAddEntity);
await _companyRepository.SaveAsync();
// 由于是创建资源,需要返回204状态码,将entity employee 实体类 映射成 Dto类用于返回
var returnDto = _mapper.Map<EmployeeDTO>(employeeToAddEntity);
return CreatedAtRoute(nameof(GetEmployeeForCompany), new { companyId = companyId, employeeId = returnDto.Id }, returnDto);
}
// 如果 员工信息不为空,则执行更新操作
_mapper.Map(employee, employeeEntity);
_companyRepository.UpdateEmployee(employeeEntity);
await _companyRepository.SaveAsync();
return NoContent();
}
put 一般用于整体的资源更新和替换,但多数情况下只是修改资源的部分,需要使用 patch 方法
使用 patch 需要使用安装 Microsoft.AspNetCore.JsonPatch nuget 包,借助该包来完成 patch 请求的数据的解析。 但 安装完成之后,会出现解析错误的情况,这是因为 安装完 jsonpatch 包之后,它将之前asp.net core默认的json解析方替换了,但它提供的数据解析方式功能不够强大,不能满足使用,所以还需要安装 Microsoft.AspNetCore.NewtonsoftJson nuget 包 a来满足需要。 在 startup 中配置
.AddNewtonsoftJson(setup => {
setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
配置 json.net 的服务。 示例:
[HttpPatch("{employeeId}")]
public async Task<IActionResult> PartiallyUpdateEmployeeForCompany(Guid companyId, Guid employeeId, JsonPatchDocument<EmployeeUpdateDto> patchDocument)
{
if (!await _companyRepository.CompantExistsAsync(companyId))
{
return NotFound();
}
var employeeEntity = await _companyRepository.GetEmployeeAsync(companyId, employeeId);
if (employeeEntity == null)
{
var employeeDto = new EmployeeUpdateDto();
patchDocument.ApplyTo(employeeDto, ModelState);
if (!TryValidateModel(ModelState))
{
return ValidationProblem(ModelState);
}
var employeeToAdd = _mapper.Map<Employee>(employeeDto);
employeeToAdd.Id = employeeId;
_companyRepository.AddEmployee(companyId, employeeToAdd);
await _companyRepository.SaveAsync();
var returnDto = _mapper.Map<EmployeeDTO>(employeeToAdd);
return CreatedAtRoute(nameof(GetEmployeeForCompany), new { companyId = companyId, employeeId = returnDto.Id }, returnDto);
}
var dtoToPatch = _mapper.Map<EmployeeUpdateDto>(employeeEntity);
// 使用 patchDoucument ,将请求传递的参数传递给 dto 类
// 传递第二个参数,ModelState ,则可以都请求传递的数据进行数据验证
patchDocument.ApplyTo(dtoToPatch, ModelState);
// TryValidateModel 也是进行数据验证,如果验证失败,则返回 400
// todo ,这里可以通过重写 ControllerBase 的 ValidationProblem 方法,来改变返回状态码等信息
if (!TryValidateModel(dtoToPatch))
{
return ValidationProblem(ModelState);
}
// dto 类 映射 entity 实体类
_mapper.Map(dtoToPatch, employeeEntity);
// 执行过更新操作
_companyRepository.UpdateEmployee(employeeEntity);
await _companyRepository.SaveAsync();
return NoContent();
}
整体的思路跟 PUT 的请求 的处理基本一致,只是由于使用到了新的 nuget 包,导致代码有所差异。
使用 http delete 方法,进行资源删除。 示例:
[HttpDelete("{companyId}")]
public async Task<IActionResult> DeleteCompany(Guid companyId)
{
var companyEntity = await _companyRepository.GetCompanyAsync(companyId);
if (companyEntity == null)
{
return NotFound();
}
_companyRepository.Delete(companyEntity);
await _companyRepository.SaveAsync();
return NoContent();
}
比较简单,就是移除数据。