覆盖来自验证器的 http 状态代码

J0H*_*0HN 6 c# http-status-codes fluentvalidation servicestack

我有以下 DTO:

public class SomethingRequest {
     public string Code { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Code 必须是唯一的,所以我创建了一个验证器来检查是否已经有提供代码的记录,如下所示

public class SomethingValidator: AbstractValidator<SomethingRequest> 
{
    public SomethingValidator(ISomethingRepository repo) {
         RuleFor(something => something.Code).Must(BeUnique);
    }

    private bool BeUnique(string code) { ... uniqueness check... }
}
Run Code Online (Sandbox Code Playgroud)

当我使用验证功能时,验证器会自动连接到所有带有 的方法SomethingRequest,这真的很棒。

当条件失败时,我想返回409 ConflictHTTP 状态代码,但400 Bad Request总是返回。

所以,问题是:

  1. 我是否滥用了验证功能?(即自动装配的验证器并非设计用于应用程序逻辑检查)
  2. 如果不是,有什么方法可以覆盖400 BadRequest验证器的状态代码吗?

Sco*_*ott 3

我是否滥用了验证功能?(即自动连接验证器并非设计用于应用程序逻辑检查)

我想说这最好在远离验证的业务逻辑中完成,因为检查唯一性实际上是验证检查而不是验证,因为它需要针对数据源进行检查。我对这个问题的回答也解决了类似的问题。

虽然您可以使用 覆盖验证错误的响应状态代码ErrorResponseFilter,但我建议您为此业务逻辑创建自己的请求过滤器,因为随着应用程序的增长,覆盖响应会变得混乱,而且这并不是真正的验证。

在 ServiceStack 中使用过滤器属性非常简单:

public class VerifySomethingCodeAttribute : Attribute, IHasRequestFilter
{
    IHasRequestFilter IHasRequestFilter.Copy()
    {
        return this;
    }

    public int Priority { get { return int.MinValue; } }

    public void RequestFilter(IRequest req, IResponse res, object requestDto)
    {
        SomethingRequest somethingRequestDto = requestDto as SomethingRequest;
        if(somethingRequestDto == null)
            return;

        // Verify the code
        // Replace with suitable logic
        // If you need the database your wire it up from the IoC
        // i.e. HostContext.TryResolve<IDbConnectionFactory>();
        bool isUnique = ...

        if(!isUnique)
            throw HttpError.Conflict("This record already exists");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后简单注释一下DTO:

[VerifySomethingCode]
public class SomethingRequest {
    public string Code { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以确保 DTO 中的代码已被验证为唯一,并且您可以返回您想要的任何状态和响应。过滤器让您完全控制。

希望这可以帮助。