面试题:如何创建一个验证请求的API框架

本文探讨了如何通过MediatR管道行为在API请求到达领域层之前进行集中验证,保持领域层的清洁和简单。介绍了使用FluentValidation进行验证,并展示了如何通过异常处理和ProblemDetails规范提供一致的错误响应,以提升API的用户体验。
摘要由CSDN通过智能技术生成

开发一款成功软件的关键是良好的架构设计。优秀的设计不仅允许开发人员轻松地编写新功能,而且还能丝滑的适应各种变化。

好的设计应该关注应用程序的核心,即领域。

不幸的是,这很容易将领域与不属于这一层的职责混淆。每增加一个功能,就会使理解核心领域变得更加困难。同样糟糕的是,将来就更难重构了。

因此,保护领域层不受应用程序逻辑影响是很重要的。其中一个优化是对传入请求的验证。为了防止验证逻辑渗透到领域级别,我们希望在请求到达领域级别之前验证请求。

在这篇文章中,我们将学习如何从领域层中提取验证。在我们开始之前,本文假设API使用command模式将传入请求转换为命令或查询。本文中所有的代码片段都使用了MediatR。

command模式的好处是将核心逻辑从API层分离出来。大多数实现command模式的库也公开了可以连接到其中的中间件。这很有用,因为它提供了一个解决方案,可以添加需要与每个命令一起执行的应用程序逻辑。

MediatR请求

使用C# 9中引入的record类型,它可以把请求变成一行代码。另一个好处是,实例是不可变的,这使得一切变得可预测和可靠。

record AddProductToCartCommand(Guid CartId, string Sku, int Amount) : MediatR.IRequest;

为了分发上述命令,可以将传入的请求映射到控制器中。

[ApiController]
[Route("[controller]")]
public class CustomerCartsController : ControllerBase
{
    private readonly IMediator _mediator;
​
    public CustomerCartsController(IMediator mediator)
        => _mediator = mediator;
​
    [HttpPost("{cartId}")]
    public async Task<IActionResult> AddProductToCart(Guid cartId, [FromBody] CartProduct cartProduct)
    {
        await _mediator.Send(new AddProductToCartCommand(cartId, cartProduct.Sku, cartProduct.Amount));
        return Ok();
    }
}

MediatR验证

我们将使用MediatR管道,而不是在控制器中验证AddProductToCartCommand。

通过使用管道,可以在处理程序处理命令之前或之后执行一些逻辑。在这种情况下,提供一个集中的位置,在命令到达处理程序(领域)之前在该位置对其进行验证。当命令到达它的处理程序时,我们不再需要担心命令是否有效。

虽然这看起来是一个微不足道的更改,但它清理了领域层中每个处理程序。

理想情况下,我们只希望在领域中处理业务逻辑。删除验证逻辑解放了我们的思想,这样我们就可以更关注业务逻辑。由于验证逻辑是集中的,它确保所有命令都得到验证,而没有一条命令漏过漏洞。

在下面的代码片段中,我们创建了一个ValidatorPipelineBehavior来验证命令。当命令被发送时,ValidatorPipelineBehavior处理程序在它到达领域层之前接收命令。ValidatorPipelineBehavior通过调用对应于该类型的验证器来验证该命令是否有效。只有当请求有效时,才允许将请求传递给下一个处理程序。如果没有,则抛出InputValidationException异常。

我们将看看如何使用FluentValidation在验证中创建验证器。现在,重要的是要知道,当请求无效时,将返回验证消息。验证的细节被添加到异常中,稍后将用于创建响应。

public class ValidatorPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;
​
    public ValidatorPipelineBehavior(IEnumerable<IValidator<TRequest>> validators)
      => _validators = validators;
​
    public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        // Invoke the validators
        va
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值