在ASP.Net Core 2 MVC中禁用模型验证的正确方法

S W*_*aye 6 c# validation asp.net-mvc asp.net-core-2.0

使用扩展方法设置MVC

services.AddMvc()
Run Code Online (Sandbox Code Playgroud)

然后在控制器中,这也可能适用于GET,使用正文中提供的参数为POST操作创建一个方法,例如

[HttpPost("save")]
public Entity Save([FromBody]Entity someEntity)
Run Code Online (Sandbox Code Playgroud)

当调用该动作时,MVC管道将调用ParameterBinder,而ParameterBinder又调用DefaultObjectValidator.我不想要验证(一件事情很慢,但更重要的是循环复杂的循环图),但似乎关闭管道验证的唯一方法是这样的:

public class NonValidatingValidator : IObjectModelValidator
{
    public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

并在StartUp/ConfigureServices中:

        var validator = services.FirstOrDefault(s => s.ServiceType == typeof(IObjectModelValidator));
        if (validator != null)
        {
            services.Remove(validator);
            services.Add(new ServiceDescriptor(typeof(IObjectModelValidator), _ => new NonValidatingValidator(), ServiceLifetime.Singleton));
        }
Run Code Online (Sandbox Code Playgroud)

这看起来像一把大锤.我环顾四周,找不到替代方案,也试图删除DataAnnotationModelValidator没有成功,所以想知道是否有更好/正确的方法来关闭验证?

小智 8

 services.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });
Run Code Online (Sandbox Code Playgroud)

应该禁用自动模型状态验证。

  • 这个答案是错误的。它仅禁用验证错误的处理程序,但不会禁用验证本身! (6认同)
  • @disklosr 怎么样 `services.AddControllers(options =&gt; options.ModelValidatorProviders.Clear());` (3认同)
  • **在 .Net 7 上运行良好**,经过此配置,我们可以轻松地在 Controller 方法中进行验证,例如“ModelState.IsValid”,然后我们可以使用自定义验证模型响应用户。使用此方法将重试所有错误`ModelState.Values.SelectMany(f =&gt; f.Errors).Select(f =&gt; f.ErrorMessage)` (2认同)

小智 8

您应该考虑使用 ValidateNeverAttribute 它几乎没有文档记录,并且被 Microsoft 隐藏得很好。

[ValidateNever]
public class Entity 
{
....
}
Run Code Online (Sandbox Code Playgroud)

这使您可以精细控制要验证哪些实体、不验证哪些实体。


dis*_*osr 7

截至aspnet core 3.1,这是禁用模型验证的方法,如文档中所示:

首先创建这个 NullValidator 类:

public class NullObjectModelValidator : IObjectModelValidator
{
    public void Validate(ActionContext actionContext,
        ValidationStateDictionary validationState, string prefix, object model)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

然后用它代替真实的模型验证器:

services.AddSingleton<IObjectModelValidator, NullObjectModelValidator>();
Run Code Online (Sandbox Code Playgroud)

请注意,这只会禁用模型验证,您仍然会收到模型绑定错误。

  • 这个解决方案有一个大问题,你应该警惕(并且花了我很多时间来找出):当你同时使用这个解决方案+控制器中的 [ApiController] 属性 [FromHeader] 参数时,将始终自动给出一个400 错误请求,没有任何日志记录,使得很难找到问题的根源。 (3认同)

小智 6

扩展.AddMvc()方法有一个重载,您可以在其中配置很多东西。其中之一就是ModelValidatorProviders.

如果您清除此列表,例如:

services.AddMvc(options => options.ModelValidatorProviders.Clear());
Run Code Online (Sandbox Code Playgroud)

不应再进行验证。

  • 不,我的意思是它仍然调用 DefaultObjectValidator,我想存在一些类似“我们是否有验证器,如果没有添加 DefaultObjectValidator”的代码 (2认同)

Sko*_*šek 5

使用这个扩展方法:

public static IServiceCollection DisableDefaultModelValidation(this IServiceCollection services)
{
  ServiceDescriptor serviceDescriptor = services.FirstOrDefault<ServiceDescriptor>((Func<ServiceDescriptor, bool>) (s => s.ServiceType == typeof (IObjectModelValidator)));
  if (serviceDescriptor != null)
  {
    services.Remove(serviceDescriptor);
    services.Add(new ServiceDescriptor(typeof (IObjectModelValidator), (Func<IServiceProvider, object>) (_ => (object) new EmptyModelValidator()), ServiceLifetime.Singleton));
  }
  return services;
}


public class EmptyModelValidator : IObjectModelValidator
{
  public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model)
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

public void ConfigureServices(IServiceCollection services)
{
    services.DisableDefaultModelValidation();
}
Run Code Online (Sandbox Code Playgroud)