我使用https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.2&tabs=visual-studio作为参考,并对更新的处理方式很感兴趣。
为更新方法提供以下代码:
public class Todo
{
public int Id { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
}
public class UpdateTodoRequest
{
public string Title { get; set; }
public bool Completed { get; set; }
}
public async Task<ActionResult> UpdateAsync([FromRoute] id, UpdateTodoRequest todoUpdateRequest)
{
if (todo == null)
{
return BadRequest();
}
var result = await _todoService.UpdateAsync(id, todoUpdateRequest);
// Here I can have three possible results
// 1. Todo with that Id was not found - 404
// 2. Todo didn't pass validation rules - 400 (together with list of rules that didn't pass)
// 3. Everything was successful - 204
}
我应该如何为_todoService.UpdateAsync
方法签名建模,以便它可以处理我列出的所有三种情况?
我可以将其重构如下:
public async Task<ActionResult> UpdateAsync([FromRoute] id, UpdateTodoRequest todoUpdateRequest)
{
if (todo == null)
{
return BadRequest();
}
// Getting the whole Todo by id coming from route
var todo = await _todoService.GetById(id);
if (todo == null)
{
// Returning 404 here
return NotFound();
}
// Updating values coming from request to todo taken from service
todo.Title = todoUpdateRequest.Title;
todo.Completed = todo.Completed;
// Result = boolean for success/failure
var result = await _todoService.UpdateAsync(todo);
return result ? NoContent() : BadRequest();
}
在此版本中,我几乎可以处理所需的案例:
那么我该如何为我的服务建模,以便控制器可以处理以上所有这三种情况?同样,我乐于接受任何建议以不同的方式做事,或者公开讨论已被讨论至死的SO问题。
我还认为,使用功能世界中的Either
Monad:https://mikhail.io/2016/01/validation-with-either-data-type-in-csharp/来指示成功/验证错误并根据其结果返回正确的响应类型是很有意义的。
答案 0 :(得分:1)
由于该操作中有多种返回类型和路径,因此必须自由使用[ProducesResponseType]
属性。此属性为由Swagger之类的工具生成的API帮助页面生成更具描述性的响应详细信息。 [ProducesResponseType]
表示该操作将返回的已知类型和HTTP状态代码。请参阅here。
您可以使用下面的代码返回三种响应的类型。
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> UpdateAsync([FromRoute] id, UpdateTodoRequest todoUpdateRequest)