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

问题描述 投票:0回答:8

使用扩展方法设置 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)
    {
    }
}

并在启动/配置服务中:

        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
但没有成功,所以想知道是否有更好/正确的方法来关闭验证?

c# asp.net-mvc validation asp.net-core-2.0
8个回答
47
投票
 services.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });

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


8
投票

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

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

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


7
投票

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>();

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


5
投票

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

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

services.AddMvc(options => options.ModelValidatorProviders.Clear());

验证不应再进行。


4
投票

使用此扩展方法:

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();
}

3
投票

要关闭对继承类的所有内容的验证:

  var mvc = services.AddMvc(options =>
  {
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(VMClass))); 
  }); // to avoid validation of the complete world by following VMClass refs

2
投票

创建空模型验证器类。

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

在配置服务方法中将 DefaultModelValidator 替换为 EmptyModelValidator。

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

EmptyModelValidator 不验证模型,因此 ModelState.IsValid 始终返回

false


0
投票

虽然 @aseaSharp 答案(可能)做同样的事情,但通常您只想在几个操作上禁用模型验证。这是我的几句话:

属性类

using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace D3S.KoFu.WebSite.Helpers;

[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].GetType().FullName == "Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilterFactory")  
            {  
                action.Filters.RemoveAt(i);  
                break;  
            }  
        }  
    }
}

和像这样的标准方法装饰

[HttpPost]
[SuppressModelStateInvalidFilter]
public IActionResult DoIt([FromBody] MyModel model)
{
   ...
}
© www.soinside.com 2019 - 2024. All rights reserved.