我仍然是一名业余程序员,试图调整我的技能,我读到的一个习惯是添加一致的 API 响应,以确保用户从我的 API 获得一致的结果。所以我创建了以下模型:
public class ResponseDTO<T>
{
public required bool Succeeded { get; set; }
public required string Message { get; set; } = "";
public required int StatusCode {get; set;}
public string[]? Errors { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Pagination? Pagination {get; set;}
public T Data { get; set; }
}
不清楚从最佳实践来看,如果数据被假定为 T 的单个结果而不是列表,我是否应该忽略分页?通过使用 JsonIgnore 属性,或者我应该始终返回分页数据。
我的第二个问题是如何捕获某些请求期间的错误。例如,对于文档上传请求,我有以下控制器:
public async Task<IActionResult> AddRevisedCertificationAsync([FromForm] AddDocumentDTO addDocumentDTO)
{
try
{
var documentDTO = await _documentsService.AddRevisedCertificationAsync(addDocumentDTO);
return Ok(new ResponseDTO<DocumentDTO>(){
Succeeded = true,
StatusCode = 200,
Message = "The file have been successfully uploaded.",
Data = documentDTO,
Pagination = null});
}
catch(Exception ex)
{
var documentDTO = await _documentsService.AddRevisedCertificationAsync(addDocumentDTO);
return Ok(new ResponseDTO<DocumentDTO>(){
Succeeded = false,
StatusCode = 400,
Message = "The files were not uploaded due to a system error.",
Data = null,
Pagination = null});
}
}
我是否应该在每个控制器中执行 try 和 catch 语句来捕获错误并将结果作为状态代码返回,尽管请求中的总体状态代码将显示 200,因为我使用 Ok() 返回?只是感觉很奇怪。另外,假设我知道有两种可能的例外情况。其中一个文档没有上传到我们的云存储,这是由于某些未知错误而导致的,或者该文件应该是 pdf 格式。我应该在 catch 语句中创建 if 语句来查找抛出的异常类型吗?就像在我的服务层中将 400 异常抛出回我的控制器一样,catch 中的 if 语句将指示上传失败,因为它需要 pdf,并在服务层中抛出 500 异常,如果文档因系统错误而未上传到框,并且再次在 if 语句中捕获它吗?
我只是在努力思考这一切应该如何运作,以便我可以通过我的应用程序一致地实现它。
尚不清楚根据最佳实践,数据是否应该是 T 的单个结果而不是列表我应该忽略分页吗?经过 使用 JsonIgnore 属性还是应该始终返回分页 数据。
回答你这个问题:
如果
Data
属性包含单个对象而不是列表,则最好排除分页,在这种情况下使用 JsonIgnore
属性是合适的。
我的第二个问题是如何捕获某些请求期间的错误。为了 例如,对于文档上传请求,我有以下内容 控制器:
要处理代码中的错误,您可以使用 try-catch 时钟。
[HttpPost]
public async Task<IActionResult> AddRevisedCertificationAsync([FromForm] AddDocumentDTO addDocumentDTO)
{
try
{
var documentDTO = await _documentsService.AddRevisedCertificationAsync(addDocumentDTO);
return Ok(new ResponseDTO<DocumentDTO>()
{
Succeeded = true,
StatusCode = 200,
Message = "The file has been successfully uploaded.",
Data = documentDTO
});
}
catch (KnownException ex) // Replace 'KnownException' with your specific exceptions, e.g., FormatException for a PDF error.
{
return BadRequest(new ResponseDTO<DocumentDTO>()
{
Succeeded = false,
StatusCode = 400,
Message = ex.Message,
Errors = new[] { "The file must be a PDF." }
});
}
catch (Exception ex) // General exception handling for unknown errors.
{
return StatusCode(500, new ResponseDTO<DocumentDTO>()
{
Succeeded = false,
StatusCode = 500,
Message = "An unexpected error occurred.",
Errors = new[] { ex.Message }
});
}
}
在服务层针对已知错误场景抛出特定异常,并在控制器中处理这些异常以提供一致的 API 响应:
public class InvalidFileFormatException : Exception
{
public InvalidFileFormatException(string message) : base(message) { }
}
public class StorageException : Exception
{
public StorageException(string message) : base(message) { }
}
服务层方法示例:
public async Task<DocumentDTO> AddRevisedCertificationAsync(AddDocumentDTO addDocumentDTO)
{
if (addDocumentDTO.File == null || !IsPdf(addDocumentDTO.File))
{
throw new InvalidFileFormatException("The file must be a PDF.");
}
try
{
// Upload logic here
}
catch (Exception ex)
{
throw new StorageException("Failed to upload the document to Box.");
}
// Assume the upload was successful and return the DocumentDTO
}
您可以参考此文档了解更多详细信息: