如何拦截 FluentValidation 错误响应,以便将其格式化为我的标准
How can I intercept FluentValidation error response so I can format it to my standard
我正在开发一个 ASP.NET Core 2.1 API,它目前有一个全局 ValidateModelAttribute 过滤器拦截 OnActionExecuting 方法中的 context.ModelState,因此它可以格式化任何模型状态错误以匹配错误信息的项目设计标准。
效果很好。但是,我决定将 FluentValidation 添加到项目中,即使它也可以正常工作,它 returns 模型状态响应没有命中 ValidateModelAttribute 过滤器中的 OnActionExecuting 方法 class。
这是 Startup 中的代码 --> AddMvc 的 ConfigureServices 方法
services.AddMvc(config =>
{
config.Filters.Add(typeof(ValidateModelAttribute));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<ServiceTypeCodeValidator>())
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
这里是ValidateModelAttributeclass本身,仅供参考;
public class ValidateModelAttribute : ActionFilterAttribute
{
/// <summary>
/// Validates model state upon action execution
/// </summary>
/// <param name="context">ActionExecutingContext object</param>
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid) return;
var errorList = context.ModelState.Where(ms => ms.Value.Errors.Any()).ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Errors.Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage).ToArray()
);
var validationErrors = new ValidationErrors();
foreach (var item in errorList)
{
foreach (var message in item.Value)
{
if (validationErrors.Errors.ContainsKey(item.Key))
{
validationErrors.Errors[item.Key].Add(message);
}
else
{
validationErrors.Errors.Add(item.Key, new List<string>() { message });
}
}
}
var globalError = new GlobalError { Errors = errorList };
context.Result = new BadRequestObjectResult(globalError);
}
}
我假设因为这是 asp.net 管道并且 AddFluentValidation 出现在 config.filters.Add 行之后,这就是我无法通过 ValidateModelAttribute 过滤器覆盖 FluentValidation 的错误消息的原因。
所以我的问题是,FluentValidation 是否提供任何类型的挂钩我可以覆盖以格式化模型状态错误响应以匹配项目错误消息标准?
当您说 returns ModelState 响应时,您是指默认的 .NET 响应吗?如果是这样,只需将其添加到 startup
services.Configure<Microsoft.AspNetCore.Mvc.ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
我正在开发一个 ASP.NET Core 2.1 API,它目前有一个全局 ValidateModelAttribute 过滤器拦截 OnActionExecuting 方法中的 context.ModelState,因此它可以格式化任何模型状态错误以匹配错误信息的项目设计标准。
效果很好。但是,我决定将 FluentValidation 添加到项目中,即使它也可以正常工作,它 returns 模型状态响应没有命中 ValidateModelAttribute 过滤器中的 OnActionExecuting 方法 class。
这是 Startup 中的代码 --> AddMvc 的 ConfigureServices 方法
services.AddMvc(config =>
{
config.Filters.Add(typeof(ValidateModelAttribute));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<ServiceTypeCodeValidator>())
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
这里是ValidateModelAttributeclass本身,仅供参考;
public class ValidateModelAttribute : ActionFilterAttribute
{
/// <summary>
/// Validates model state upon action execution
/// </summary>
/// <param name="context">ActionExecutingContext object</param>
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid) return;
var errorList = context.ModelState.Where(ms => ms.Value.Errors.Any()).ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Errors.Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage).ToArray()
);
var validationErrors = new ValidationErrors();
foreach (var item in errorList)
{
foreach (var message in item.Value)
{
if (validationErrors.Errors.ContainsKey(item.Key))
{
validationErrors.Errors[item.Key].Add(message);
}
else
{
validationErrors.Errors.Add(item.Key, new List<string>() { message });
}
}
}
var globalError = new GlobalError { Errors = errorList };
context.Result = new BadRequestObjectResult(globalError);
}
}
我假设因为这是 asp.net 管道并且 AddFluentValidation 出现在 config.filters.Add 行之后,这就是我无法通过 ValidateModelAttribute 过滤器覆盖 FluentValidation 的错误消息的原因。
所以我的问题是,FluentValidation 是否提供任何类型的挂钩我可以覆盖以格式化模型状态错误响应以匹配项目错误消息标准?
当您说 returns ModelState 响应时,您是指默认的 .NET 响应吗?如果是这样,只需将其添加到 startup
services.Configure<Microsoft.AspNetCore.Mvc.ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});