我有以下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... }
}
由于我使用验证功能,验证器会自动连接到SomethingRequest
的所有方法,这真的很棒。
当条件失败时,我想返回409 Conflict
HTTP状态代码,但始终会返回400 Bad Request
。
所以,问题是:
400 BadRequest
状态代码?答案 0 :(得分:3)
1)虽然它允许依赖注入和存储库连接,但是流畅的验证代码不是你应该放置这种代码的地方,因为它更符合验证代码。 This answer对两者之间的差异有一个很好的解释。我只想补充说,如果只是为了更容易返回适当的状态代码,将验证从验证中分离出来也是有意义的。
2)如果您想覆盖400 BadRequest
状态代码,可以使用验证功能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改变。
答案 1 :(得分:2)
我是否滥用了验证功能? (即自动验证的验证器不能用于应用程序逻辑检查)
我认为这最好在远离验证的业务逻辑中完成,因为检查唯一性实际上是验证检查而不是验证,因为它需要检查数据源。 My answer on this question解决了类似问题。
虽然您可以使用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");
}
}
然后只需注释DTO:
[VerifySomethingCode]
public class SomethingRequest {
public string Code { get; set; }
}
然后,您可以确定DTO中的代码已经过验证,并且您可以返回所需的任何状态和响应。过滤器为您提供全面控制。
希望这有帮助。