如何在ASP.NET Core MVC控制器中阻止模型属性被验证?
解决ASP.NET Core中跳过特定属性模型验证的问题
这个问题很常见——当你不想让模型的某些属性(尤其是包含复杂类型的列表)参与验证时,ASP.NET Core的默认递归验证会帮你“过度验证”,导致Action根本没机会执行。下面给你两种可行的方案,都能实现你想要的[NoValidation]特性效果:
方案一:在自定义ValidateModelAttribute中移除指定属性的验证错误
这种方法适合你已经在使用自定义ValidateModelAttribute的场景,直接在验证后清理掉不需要的错误即可:
1. 定义NoValidationAttribute特性
首先创建标记用的特性,用来标识不需要验证的属性:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class NoValidationAttribute : Attribute { }
2. 修改你的ValidateModelAttribute
在检查ModelState之前,先移除所有带有[NoValidation]标记的属性及其子属性的验证错误:
public class ValidateModelAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { // 收集所有标记了[NoValidation]的属性名 var noValidationProps = context.ActionArguments .SelectMany(arg => arg.Value?.GetType().GetProperties() .Where(p => p.GetCustomAttribute<NoValidationAttribute>() != null) .Select(p => p.Name) ?? Enumerable.Empty<string>()) .ToList(); // 移除这些属性及其子属性的验证错误(比如RejectedEmployees[0].FirstName这类路径) foreach (var key in context.ModelState.Keys.ToList()) { if (noValidationProps.Any(prop => key == prop || key.StartsWith($"{prop}."))) { context.ModelState.Remove(key); } } // 清理后再次检查,如果还有错误才返回BadRequest if (!context.ModelState.IsValid) { context.Result = new BadRequestObjectResult(context.ModelState); } } } }
方案二:自定义ModelValidatorProvider(更高效)
这种方法从模型验证的源头入手,直接不让验证器对标记的属性进行验证,比方案一更高效:
1. 同样先定义NoValidationAttribute
和方案一的特性代码完全一样:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class NoValidationAttribute : Attribute { }
2. 实现自定义的ModelValidatorProvider
public class NoValidationModelValidatorProvider : IModelValidatorProvider { public void CreateValidators(ModelValidatorProviderContext context) { // 检查当前模型属性是否带有[NoValidation]标记 if (context.ModelMetadata.PropertyInfo?.GetCustomAttribute<NoValidationAttribute>() != null) { // 清空该属性的所有验证器,这样就不会执行任何验证逻辑 context.Validators.Clear(); } } }
3. 在Startup中注册这个Provider
services.AddMvc(options => { options.Filters.Add(new ValidateModelAttribute()); // 添加自定义验证器提供者 options.ModelValidatorProviders.Add(new NoValidationModelValidatorProvider()); });
最后一步:标记不需要验证的属性
在你的ExcelEmployeeModel中,给RejectedEmployees加上[NoValidation]标记:
public class ExcelEmployeeModel { [Required] public String Description { get; set; } public List<Employee> Accepted { get; set; } [NoValidation] public List<Employee> RejectedEmployees { get; set; } }
这样一来,无论是方案一还是方案二,都能跳过RejectedEmployees及其内部Employee对象的所有验证,你的Action就能正常接收到数据并执行了。
内容的提问来源于stack exchange,提问作者jwize
相关产品推荐
相关产品推荐

