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

时间:2017-09-23 01:00:25

标签: c# asp.net-mvc validation asp.net-core-2.0

使用扩展方法

设置MVC
services.AddMvc()

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

[HttpPost("save")]
public Entity Save([FromBody]Entity someEntity)

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

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

并在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));
        }

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

6 个答案:

答案 0 :(得分:4)

 services.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });

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

答案 1 :(得分:3)

aspnet core 3.1开始,这就是禁用模型验证的方式,如docs所示:

首先创建此NullValidator类:

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

    }
}

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

services.AddSingleton<IObjectModelValidator, NullObjectModelValidator>();

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

答案 2 :(得分:1)

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

如果清除此列表,例如:

services.AddMvc(options => options.ModelValidatorProviders.Clear());
不应再进行验证。

答案 3 :(得分:1)

使用此扩展方法:

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)
  {
  }
}

用法:

public void ConfigureServices(IServiceCollection services)
{
    services.DisableDefaultModelValidation();
}

答案 4 :(得分:0)

创建空的模型验证器类。

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

在configure services方法中将DefaultModelValidator替换为EmptyModelValidator。

services.Replace(
    new ServiceDescriptor(typeof(IObjectModelValidator), 
    typeof(EmptyModelValidator),
    ServiceLifetime.Singleton)
);

EmptyModelValidator无法验证模型,因此ModelState.IsValid始终返回false

答案 5 :(得分:0)

您应该考虑使用 ValidateNeverAttribute,它几​​乎没有记录并且被 Microsoft 很好地隐藏起来。

[ValidateNever]
public class Entity 
{
....
}

这让您可以精细地控制哪些实体要验证,哪些不验证。