リクエスト DTO の自動検証を処理するために、ServiceStack で FluentValidation を評価しています。
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(MyValidator).Assembly);
エラーはErrorResponse
DTO をシリアル化することによってクライアントに返され、次のようになります。
{
"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."
}
]
}
別の応答 DTO を使用してエラーを返すことができるかどうかを知りたいです。例えば:
{
"code": "123",
"error": "'Age' must be greater than '0'."
}
サービスでバリデーターを明示的に使用できることを知っています。
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
}
}
しかし、ここでの問題は、応答 DTO を置き換えてよりクリーンなサービスを提供できるように、この検証エラーをどこかで暗黙的に傍受できるかどうかです。
public MyService : Service
{
public object Get(MyRequestDto request)
{
... at this stage request DTO validation has passed
}
}
アップデート:
ソースコードをさらに掘り下げた後、これは、より具体的にはそれが登録するリクエストフィルターに焼き付けられているようです: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);
}
}
カスタム検証機能を作成することで、目的の効果を得ることができました。しかし、もっとエレガントな方法があるのではないでしょうか?