未标记Required的模型字段为何导致ModelState.IsValid返回false?
问题
我定义了如下视图模型:
public record CreateViewModel { [Required] [StringLength( 250, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 5 )] public string Name { get; set; } = string.Empty; [StringLength( 20, ErrorMessage = "The {0} must be at least {2} characters long." )] [Display(Name = "Phone Number")] public string AlternateContactPhoneNumber { get; set; } = string.Empty; }
控制器执行以下代码时:
if (!ModelState.IsValid) { return View(model); }
系统提示“Phone Number”字段为必填项,但该属性并未标记[Required]特性,这是什么原因?
原因与解决办法
- 核心原因:你的项目开启了Nullable引用类型(C# 8及以上版本常见配置,可通过项目文件
<Nullable>enable</Nullable>确认),ASP.NET Core会自动为所有非可空引用类型的属性(比如这里的string AlternateContactPhoneNumber,而非string?)添加隐式的[Required]验证规则,不需要手动标记[Required]特性就会触发必填校验。 - 额外问题:你在
StringLength特性的错误消息中使用了{2}占位符(对应MinimumLength参数值),但未指定MinimumLength,这会导致错误消息显示异常,但触发必填提示的根本原因还是Nullable引用类型的隐式验证。
解决办法
根据业务需求选择以下方案:
- 允许字段为空:将属性改为可空引用类型,取消隐式必填验证:
public string? AlternateContactPhoneNumber { get; set; } = string.Empty; - 保留非可空但调整验证逻辑:如果需要字段非空但想自定义验证规则,可显式添加
[Required]特性并配置参数(比如允许空字符串):[Required(AllowEmptyStrings = true)] [StringLength(20, ErrorMessage = "The {0} must be at most {1} characters long.")] [Display(Name = "Phone Number")] public string AlternateContactPhoneNumber { get; set; } = string.Empty; - 关闭全局隐式验证:在
Program.cs中关闭Nullable引用类型的自动验证(不推荐,会失去类型安全提示):builder.Services.AddControllersWithViews(options => { options.ModelMetadataDetailsProviders.RemoveType<RequiredMemberModelMetadataProvider>(); });
内容的提问来源于stack exchange,提问作者Jesus
相关产品推荐
相关产品推荐

