Не похоже, что библиотека FluentValidation справится с этим самостоятельно.Обходной путь - реализовать интерфейс IValidatorInterceptor
в конкретной реализации AbstractValidator<T>
.Кэш памяти может использоваться для хранения уникального идентификатора запроса, который затем позволяет извлечь идентификатор из кэша из фильтра действий.Будет возвращен объект ValidationResult
, который содержит всю расширенную информацию проверки.
Ниже приведены примеры кода:
public abstract class BaseModelValidator<T> : AbstractValidator<T>, IValidatorInterceptor
{
protected readonly IMemoryCache cache;
protected readonly ILogger<BaseModelValidator<T>> log;
protected string RequestId { get; set; }
public BaseModelValidator(IMemoryCache cache, ILogger<BaseModelValidator<T>> log)
{
this.cache = cache;
this.log = log;
}
public virtual ValidationContext BeforeMvcValidation(ControllerContext controllerContext, ValidationContext validationContext)
{
RequestId = controllerContext.HttpContext.TraceIdentifier;
return validationContext;
}
public virtual ValidationResult AfterMvcValidation(ControllerContext controllerContext, ValidationContext validationContext, ValidationResult result)
{
cache.Set(RequestId, result, TimeSpan.FromMinutes(1));
return result;
}
}
Фильтр глобального действия:
public class ActionModelValidationAttribute : ActionFilterAttribute
{
readonly ILogger<ActionModelValidationAttribute> log;
readonly IMemoryCache cache;
public ActionModelValidationAttribute(IMemoryCache cache, ILogger<ActionModelValidationAttribute> log)
{
this.log = log;
this.cache = cache;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var key = context.HttpContext.TraceIdentifier;
cache.TryGetValue<ValidationResult>(key, out var result);
if (result == null) ReturnError(context, key); // impl ReturnError however you like
cache.Remove(key);
var count = result.Errors.Count();
var controllerName = context.RouteData.Values["Controller"] ?? "unknown";
var routeName = context.RouteData.Values["Action"] ?? "unknown";
var response = result.AsBaseResponse();
log.LogDebug($"Model validation failed. {count} errors in model for {controllerName}.{routeName}");
context.Result = new JsonResult(response)
{
StatusCode = (int)HttpStatusCode.BadRequest
};
}
}
}