[required]未生效是因为模型绑定未触发,需用[frombody]等特性让框架接管对象绑定;值类型如int、datetime默认非null,需改用可空类型或range等约束;手动验证须用validator.tryvalidateobject并设validateallproperties:true。

为什么 [Required] 加了却没报错?
因为验证根本没跑起来——[Required] 不是“贴上就生效”的魔法标签,它依赖 ASP.NET Core 的模型绑定流程自动触发。你手动 new User() 再逐个赋值,框架完全不知道你在干啥,ModelState.IsValid 也永远为 true。
必须让参数由框架接管:用 [FromBody]、[FromForm]、[FromQuery] 或路由绑定(如 [Route("api/users/{id}")])接收整个对象。否则所有特性都形同虚设。
- ✅ 正确:
public IActionResult Post([FromBody] UserDto dto)—— 框架自动反序列化 + 校验 - ❌ 错误:
public IActionResult Post() { var dto = new UserDto(); dto.Name = Request.Form["name"]; }—— 验证器压根没机会读属性 - ⚠️ 注意:若 DTO 有私有
set,确保有public get;无 getter 的属性会被跳过
[Required] 对 int 和 DateTime 为啥总通过?
因为它们不是“可空类型”:int 默认是 0,DateTime 默认是 DateTime.MinValue,[Required] 只判断“是否为 null”,对值类型永远返回 true。
想校验数值字段非零或日期被真实传入,得换方式:
- 把字段改成可空类型:
public int? Age { get; set; }+[Required] - 用范围约束代替必填:
[Range(1, 120)](比[Required]更准确) - 日期字段强制传值:
public DateTime? BirthDate { get; set; }+[Required] - 前端传
"age": null,后端仍是int age = 0—— 这是 JSON 反序列化行为,不是验证失效
非 Controller 层怎么手动验证 DTO?
Service、Repository 或工具类里不能依赖 ModelState,得用 Validator.TryValidateObject 主动触发。
示例代码(注意传参顺序和 validateAllProperties 必须为 true):
var context = new ValidationContext(dto); var results = new List<validationresult>(); bool isValid = Validator.TryValidateObject(dto, context, results, validateAllProperties: true);</validationresult>
- 必须传
validateAllProperties: true,否则只校验有值的属性([Required]就失效) -
results包含每个失败项的ErrorMessage和MemberNames(可用于定位字段) - 不支持异步、不支持服务注入——复杂逻辑(如查库校验邀请码)应改用 FluentValidation
EditForm 中 DataAnnotations 不显示错误?
Blazor 的 DataAnnotationsValidator 只负责计算,不负责说话。没看到红字,大概率是漏了两件事:
-
<editform model="@model"></editform>必须显式写Model参数,不能只靠@bind-Value推断 -
<validationmessage for="@(() => model.Email)"></validationmessage>的For必须是表达式树,写成"Email"或@model.Email都无效 - 嵌套属性要写全路径:
@(() => model.Address.Street),不能省略Address -
ValidationSummary默认不显示字段级错误,需加ModelErrorsOnly="false"
最后确认模型类引用了 System.ComponentModel.DataAnnotations,且属性是 public 并含 get。










