.NET Core 数据验证(最全实战指南)

.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("参数错误");
        }
    }
}

核心总结(必看)

  1. 最简单 :给 DTO 加 [Required][EmailAddress] 等注解
  2. 最方便 :控制器加 [ApiController],自动验证、自动返回错误
  3. 最规范:全局配置统一错误返回格式
  4. 扩展:内置不够用 → 写自定义验证特性

总结:.NET Core 验证 = 数据注解 + 自动校验,零冗余代码!

相关推荐
苍何10 小时前
分享最近高频用 Agent 提效的 4 大场景
后端
Java编程爱好者10 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
后端
XovH10 小时前
Django 从 0 到 1 打造完整电商平台:下单前的准备,订单模型设计
后端
XovH10 小时前
Django 从 0 到 1 打造完整电商平台:确认订单页面与提交订单
后端
Cache技术分享10 小时前
418. 现代 Java IO 最佳实践 - 网络数据获取:从 HttpClient 到图片下载
前端·后端
TYKJ02310 小时前
CDN加速的原理,远不止缓存这么简单
后端·性能优化·图片资源
XovH10 小时前
Django 从 0 到 1 打造完整电商平台:我的订单列表与订单详情
后端
Nyarlathotep011310 小时前
并发集合类(4):PriorityBlockingQueue
java·后端
XovH10 小时前
Django 从 0 到 1 打造完整电商平台:集成支付宝沙箱支付
后端
国思RDIF框架10 小时前
国思 RDIF 低代码快速开发框架 v6.3 版本重磅发布!性能与体验双飞跃
前端·vue.js·后端