use*_*966 4 swagger .net-core asp.net-core-webapi
我现在尝试使用 .NET Web API 改进自己,并尝试在 Swagger 中返回自定义错误。但是当返回这个自定义错误时,我可以看到错误在哪一行。我该怎么做才能防止这种情况发生?
public async Task<BookCreateDTO> CreateBook(BookCreateDTO bookCreateDto)
{
if (await _context.Books.AnyAsync(x => x.Name == bookCreateDto.Name))
{
throw new BookExistException("Book already exist");
}
var book= _mapper.Map<Book>(bookCreateDto);
_context.Books.Add(book);
await _context.SaveChangesAsync();
return book;
}
Run Code Online (Sandbox Code Playgroud)
我应该怎么做才能在 Swagger 响应中仅看到此异常消息?感谢您的帮助。
异常应该是异常的:不要为非异常错误抛出异常。
我不建议在 C# 操作方法返回类型中指定 Web 服务的响应 DTO 类型,因为它限制了您的表达能力(正如您所发现的)。
IActionResult或ActionResult<T>来记录默认(即 HTTP 2xx)响应类型,然后在[ProducesResponseType]属性中列出错误 DTO 类型及其相应的 HTTP 状态代码。
DtoFooDtoBarDtoQuxModelState(Key如果可能的话,使用 ),并让ASP.NET Core 使用ProblemDetails.ProblemDetails- 或者它可以显示DeveloperExceptionPage- 或完全其他内容。
[ProducesResponseType]:这在使用 Swagger/NSwag 生成在线文档和客户端库时非常有用。POST /users。{ accessLevel: 'superAdmin' }虽然您可以排除或限制可以通过请求设置对象的哪些属性,但它只会增加项目的维护工作量(因为它是程序中的另一个非本地、手动编写的列表或定义,您需要确保将其保留在- 与其他一切同步。User实体将具有 aByte[] PasswordHash 和Byte[] PasswordSalt属性(我希望......),显然这两个属性永远不能公开;但是在用于编辑用户的用户 DTO 中,您可能需要不同的成员,例如NewPassword和ConfirmPassword- 它们根本不映射到数据库列。Customer对象具有内联街道地址字段,但现在它们丢失了(因为您的CustomerEF 实体类型不再具有街道地址列,这在CustomerAddress实体类中已结束)。Customer对象的专用 DTO 类型,那么在更新应用程序设计的过程中,您会注意到由于 DTO 中的 C# 编译时类型检查,构建会更快中断(而不是不可避免地更晚!)到实体(以及实体到 DTO)映射代码 - 这就是一个好处。无论如何,我已经修改了您发布的代码以遵循上述指导:
[ProducesResponseType]属性。
BookCreateDTO我明白两次指定默认响应类型是多余的 ([ProducesResponseType]以及ActionResult<BookCreateDTO>- 您应该能够删除其中任何一个而不影响 Swagger 输出。[FromBody]为了安全起见,我添加了一个显式的。BadRequest响应中返回模型验证消息,该消息将呈现为 IETF RFC 7807 响应,也 ProblemDetails 就是抛出异常,然后希望您配置了 ASP。 NET Core 管道(在Configure())中将其作为处理ProblemDetails,而不是调用调试器或使用DeveloperExceptionPage.
conflictResult.StatusCode = 409;覆盖。BookCreateDTO最终响应是通过 AutoMapper从新实例生成的,而Ok()不是序列化Book实体对象。[ProducesResponseType(typeof(BookCreateDTO), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]
public async Task< ActionResult<BookCreateDTO> > CreateBook( [FromBody] BookCreateDTO bookCreateDto )
{
// Does a book with the same name exist? If so, then return HTTP 409 Conflict.
if( await _context.Books.AnyAsync(x => x.Name == bookCreateDto.Name) )
{
this.ModelState.Add( nameof(BookCreateDTO.Name), "Book already exists" );
BadRequestObjectResult conflictResult = this.BadRequest( this.ModelState );
// `BadRequestObjectResult` is HTTP 400 by default, change it to HTTP 409:
conflictResult.StatusCode = 409;
return conflictResult;
}
Book addedBook;
{
addedBook = this.mapper.Map<Book>( bookCreateDto );
_ = this.context.Books.Add( book );
_ = await this.context.SaveChangesAsync();
}
BookCreateDTO responseDto = this.mapper.Map<BookCreateDTO >( addedBook );
return this.Ok( responseDto );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1371 次 |
| 最近记录: |