C# .NET6 Web API 如何移除模型默认必填验证支持部分字段传参
.NET 6 及以上版本默认启用不可空引用类型的隐式必填校验规则:当项目开启可空引用类型(Nullable)配置后,模型中所有未标记为可空(未追加?声明)的引用类型属性(比如代码里的string类型字段),框架会自动为其添加隐式的[Required]验证规则,无需手动标注验证特性,未传对应字段时就会触发模型验证失败,返回400错误。
按照推荐优先级从高到低排列:
方案1:为密码重置接口定义专用DTO(工程实践最优解)
不同业务接口的参数校验规则存在差异时,不要强行复用同一个数据传输对象,单独定义重置密码场景专用的DTO,仅保留需要的字段,从根源上避免无关字段的校验干扰:public class ResetPasswordRequestDto { public string Email { get; set; } public string Password { get; set; } }对应修改接口入参类型即可,原有业务逻辑无需调整:
[HttpPatch] [Route("/forgotpassword")] public IActionResult ResetPassword(ResetPasswordRequestDto credentials) { if (_authenticationManager.ResetPasword(credentials)) { string success = "Password Has been set succcessfully"; return Ok(DataWrapperService.WrapData(success, true)); } else { string error = "invalid Credentials "; return Unauthorized(DataWrapperService.WrapData(error, false)); } }该方案符合接口隔离设计原则,后续调整单个接口的参数规则时不会影响其他使用原DTO的接口(注册、信息更新),维护成本最低。
方案2:将非必填字段标记为可空引用类型
如果暂时不想拆分DTO,可以把重置密码场景下不需要传递的字段全部标记为可空,框架就不会对这些字段执行隐式必填校验:public class UserCredentialsDto { public string Email { get; set; } public string Password { get; set; } public string? Username { get; set; } public string? Name { get; set; } public string? Usertype { get; set; } public string? Professional { get; set; } public string? SecurityQuestion { get; set; } public string? SecurityAnswer { get; set; } }注意该方案会让所有复用
UserCredentialsDto的接口都默认不校验上述字段的必填性,如果注册、信息更新接口要求这些字段为必填,需要手动为对应场景补充必填校验,容易出现规则遗漏。方案3:全局关闭隐式必填验证(仅建议临时调试使用)
如果不想调整模型定义,可以在Program.cs中配置关闭框架对非可空引用类型的自动必填校验,配置后所有未显式标注[Required]特性的属性都不会触发必填校验:builder.Services.AddControllers() .AddDataAnnotationsValidation(options => { options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true; });该配置全局生效,会导致所有接口的模型默认跳过非空字段的自动校验,大幅提升空值异常的出现概率,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者Srikrishna Sharma

