我喜欢ASP.NET Core 2.1新增的Automatic HTTP 400 responses功能,并且在大多数情况下效果都很好。
但是,在一项操作中,我需要在验证有效负载之前进行一些预处理。我有一个自定义验证器,该验证器需要模型中的两个值来执行验证。这些值之一在路径中,因此我想从路径上在模型上设置该值,然后进行验证。
我不想使用以下所有操作关闭功能:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
}
有什么办法可以将其关掉吗?
编辑:
我尝试修改InvalidModelStateResponseFactory,但是并不能解决我的问题,因为我仍然需要执行控制器操作:
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = actionContext =>
{
var ignore = actionContext.ActionDescriptor.FilterDescriptors.Any(fd => fd.Filter is SuppressModelStateInvalidFilterAttribute);
if (ignore)
{
// Can only return IActionResult so doesn't enter the controller action.
}
return new BadRequestObjectResult(actionContext.ModelState);
};
});
[AttributeUsage(AttributeTargets.Method)]
public class SuppressModelStateInvalidFilterAttribute : FormatFilterAttribute
{
}
编辑:
以下是我在asp.net核心存储库中提出的一个问题的链接,以防万一我遇到问题-https://github.com/aspnet/Mvc/issues/8575
答案 0 :(得分:2)
可能可以通过针对特定情况实现自己的验证器来解决。文档中对此进行了很好的介绍。
要么验证模型绑定器,要么创建定制模型绑定器,以在验证之前完成所有预处理。
答案 1 :(得分:1)
您可以使用ApiBehaviorOptions.InvalidModelStateResponseFactory
属性来根据actionContext
的详细信息处理特定的案例:
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = actionContext =>
{
// Do what you need here for specific cases with `actionContext`
// I believe you can cehck the action attributes
// if you'd like to make mark / handle specific cases by action attributes.
return new BadRequestObjectResult(context.ModelState);
}
});
答案 2 :(得分:1)
我收到了Microsoft的回复-https://github.com/aspnet/Mvc/issues/8575
以下内容颇具魅力。
[AttributeUsage(AttributeTargets.Method)]
public class SuppressModelStateInvalidFilterAttribute : Attribute, IActionModelConvention
{
public void Apply(ActionModel action)
{
for (var i = 0; i < action.Filters.Count; i++)
{
if (action.Filters[i] is ModelStateInvalidFilter)
{
action.Filters.RemoveAt(i);
break;
}
}
}
}
然后,在我的控制器中,我可以在重新验证模型之前对模型进行更改(请注意ModelState.Clear(),TryValidateModel添加到现有模型状态):
if (model == null)
{
return BadRequest(ModelState);
}
model.Property = valueFromPath;
ModelState.Clear();
if (TryValidateModel(model) == false)
{
return BadRequest(ModelState);
}
答案 3 :(得分:1)
基于Simon Vane的回答,我不得不如下修改ASP.Net Core 2.2的属性:
/// <summary>
/// Suppresses the default ApiController behaviour of automatically creating error 400 responses
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class SuppressModelStateInvalidFilterAttribute : Attribute, IActionModelConvention {
private static readonly Type ModelStateInvalidFilterFactory = typeof(ModelStateInvalidFilter).Assembly.GetType("Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilterFactory");
public void Apply(ActionModel action) {
for (var i = 0; i < action.Filters.Count; i++) {
if (action.Filters[i] is ModelStateInvalidFilter || action.Filters[i].GetType() == ModelStateInvalidFilterFactory) {
action.Filters.RemoveAt(i);
break;
}
}
}
}
答案 4 :(得分:1)
我遇到了类似的问题,并提出了解决方案。
public class SuppressModelStateInvalidFilterAttribute : ActionFilterAttribute
{
public SuppressModelStateInvalidFilterAttribute()
{
Order = -2500;
}
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
context.ModelState.Clear();
return next.Invoke();
}
}