Dar*_*rov 16 c# fluentvalidation servicestack
我正在评估ServiceStack中的FluentValidation以处理请求DTO的自动验证:
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(MyValidator).Assembly);
Run Code Online (Sandbox Code Playgroud)
通过序列化ErrorResponseDTO 将错误返回给客户端,可能如下所示:
{
"ErrorCode": "GreaterThan",
"Message": "'Age' must be greater than '0'.",
"Errors": [
{
"ErrorCode": "GreaterThan",
"FieldName": "Age",
"Message": "'Age' must be greater than '0'."
},
{
"ErrorCode": "NotEmpty",
"FieldName": "Company",
"Message": "'Company' should not be empty."
}
]
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以使用不同的响应DTO返回错误.例如:
{
"code": "123",
"error": "'Age' must be greater than '0'."
}
Run Code Online (Sandbox Code Playgroud)
我知道可以在服务中明确使用验证器:
public MyService : Service
{
private readonly IValidator<MyRequestDto> validator;
public MyService(IValidator<MyRequestDto> validator)
{
this.validator = validator;
}
public object Get(MyRequestDto request)
{
var result = this.validator.Validate(request);
if (!result.IsValid)
{
throw new SomeCustomException(result);
}
... at this stage request DTO validation has passed
}
}
Run Code Online (Sandbox Code Playgroud)
但这里的问题是,是否有可能在某处隐式拦截此验证错误,以便我可以替换响应DTO并拥有更清洁的服务:
public MyService : Service
{
public object Get(MyRequestDto request)
{
... at this stage request DTO validation has passed
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
在进一步深入研究源代码之后,看起来它被烧入了ValidationFeature更具体的注册请求过滤器:
public class ValidationFilters
{
public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
var validator = ValidatorCache.GetValidator(req, requestDto.GetType());
if (validator == null) return;
var validatorWithHttpRequest = validator as IRequiresHttpRequest;
if (validatorWithHttpRequest != null)
validatorWithHttpRequest.HttpRequest = req;
var ruleSet = req.HttpMethod;
var validationResult = validator.Validate(
new ValidationContext(requestDto, null, new MultiRuleSetValidatorSelector(ruleSet)));
if (validationResult.IsValid) return;
var errorResponse = DtoUtils.CreateErrorResponse(
requestDto, validationResult.ToErrorResult());
res.WriteToResponse(req, errorResponse);
}
}
Run Code Online (Sandbox Code Playgroud)
通过编写自定义验证功能,我能够实现所需的效果.但也许有更优雅的方式?
myt*_*thz 13
我刚刚签入了一个Customization Error钩子,它允许您指定一个自定义错误过滤器,以便在下一版ServiceStack(v3.9.44 +)中更容易支持这种用例.
从CustomValidationErrorTests,您现在可以配置ValidationFeature以使用将返回的自定义错误过滤器,例如:
public override void Configure(Container container)
{
Plugins.Add(new ValidationFeature {
ErrorResponseFilter = CustomValidationError });
container.RegisterValidators(typeof(MyValidator).Assembly);
}
public static object CustomValidationError(
ValidationResult validationResult, object errorDto)
{
var firstError = validationResult.Errors[0];
var dto = new MyCustomErrorDto {
code = firstError.ErrorCode, error = firstError.ErrorMessage };
//Ensure HTTP Clients recognize this as an HTTP Error
return new HttpError(dto, HttpStatusCode.BadRequest, dto.code, dto.error);
}
Run Code Online (Sandbox Code Playgroud)
现在,您的HTTP客户端将收到您的自定义错误响应:
try
{
var response = "http://example.org/customerror".GetJsonFromUrl();
}
catch (Exception ex)
{
ex.GetResponseBody().Print();
//{"code":"GreaterThan","error":"'Age' must be greater than '0'."}
}
Run Code Online (Sandbox Code Playgroud)
警告:以这种方式自定义错误响应时,ServiceStack的类型化C#客户端将不再提供类型化异常,因为它们期望错误响应包含ResponseStatus DTO属性.
| 归档时间: |
|
| 查看次数: |
3701 次 |
| 最近记录: |