.NET Core 内置**强大的模型验证(Model Validation)**机制,基于 DataAnnotations 数据注解 + 自动验证,无需手写大量判断代码,是 API、MVC 项目的标准验证方案。
我给你整理最常用、最实用的用法,直接复制就能用!
一、最核心用法:DataAnnotations 注解(推荐)
直接在模型类 / DTO 上加特性,框架会自动验证,无需手动判断。
1. 常用验证特性(背会这 10 个就够用)
csharp
// 必填
[Required(ErrorMessage = "用户名不能为空")]
// 字符串长度
[StringLength(50, MinimumLength = 2, ErrorMessage = "长度 2-50 位")]
// 范围(数字)
[Range(1, 120, ErrorMessage = "年龄必须在 1-120 之间")]
// 正则表达式(手机号、身份证等)
[RegularExpression(@"^1[3-9]\d{9}$", ErrorMessage = "手机号格式不正确")]
// 邮箱格式
[EmailAddress(ErrorMessage = "邮箱格式不正确")]
// 密码复杂度
[DataType(DataType.Password)]
// 比较两个字段(确认密码)
[Compare("Password", ErrorMessage = "两次密码不一致")]
// 电话号码
[Phone(ErrorMessage = "电话号码格式错误")]
// 最大/最小值
[MaxLength(100)]
[MinLength(6)]
// 自定义错误消息
[Required(ErrorMessage = "请输入姓名")]
二、完整实战示例(DTO + 自动验证)
1. 定义 DTO(带验证)
csharp
using System.ComponentModel.DataAnnotations;
namespace YourProject.DTOs
{
public class CreateUserDto
{
[Required(ErrorMessage = "用户名不能为空")]
[StringLength(20, MinimumLength = 2, ErrorMessage = "用户名长度 2-20 位")]
public string UserName { get; set; }
[Required(ErrorMessage = "密码不能为空")]
[MinLength(6, ErrorMessage = "密码至少 6 位")]
public string Password { get; set; }
[Required(ErrorMessage = "确认密码不能为空")]
[Compare(nameof(Password), ErrorMessage = "两次密码不一致")]
public string ConfirmPassword { get; set; }
[EmailAddress(ErrorMessage = "邮箱格式不正确")]
public string Email { get; set; }
[RegularExpression(@"^1[3-9]\d{9}$", ErrorMessage = "手机号格式错误")]
public string Phone { get; set; }
[Range(1, 120, ErrorMessage = "年龄必须在 1-120 之间")]
public int Age { get; set; }
}
}
三、API 中自动使用验证(无需手写判断)
1. 控制器写法(.NET Core 自动验证)
csharp
using Microsoft.AspNetCore.Mvc;
using YourProject.DTOs;
[Route("api/[controller]")]
[ApiController] // 关键:加了这个,框架会自动验证模型
public class UserController : ControllerBase
{
[HttpPost("create")]
public IActionResult Create(CreateUserDto dto)
{
// 重点:加了 [ApiController],如果验证失败,框架会自动返回 400 错误!
// 这里直接写业务逻辑即可
return Ok("创建成功");
}
}
2. 自动返回的错误格式(前端直接用)
json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"UserName": ["用户名不能为空"],
"Phone": ["手机号格式错误"],
"Age": ["年龄必须在 1-120 之间"]
}
}
四、手动获取验证结果(兼容老项目)
如果没加 [ApiController],可以手动判断:
csharp
[HttpPost("create")]
public IActionResult Create(CreateUserDto dto)
{
// 手动判断验证是否通过
if (!ModelState.IsValid)
{
// 返回验证错误
return BadRequest(ModelState);
}
return Ok("创建成功");
}
五、自定义验证(满足特殊业务规则)
如果内置注解不够用,可以自定义验证特性。
示例:验证"用户名不能包含 admin"
csharp
using System.ComponentModel.DataAnnotations;
public class NoAdminAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
var userName = value?.ToString();
if (userName != null && userName.Contains("admin"))
{
return new ValidationResult("用户名不能包含 admin");
}
return ValidationResult.Success;
}
}
使用:
csharp
[NoAdmin] // 自定义验证
public string UserName { get; set; }
六、全局统一验证返回格式(企业级)
默认的 400 返回格式太丑,我们可以统一成前端友好格式。
在 Program.cs 中配置:
csharp
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
// 自定义验证失败返回结果
options.InvalidModelStateResponseFactory = context =>
{
// 提取所有错误信息
var errors = context.ModelState
.Where(e => e.Value.Errors.Count > 0)
.ToDictionary(
k => k.Key,
v => v.Value.Errors.Select(e => e.ErrorMessage).ToArray()
);
// 统一返回格式
var result = new
{
Code = 400,
Message = "参数验证失败",
Errors = errors
};
return new BadRequestObjectResult(result);
};
});
返回效果:
json
{
"Code": 400,
"Message": "参数验证失败",
"Errors": {
"UserName": ["用户名不能为空"],
"Phone": ["手机号格式错误"]
}
}
七、服务层(Service)验证
如果想在业务层做验证,可以手动调用:
csharp
using System.ComponentModel.DataAnnotations;
public class UserService
{
public void CreateUser(CreateUserDto dto)
{
// 手动验证
var validationContext = new ValidationContext(dto);
var validationResults = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(dto, validationContext, validationResults, true);
if (!isValid)
{
// 处理错误
throw new ArgumentException("参数错误");
}
}
}
核心总结(必看)
- 最简单 :给 DTO 加
[Required]、[EmailAddress]等注解 - 最方便 :控制器加
[ApiController],自动验证、自动返回错误 - 最规范:全局配置统一错误返回格式
- 扩展:内置不够用 → 写自定义验证特性
总结:.NET Core 验证 = 数据注解 + 自动校验,零冗余代码!