servicestack,http-status-codes,fluentvalidation,C#,servicestack,Http Status Codes,Fluentvalidation" /> servicestack,http-status-codes,fluentvalidation,C#,servicestack,Http Status Codes,Fluentvalidation" />

C# 覆盖验证程序中的http状态代码

C# 覆盖验证程序中的http状态代码,c#,servicestack,http-status-codes,fluentvalidation,C#,servicestack,Http Status Codes,Fluentvalidation,我有以下DTO: public class SomethingRequest { public string Code { get; set; } } code必须是唯一的,因此我创建了一个验证器,用于检查是否已经存在包含所提供代码的记录,如下所示 public class SomethingValidator: AbstractValidator<SomethingRequest> { public SomethingValidator(ISomethingR

我有以下DTO:

public class SomethingRequest {
     public string Code { get; set; }
}
code
必须是唯一的,因此我创建了一个验证器,用于检查是否已经存在包含所提供代码的记录,如下所示

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

    private bool BeUnique(string code) { ... uniqueness check... }
}
公共类SomethingValidator:AbstractValidator
{
公共SomethingValidator(ISomethingRepository repo){
RuleFor(something=>something.Code).Must(BeUnique);
}
私有布尔BeUnique(字符串代码){…唯一性检查…}
}
当我使用验证功能时,验证器会自动连接到带有
SomethingRequest
的所有方法,这真是太棒了

当条件失败时,我想返回
409冲突
HTTP状态码,但
400错误请求
总是返回

因此,问题是:

  • 我是否误用了vaidation功能?(即,自动连线验证器设计不用于应用程序逻辑检查)
  • 如果我没有,是否有任何方法可以覆盖来自验证器的
    400 BadRequest
    状态代码
  • 1) 尽管它允许依赖注入和连接存储库,但fluent验证代码并不是您应该放置此类代码的地方,因为它更像是验证代码。很好地解释了两者之间的差异。我要补充的是,如果只是为了更容易地返回适当的状态代码,那么将验证与验证分离也是有意义的

    2) 如果要覆盖
    400 BADDREQUEST
    状态代码,可以使用验证功能的
    ErrorResponseFilter
    如下:

    Plugins.Add(new ValidationFeature
    {
        ErrorResponseFilter = CustomValidationError
    });
    
    ...
    
    private object CustomValidationError(ValidationResult validationResult, object errorDto)
    {
        var firstError = validationResult.Errors.First();
        return new HttpError(HttpStatusCode.Conflict, firstError.ErrorCode, firstError.ErrorMessage);
    }
    
    此筛选器看起来是用于全局解决方案的,因为它似乎没有为您提供任何确定错误来源的dto/服务的简单方法。我建议改为在1中进行更改

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

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

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

    在ServiceStack中使用筛选器属性非常简单:

    公共类VerifySomethingCodeAttribute:Attribute,IHasRequestFilter
    {
    IHasRequestFilter IHasRequestFilter.Copy()
    {
    归还这个;
    }
    公共int优先级{get{return int.MinValue;}}
    public void RequestFilter(IRequest请求、IResponse响应、对象requestDto)
    {
    SomethingRequest somethingRequestDto=作为SomethingRequest的requestDto;
    if(somethingRequestDto==null)
    返回;
    //验证代码
    //替换为合适的逻辑
    //如果你需要这个数据库,你可以通过IoC连接它
    //即HostContext.TryResolve();
    bool isUnique=。。。
    如果(!isUnique)
    抛出HttpError.Conflict(“此记录已存在”);
    }
    }
    
    然后简单地注释DTO:

    [VerifySomethingCode]
    公共类SomethingRequest{
    公共字符串代码{get;set;}
    }
    
    然后,您可以确保DTO中的代码将被验证为唯一的,并且您可以返回所需的任何状态和响应。过滤器为您提供完全控制


    希望这能有所帮助。

    谢谢您的链接。至于响应过滤器-这有点过分了,因为实际上,在提到的验证器中有更多的检查,而验证器并不打算抛出409。您是否能够将此检查添加到您将在服务期间执行的业务逻辑中?这样,您仍然可以使用dto在不同的方法中重复使用代码(假设在所有方法中都使用了一些业务逻辑)?非常感谢您的反馈,谢谢。:)@斯科特,还没有,我被卷入了其他的事情。我已经和我的同事们讨论过这个方法,我们认为这是一条路要走,但我们现在有400个还可以,还有一些更重要的事情要做。无论如何,我会让你知道:)没问题,对不起,我不是故意催你的。祝您的项目好运。@Scott别担心,不会造成任何伤害:)谢谢。@Scott我最终将验证移到了服务层。过滤方法可行,但不可行,因为每个请求需要一个过滤器,需要唯一性检查(或公共接口,或提取要验证的内容的其他方法)。