Skip to main content

8.Ⅰ 基础使用

📝 模块更新日志
  • 新特性
    •   数据验证模块支持配置属性验证级联模式 4.9.8.25 ⏱️2026.03.23 f50b3d4
    •   数据验证模块 ValidatorResult 类型和验证器 TryValidate 方法 4.9.8.10 ⏱️2026.01.29 fb2c04b
    •   Must.Exception(message) 静态方法,可在 Must 验证器中手动抛出异常 4.9.8.3 ⏱️2026.01.25 809014e
    •   数据验证支持配置级联(组合)验证模式 UseMode(mode) 4.9.8.1 ⏱️2026.01.22 ade659d
  • 突破性变化
    •   数据验证比较验证器抽象基类 4.9.8.40 ⏱️2026.04.14 4870e71
    •   数据验证服务名称:AddValidationCore -> AddCordon 4.9.8.35 ⏱️2026.04.08 9dcdf56
    •   数据验证 DecimalPlaces 验证器为 Decimal(包含验证特性和链式验证) 4.9.8.35 ⏱️2026.04.08 9dcdf56
    •   数据验证模块 UseMode 方法名称为 UseRuleMode 4.9.8.25 ⏱️2026.03.23 f50b3d4
    •   数据验证模块 CompositeMode 枚举名称为 RuleMode 4.9.8.25 ⏱️2026.03.23 f50b3d4
    •   数据验证 ColorValue 验证器为 Color 4.9.8.10 ⏱️2026.01.31 ab9ad35
  • 问题修复
    •   数据验证比较验证器不支持非 int/double 类型比较 4.9.8.40 ⏱️2026.04.14 4870e71
    •   数据验证模块枚举验证器不支持可空枚举类型 4.9.8.14 ⏱️2026.02.06 2b60cbb
    •   数据验证单值验证特性验证器无法同步验证特性错误信息配置问题 4.9.8.1 ⏱️2026.01.22 9f188e8
  • 其他更改
    •   数据验证模块条件验证器及新增智能配置链式条件 4.9.8.23 ⏱️2026.03.15 05fd2a8
    •   数据验证模块枚举验证器和属性比较验证器 4.9.8.8 ⏱️2026.01.27 ea58a8c
    •   数据验证模块验证特性验证器处理逻辑 4.9.8.7 ⏱️2026.01.26 4422649
    •   数据验证模块组合验证器和条件验证器处理逻辑 4.9.8.6 ⏱️2026.01.26 411ec24
    •   数据验证模块验证上下文默认 DisplayName 4.9.8.2 ⏱️2026.01.24 048b11e
4.9.8+ 版本说明

Furion 4.9.8+ 版本采用 Cordon 数据验证替换原有的数据验证查看旧文档

重要说明

以下内容仅适用于 Furion 4.9.8+ 版本,且不支持 .NET8 以下版本。

8.1 数据验证概述

数据验证是指在程序运行过程中,对输入或传输的数据进行合法性与完整性检查,以确保其符合业务规则和系统预期,防止无效、恶意或格式错误的数据进入核心逻辑,保障应用的稳定性与安全性。

8.1.1 应用场景

数据验证在现代应用开发中具有广泛的应用场景,主要包括:

  • Web API 请求校验:自动验证客户端提交的 JSON 或表单数据,拦截非法输入。
  • 用户注册与登录校验:验证邮箱、手机号、密码强度等字段的合法性。
  • 表单提交验证:前后端统一校验逻辑,提升体验与数据一致性。
  • 领域模型状态校验:确保业务对象在变更或持久化前符合规则。
  • 微服务数据契约校验:在服务边界验证输入输出,增强系统健壮性。
  • 批量数据导入校验:对 ExcelCSV 等批量数据逐条验证并汇总错误。
  • 配置参数校验:验证应用配置项的有效性与完整性。
  • 多语言错误提示:按用户语言返回本地化验证错误信息。
  • 动态规则校验:通过特性或配置灵活启停验证逻辑。
  • 异步唯一性校验:如检查用户名或订单号是否已存在。
  • 其他场景:适用于多种其他需要保障数据合法性的业务场景。

通过数据验证,开发者能够有效拦截非法输入、统一校验逻辑、降低系统风险,显著提升开发效率与应用的可维护性。

8.2 快速入门

安装包说明

Furion 框架已内置该功能,无需额外安装 NuGet 包。若使用非 Furion 框架,可通过以下命令安装 CordonCordon.AspNetCore 包:

  • 适用于任何 .NET/C# 应用:
dotnet add package Cordon
  • 适用于 Web 应用(包含 Cordon 且提供规则集功能):
dotnet add package Cordon.AspNetCore

8.2.1 传统验证方式

在软件开发的早期阶段,尤其是在 Web API 和自动化验证机制尚未普及的年代,开发者通常将数据校验逻辑直接写在业务方法的入口处。这种方式看似简单直接,却容易导致校验逻辑与业务逻辑混杂,带来长期维护问题。

以一个用户注册场景为例,常见代码可能如下:

[HttpPost]
public async Task<bool> Register(User user)
{
// 手动校验参数
if (string.IsNullOrWhiteSpace(user.Name))
throw new ArgumentException("姓名不能为空");

if (user.Name.Length < 2)
throw new ArgumentException("姓名不能少于 2 个字符");

if (user.Age < 18)
throw new ArgumentException("年龄不能小于 18 岁");

if (string.IsNullOrWhiteSpace(user.Password))
throw new ArgumentException("密码不能为空");

if (user.Password != user.ConfirmPassword)
throw new ArgumentException("两次输入的密码不一致");

// 执行实际业务
await _repository.InsertAsync(user);
// ...

return true;
}

在小型或原型项目中,这种写法或许勉强可行。但随着模型复杂度增加,问题迅速显现:

  • 职责混杂:校验逻辑嵌入业务方法,违反了单一职责原则;
  • 重复代码:若多个方法需要校验 User,相同的判断逻辑会被到处复制;
  • 维护困难:校验规则分散在各处,修改或扩展时极易遗漏,形成“逻辑碎片”。

久而久之,业务方法不仅变得冗长难读,还难以测试和演进。因此,将校验逻辑硬编码在业务方法中是一种应避免的做法。它污染了核心业务流程,阻碍了验证规则的集中管理和复用,显著增加系统维护成本。

为解决上述问题,更合理的做法是将验证规则与模型本身绑定,使校验逻辑内聚于数据结构,而非散落在业务代码中。

8.2.2 基于特性的验证

与 8.2.1 中将校验逻辑硬编码在业务方法中的做法不同,更合理的方式是将验证规则直接绑定到模型本身。在 .NET 生态中,最常见且标准化的实现手段是使用验证特性——即继承自 ValidationAttribute 的特性类。

通过在模型属性上标注这些特性,支持在不侵入业务代码的前提下,声明式地定义校验规则。验证逻辑由此与模型结构紧密耦合,而与业务流程彻底解耦。

以同样的用户注册场景为例,使用验证特性后的 User 模型如下:

public class User
{
[Required(ErrorMessage = "姓名不能为空"), MinLength(2, ErrorMessage = "姓名不能少于 2 个字符")]
public string? Name { get; set; }

[Min(18, ErrorMessage = "年龄不能小于 18 岁")]
public int Age { get; set; }

[Required(ErrorMessage = "密码不能为空"), Compare(nameof(ConfirmPassword), ErrorMessage = "两次输入的密码不一致")]
public string? Password { get; set; }

public string? ConfirmPassword { get; set; }
}

此时,业务方法不再需要任何手动校验:

[HttpPost]
public async Task<bool> Register(User user) // 在 MVC/WebAPI 应用中实现参数自动校验
{
// 执行实际业务
await _repository.InsertAsync(user);
// ...

return true;
}

ASP.NET 等框架中,当模型作为操作方法参数传入时,验证会自动触发。若规则不满足,请求将在进入业务逻辑前被拦截(通常返回 400 Bad Request),从而避免无效数据污染核心流程。

这种方式有效解决了 8.2.1 中提到的三大问题:

  • 职责分离:验证属于模型契约,业务方法只关注“做什么”;
  • 消除重复:同一模型在任意入口复用相同规则;
  • 集中管理:所有校验逻辑内聚于模型定义,便于维护与演进。

此外,框架在完整支持 .NET 内置验证特性(如 [Required][MinLength][Compare] 等)的基础上,进一步扩展了大量常用验证特性,并允许开发者通过继承 ValidationAttribute 实现自定义验证逻辑,以满足复杂业务场景的需求。

不过,验证特性本质上是静态的、基于属性的声明机制,其表达能力受限于编译时常量与单属性上下文。当验证逻辑涉及跨属性依赖、动态数据源(如数据库查询)、集合元素校验、规则集场景验证或复杂条件组合时,仅靠特性往往难以表达,甚至需要退回到手动判断。

因此,对于超出特性能力边界的验证需求,开发者需要更灵活的机制。

8.2.3 动态验证(自定义验证)

.NET 内置的验证特性(如 [Required][MinLength][Compare])适用于大多数静态、编译时确定的场景。但在实际业务中,验证逻辑常常依赖运行时动态数据——例如跨属性依赖、动态数据源(如数据库查询)或调用远程 HTTP 服务。这类动态需求已超出预定义特性的表达能力。

以“限制用户注册邮箱域名仅限 outlook.comqq.com163.com”为例,开发者通常可通过以下三种方式实现动态验证。

方式一:使用 [CustomValidation] 特性

.NET 提供了 [CustomValidation] 特性,允许将验证逻辑委托给一个符合特定签名的静态方法。该方法需返回 ValidationResult,并接受 object? value 参数,可选地还可包含 ValidationContext 参数。

  1. 定义静态验证方法

创建一个静态类并添加名为 AllowedEmailDomains 的验证方法。类名可任意指定,例如:

public static class CustomValidators
{
private static readonly string[] _allowedDomains = ["@outlook.com", "@qq.com", "@163.com"];

public static ValidationResult? AllowedEmailDomains(object? value, ValidationContext validationContext)
{
if (value is null)
{
return ValidationResult.Success;
}

if (value is not string email)
{
return new ValidationResult("不是有效的邮箱格式。");
}

if (!_allowedDomains.Any(domain => email.EndsWith(domain, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult("仅支持 outlook、qq 和 163 邮箱格式。");
}

return ValidationResult.Success;
}
}
  1. User 类中应用该特性:
public class User
{
// ...

[Required]
[EmailAddress]
[CustomValidation(typeof(CustomValidators), nameof(CustomValidators.AllowedEmailDomains))]
public string? EmailAddress { get; set; }
}

ASP.NET 等框架中,当 User 作为控制器参数传入时,模型绑定会自动触发所有关联的验证逻辑,包括通过 [CustomValidation] 注册的自定义验证方法。

方式二:自定义验证特性

通过继承 ValidationAttribute 并重写 IsValid(object?, ValidationContext) 方法,可将验证逻辑封装为可复用的声明式特性。

  1. 定义 AllowedEmailDomainsAttribute 特性:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AllowedEmailDomainsAttribute : ValidationAttribute
{
private readonly string[] _allowedDomains = ["@outlook.com", "@qq.com", "@163.com"];

/// <inheritdoc />
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
if (value is null)
{
return ValidationResult.Success;
}

if (value is not string email)
{
return new ValidationResult("不是有效的邮箱格式。");
}

if (!_allowedDomains.Any(domain => email.EndsWith(domain, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult("仅支持 outlook、qq 和 163 邮箱格式。");
}

return ValidationResult.Success;
}
}
支持从依赖注入容器中解析所需服务

IsValid 方法中,可通过 validationContext.GetService(serviceType) 从依赖注入容器中解析所需服务(例如配置、数据库上下文或 HTTP 客户端),从而实现依赖外部资源的动态验证逻辑。

  1. User 类中应用该特性:
public class User
{
// ...

[Required]
[EmailAddress]
[AllowedEmailDomains] // 应用自定义验证特性
public string? EmailAddress { get; set; }
}

[CustomValidation] 一样,该特性也会在模型绑定过程中被自动执行。

方式三:实现 IValidatableObject 接口

当验证逻辑涉及多个属性或需要访问模型的完整内部状态时,可让模型实现 IValidatableObject 接口,将验证逻辑内嵌于类型自身:

public class User : IValidatableObject
{
// ...

[Required]
[EmailAddress]
public string? EmailAddress { get; set; }

private readonly string[] _allowedDomains = ["@outlook.com", "@qq.com", "@163.com"];

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (EmailAddress is not null && !_allowedDomains.Any(domain => EmailAddress.EndsWith(domain, StringComparison.OrdinalIgnoreCase)))
{
yield return new ValidationResult("仅支持 outlook、qq 和 163 邮箱格式。", [nameof(EmailAddress)]);
}
}
}

同样,在模型绑定过程中,框架会自动调用 Validate 方法,并将其返回的验证结果与其他特性(如 [Required][EmailAddress])的验证结果合并。

尽管上述方式能表达复杂验证规则,但仍存在明显局限:

  • 逻辑冗长:即使是简单的多值匹配,也需完整的条件判断和 yield return
  • 缺乏组合能力:难以以“与/或/非”方式灵活组合多个验证条件;
  • 可读性下降:规则增多时,Validate 方法易演变为庞杂的条件堆砌;
  • 类型安全性弱:依赖字符串字面量(如 nameof(EmailAddress))标识成员,易引入错误;
  • 复用成本高:验证逻辑与特定模型强耦合,难以跨类型复用。

因此,在需要高度灵活、可组合且支持强类型校验的系统中,上述机制仍显不足。开发者需要一种既能保持验证逻辑内聚,又能以声明式、链式语法表达复杂规则的验证机制。

8.2.4 链式验证 ✨

在 8.2.3 节中,支持通过 IValidatableObject 接口将验证逻辑内聚于模型,并支持从依赖注入容器中获取服务。当验证逻辑涉及多个条件组合、跨属性校验或外部依赖时,仅靠 if 判断和手动返回 ValidationResult 会使 Validate 方法变得冗长且难以维护。

为此,框架提供链式验证机制,允许在 IValidatableObject.Validate 方法内部以声明式、强类型的方式构建验证规则。该机制通过扩展 ValidationContext,支持在不离开 Validate 方法的前提下,使用流畅的链式语法表达复杂逻辑。

例如,用户邮箱域名的校验可改写为:

public class User : IValidatableObject
{
// ...

[Required]
[EmailAddress]
public string? EmailAddress { get; set; }

/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
.RuleFor(u => u.EmailAddress)
.MustAny(["@outlook.com", "@qq.com", "@163.com"], (email, domain) => email.EndsWith(domain, StringComparison.OrdinalIgnoreCase))
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。")
.ToResults();
}
}

在此示例中:

  • With<User>() 从当前 ValidationContext 启动针对 User 的链式验证上下文;
  • RuleFor(u => u.EmailAddress) 开始为 EmailAddress 属性定义验证规则链
  • MustAny(...) 是一个自定义验证规则,它对传入的值与多个候选项(如域名列表)逐一调用指定的匹配逻辑,只要任意一项匹配即视为通过;
  • WithMessage(...) 为前一个验证器(此处是 MustAny)设置错误信息
  • ToResults() 将规则执行结果转换为 IEnumerable<ValidationResult>,以满足 IValidatableObject 接口要求。

该写法具有以下优势:

  • 强类型安全u => u.EmailAddress 在编译时验证属性存在性与类型;
  • 逻辑内聚:复杂校验封装于单条链,避免多个 if 分支;
  • 可复用性强:自定义验证逻辑(如 MustAny 中的委托)可复用于其他属性或模型;
  • 易于扩展:支持链式追加 WhenPreProcess 等条件或预处理操作;
  • 与特性验证共存[Required][EmailAddress] 仍生效,框架自动合并所有验证结果。

此外,为提升代码可维护性和可复用性,可将匹配逻辑封装为独立的方法:

public class User : IValidatableObject
{
// ...

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
.RuleFor(u => u.EmailAddress)
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。")
.ToResults();
}

private static bool CheckEmailAddress(string email, string domain)
{
return email.EndsWith(domain, StringComparison.OrdinalIgnoreCase);
}
}

独立验证器类

对于复杂、需复用,或需作用于第三方/不可修改类型(如 DTOPOCO)的验证逻辑,可将其封装在独立于模型的验证器类中:继承 AbstractValidator<T>,在构造函数中声明规则链。此类验证器与模型无强耦合,天然支持多场景复用。

首先,定义验证器类:

public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(u => u.EmailAddress)
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。");
}

private static bool CheckEmailAddress(string email, string domain)
{
return email.EndsWith(domain, StringComparison.OrdinalIgnoreCase);
}
}

随后,可在多种场景中使用该验证器:

  1. 在模型中通过 IValidatableObject 集成
public class User : IValidatableObject
{
// ...

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.ValidateWith<UserValidator>();
}
}
  1. 手动实例化调用
public async Task Add(User user)
{
var userValidator = new UserValidator();

// 执行验证
userValidator.Validate(user);

// 其他业务逻辑
}
  1. 通过依赖注入在服务中使用
public class UserService
{
private readonly UserValidator _userValidator;

public UserService(UserValidator userValidator)
{
_userValidator = userValidator;
}

public async Task Add(User user)
{
// 执行验证
_userValidator.Validate(user);

// 其他业务逻辑
}
}
  1. 通过特性绑定到操作方法参数

可使用 [ValidateWith<TValidator>] 特性,将验证器绑定到控制器操作的参数:

[ApiController]
[Route("[controller]/[action]")]
public class UserController
{
[HttpPost]
public Task Create([ValidateWith<UserValidator>] User user)
{
return Task.CompletedTask;
}
}
  1. 在验证器中注入服务(如本地化资源)

验证器构造函数支持依赖注入,例如注入 IStringLocalizer<T> 实现多语言:

public class UserValidator : AbstractValidator<User>
{
public UserValidator(IStringLocalizer<UserValidator> localizer)
{
RuleFor(u => u.EmailAddress)
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage(localizer["AllowedEmailDomains_ErrorMessage"]);
}

private static bool CheckEmailAddress(string email, string domain)
{
return email.EndsWith(domain, StringComparison.OrdinalIgnoreCase);
}
}

此类验证器不依赖模型定义,具有高度解耦性:

  • 可用于 IValidatableObject 的自动验证;
  • 也可通过依赖注入或手动实例化,在服务层、API 控制器或单元测试中直接调用,对任意 User 实例执行验证。
    这种设计显著提升了验证逻辑的复用性可测试性
启用依赖注入服务支持

以上操作需确保验证器已注册到服务容器:

services.AddCordon(builder =>
{
builder.AddValidator(typeof(UserValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});

或在 ASP.NET 应用中:

services.AddControllers()
.AddCordon(builder =>
{
builder.AddValidator(typeof(UserValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});

提供与验证特性对等的链式规则

框架为链式验证提供了与 .NET 内置验证特性(如 [Required][EmailAddress]功能对等的强类型方法(例如 .Required().EmailAddress()),因此无需依赖验证特性即可完整表达所有验证逻辑。同时,若模型仍保留验证特性,框架会自动合并特性验证与链式规则的执行结果,确保所有约束均被检查。

以下示例展示了如何仅通过链式规则,完整实现 User 模型的所有验证逻辑,无需使用任何验证特性:

public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(u => u.Name)
.Required().WithMessage("姓名不能为空")
.MinLength(2).WithMessage("姓名不能少于 2 个字符");

RuleFor(u => u.Age)
.Min(18).WithMessage("年龄不能小于 18 岁");

RuleFor(u => u.Password)
.Required().WithMessage("密码不能为空")
.Compare(u => u.ConfirmPassword).WithMessage("两次输入的密码不一致");

RuleFor(u => u.EmailAddress)
.Required()
.EmailAddress()
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。");
}

private static bool CheckEmailAddress(string email, string domain)
{
return email.EndsWith(domain, StringComparison.OrdinalIgnoreCase);
}
}
添加未内置的验证特性链式支持

对于框架尚未内置或自定义的验证特性,可通过 .WithAttributes(params ValidationAttribute[]) 方法将其融入链式验证,例如:

RuleFor(u => u.EmailAddress)
.WithAttributes(new AllowedEmailDomainsAttribute()); // 支持传入多个特性实例
支持连续链式调用

虽然上述写法按属性分段,更利于阅读和维护,但若偏好紧凑风格,也可连续链式书写:

RuleFor(u => u.Name)
.Required().WithMessage("姓名不能为空")
.MinLength(2).WithMessage("姓名不能少于 2 个字符")
.RuleFor(u => u.Age)
.Min(18).WithMessage("年龄不能小于 18 岁")
.RuleFor(u => u.Password)
.Required().WithMessage("密码不能为空")
.Compare(u => u.ConfirmPassword).WithMessage("两次输入的密码不一致")
.RuleFor(u => u.EmailAddress)
.Required()
.EmailAddress()
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。");

同样的验证逻辑也可直接在模型的 IValidatableObject.Validate 方法中以链式语法编写,无需引入独立验证器类:

public class User : IValidatableObject
{
// ...

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
.RuleFor(u => u.Name)
.Required().WithMessage("姓名不能为空")
.MinLength(2).WithMessage("姓名不能少于 2 个字符")
.RuleFor(u => u.Age)
.Min(18).WithMessage("年龄不能小于 18 岁")
.RuleFor(u => u.Password)
.Required().WithMessage("密码不能为空")
.Compare(u => u.ConfirmPassword).WithMessage("两次输入的密码不一致")
.RuleFor(u => u.EmailAddress)
.Required()
.EmailAddress()
.MustAny(["@outlook.com", "@qq.com", "@163.com"], CheckEmailAddress)
.WithMessage("仅支持 outlook、qq 和 163 邮箱格式。")
.ToResults();
}

private static bool CheckEmailAddress(string email, string domain)
{
return email.EndsWith(domain, StringComparison.OrdinalIgnoreCase);
}
}

适用场景建议

链式验证尤其适合以下情形:

  • .NET 原生验证特性(如 [Required])表达能力不足;
  • 需为第三方或不可修改的类型(如 DTOPOCO)附加验证逻辑;
  • 验证规则依赖外部服务(如配置、数据库或 HTTP 客户端);
  • 验证逻辑需在多层架构(如应用层、API 层、测试层)中复用。

通过声明式、强类型的链式语法,链式验证有效减少样板代码,特别适合表达组合式、跨属性或依赖运行时数据的业务规则。

8.2.5 嵌套对象与集合验证

在实际业务中,用户提交的数据通常由多个关联模型组成——例如注册时包含家庭住址、多段工作经历或多个兴趣爱好。这类结构天然涉及 嵌套对象(如 Address)和 集合类型(如 List<WorkExperience>List<string>)的验证。

以如下模型为例:

public class Address
{
public string? City { get; set; }
public string? Street { get; set; }
}

public class WorkExperience
{
public string? Company { get; set; }
public string? Position { get; set; }
public int Years { get; set; }
}

public class User
{
public string? Name { get; set; }
public int Age { get; set; }
public Address? Address { get; set; }
public List<WorkExperience>? WorkExperiences { get; set; }
public List<string>? Hobbies { get; set; }
}

框架通过统一的链式 API 支持对不同结构配置验证规则:

  • 普通属性与嵌套对象(如 NameAgeAddress)使用 RuleFor(...) 定义验证规则链(如 .Required().MinLength(3))。
  • 嵌套对象的内部属性:在 RuleFor(...) 后调用 .ChildRules(...),可深入配置其子属性的验证规则。
  • 集合属性(如 WorkExperiencesHobbies)使用 RuleForCollection(...) 定义集合级约束(如 .MaxLength(5)),并支持进一步细化元素验证:
    • 若元素为 引用类型(如 WorkExperience不包括 string),可通过 .ChildRules(...) 配置其内部属性;
    • 若需对 任意类型 的元素(包括值类型、字符串或引用类型)逐个应用验证,则使用 .EachRules(...)
集合元素验证规则说明

对同一集合属性,.ChildRules(...).EachRules(...) 互斥,不可同时使用。应根据元素类型及验证需求择一配置。

验证规则的组织方式

框架支持以下两种验证规则配置范式:

1. 聚合根集中配置(适用于简单场景)

将全部验证逻辑(包括嵌套对象和集合元素的内部规则)集中定义在顶层模型(如 User)中:

public class User : IValidatableObject
{
public string? Name { get; set; }
public int Age { get; set; }
public Address? Address { get; set; }
public List<WorkExperience>? WorkExperiences { get; set; }
public List<string>? Hobbies { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
.RuleFor(u => u.Name).Required().MinLength(3)
.RuleFor(u => u.Age).Age(true)
.RuleFor(u => u.Address).Required().ChildRules(addr =>
{
addr.RuleFor(a => a.City).Required()
.RuleFor(a => a.Street).Required();
})
.RuleForCollection(u => u.WorkExperiences).MaxLength(5).ChildRules(exp =>
{
exp.RuleFor(e => e.Company).Required()
.RuleFor(e => e.Position).Required()
.RuleFor(e => e.Years).Range(1900, 2026);
})
.RuleForCollection(u => u.Hobbies).EachRules(h => h.Required().MinLength(2))
.ToResults();
}
}

优点

  • 逻辑集中,适合快速原型或一次性验证。

局限性

  • 子模型(如 AddressWorkExperience)无法独立复用其验证规则;
  • 在其他上下文(如独立 API 参数、批量导入)中使用时,内部规则不会自动生效,易引发数据不一致。
空值处理行为

若未显式要求 AddressWorkExperiencesHobbies 非空(如未调用 .Required().NotNull().NotEmpty()),则当其值为 null 或空集合时,内部验证规则将被跳过,整体视为验证通过。

2. 模型自治 + 聚合根协调(推荐)

采用 “模型自治” 策略:每个模型负责自身验证逻辑,聚合根仅关注结构层面的约束(如非空性、集合长度),不侵入子对象内部细节。

public class Address : IValidatableObject
{
public string? City { get; set; }
public string? Street { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<Address>()
.RuleFor(a => a.City).Required()
.RuleFor(a => a.Street).Required()
.ToResults();
}
}

public class WorkExperience : IValidatableObject
{
public string? Company { get; set; }
public string? Position { get; set; }
public int Years { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<WorkExperience>()
.RuleFor(w => w.Company).Required()
.RuleFor(w => w.Position).Required()
.RuleFor(w => w.Years).Range(1900, 2026)
.ToResults();
}
}

public class User : IValidatableObject
{
public string? Name { get; set; }
public int Age { get; set; }
public Address? Address { get; set; }
public List<WorkExperience>? WorkExperiences { get; set; }
public List<string>? Hobbies { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
.RuleFor(u => u.Name).Required().MinLength(3)
.RuleFor(u => u.Age).Age(true)
.RuleFor(u => u.Address).Required()
.RuleForCollection(u => u.WorkExperiences).MaxLength(5)
.RuleForCollection(u => u.Hobbies).EachRules(h => h.Required().MinLength(2))
.ToResults();
}
}

优势

  • 验证契约完整且可复用:无论作为独立对象还是嵌套成员,模型的规则始终生效;
  • 职责清晰、低耦合:子模型不依赖聚合根,聚合根不承担内部校验;
  • 天然支持多场景复用:如单独校验地址、批量处理履历、跨 API 共享模型等。

借助 RuleFor(...)RuleForCollection(...).ChildRules(...).EachRules(...) 的组合,框架提供了类型安全、链式流畅的 API,可表达任意深度的嵌套对象与集合验证逻辑。

推荐实践

在大多数项目中,应优先采用 “模型自治” 策略。这是构建健壮、可维护、可复用验证体系的核心原则。仅在简单场景或快速原型开发中,可考虑聚合根集中配置。

8.2.6 主动验证与依赖注入

ASP.NET 应用中,控制器操作方法通常会自动执行模型验证(基于 ModelState),前提是模型使用了验证特性(如 [Required])或实现了 IValidatableObject 接口。不过,在业务层、领域服务、仓储层等非控制器组件中,并无自动验证机制。此时,必须显式调用验证逻辑以确保数据完整性。

框架为此提供了灵活的主动验证能力,支持依赖注入与非依赖注入两种场景。

方式一:通过依赖注入使用 IValidationService(推荐)

若应用支持依赖注入,可通过 IValidationService 执行验证。

1. 注册服务

在使用前,需在 Program.cs(或 Startup.cs)中注册验证服务:

// 在 Startup.cs 中:
services.AddCordon();

// 在 Program.cs 中:
// builder.Services.AddCordon();

2. 注入验证服务

在服务类中注入 IValidationService

public class UserService
{
private readonly IValidationService _validationService;

public UserService(IValidationService validationService)
{
_validationService = validationService;
}
}

.NET 8 及以上版本中,可使用 主构造函数 简化代码:

public class UserService(IValidationService validationService)
{
// 直接使用 validationService
}

也可在方法参数中按需注入:

public class UserService
{
public Task<string> Create([FromServices] IValidationService validationService, User user)
{
// 验证逻辑
}
}

3. 执行验证

注入后,可通过以下方式执行验证:

// 检查对象是否有效
var isValid = validationService.IsValid(user);

// 获取验证结果(不抛异常)
var validationResults = validationService.GetValidationResults(user);

// 验证失败时抛出 ValidationException
validationService.Validate(user);

4. 多模型验证

当一个操作涉及多个模型时,可一次性验证多个对象:

public class OrderService(IValidationService validationService)
{
public void Process(User user, Order order)
{
// 验证多个对象,任一失败即抛出异常
validationService.Validate([user, order]);
}
}

方式二:在非依赖注入环境中使用

在控制台应用、单元测试或静态上下文中,可采用以下方式:

1. 使用静态工厂获取服务实例

var validationService = Validators.Service();

var isValid = validationService.IsValid(user);
var validationResults = validationService.GetValidationResults(user);
validationService.Validate(user);

2. 手动创建验证服务实例

var validationService = new ValidationService();

// 同上使用

3. 直接使用底层验证器

var validator = Validators.AttributeObject(); // 或 new AttributeObjectValidator()

var isValid = validator.IsValid(user, null);
var validationResults = validator.GetValidationResults(user, null);
validator.Validate(user, null);

4. 使用 .NET 内置 Validator

var validationContext = new ValidationContext(user);
var validationResults = new List<ValidationResult>();

// 验证所有属性(包括嵌套对象需传 true)
var isValid = Validator.TryValidateObject(user, validationContext, validationResults, validateAllProperties: true);

// 抛异常版本
Validator.ValidateObject(user, validationContext, validateAllProperties: true);

总结

框架的验证机制具备良好的跨层适应能力

  • 业务层、领域服务、仓储层等非控制器组件中,推荐通过 IValidationService 主动验证,确保模型完整性与业务规则一致性;
  • 无依赖注入环境(如控制台程序、测试代码)中,仍可通过静态工厂、手动实例化等方式实现同等验证能力。

由此,验证逻辑可贯穿整个应用架构,不再局限于控制器层,从而保障数据一致性与业务规则的全局统一执行。

8.2.7 单值链式验证

除了对象级验证,许多场景还需要对单值(如字符串、整数、枚举或集合等)进行独立校验。框架不仅内置了丰富的单值验证器,还支持与对象验证一致的链式规则定义方式。

以下是框架提供的几种单值验证方式:

1. 使用专用验证器

框架为常见场景提供了以 Validator 结尾的专用验证器。例如,验证电子邮件地址:

// 待验证的值
var value = "support#furion.net";

// 创建验证器实例
var validator = new EmailAddressValidator();

// 检查值是否有效
var isValid = validator.IsValid(value);

// 获取验证结果(不抛异常)
var validationResults = validator.GetValidationResults(value, "Value");

// 验证失败时抛出 ValidationException
validator.Validate(value, "Value");

其中 "Value" 是该值在验证上下文中的显示名称,用于错误信息标识。

如需自定义错误信息,可通过 .WithMessage() 设置:

var validator = new EmailAddressValidator().WithMessage("这不是一个有效的电子邮箱");

2. 使用 Validators 静态类

为简化实例创建,框架提供 Validators 静态工厂类,可直接获取预配置的验证器:

var validator = Validators.EmailAddress();

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "Value");
validator.Validate(value, "Value");

同样支持自定义信息:

var validator = Validators.EmailAddress().WithMessage("这不是一个有效的电子邮箱");

所有内置验证器均可通过 Validators 快速初始化,避免手动 new,同时行为与直接实例化完全一致。

3. 链式验证(推荐)

对于需要组合多个规则的场景,推荐使用链式语法。可通过 ValueValidator<T> 构建复合验证逻辑:

var validator = new ValueValidator<string>()
.Required()
.EmailAddress().WithMessage("这不是一个有效的电子邮箱")
.MinLength(10)
.WithName("Value"); // 验证上下文中的显示名称(可选)

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value);
validator.Validate(value);

也可通过 Validators 静态工厂进一步简化:

var validator = Validators.Value<string>()
.Required()
.EmailAddress().WithMessage("这不是一个有效的电子邮箱")
.MinLength(10)
.WithName("Value");

链式写法语义清晰、易于扩展,天然支持规则复用与信息定制。

为进一步提升可维护性与复用性,还可将规则封装在独立的值验证器类中:通过继承 AbstractValueValidator<T>,将验证逻辑集中定义于构造函数中。这种方式不仅支持依赖注入和生命周期管理,还能在多个场景(如 API 参数、服务层、测试)中复用同一套验证契约。

public class EmailValidator : AbstractValueValidator<string>
{
public EmailValidator()
{
Rule()
.Required()
.EmailAddress().WithMessage("这不是一个有效的电子邮箱")
.MinLength(10)
.WithName("Value");
}
}

该验证器可通过依赖注入或手动实例化,在服务层、API 控制器或单元测试中直接调用,对任意字符串执行验证。

启用依赖注入服务支持

若需通过依赖注入使用值验证器,请确保将其注册到服务容器:

services.AddCordon(builder =>
{
builder.AddValidator(typeof(EmailValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});

或在 ASP.NET 应用中:

services.AddControllers()
.AddCordon(builder =>
{
builder.AddValidator(typeof(EmailValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});

4. 在控制器参数上使用验证特性

ASP.NET 应用中,也可直接在操作方法参数上使用验证特性。框架在 .NET 内置特性的基础上,扩展了更多实用特性:

[ApiController]
[Route("[controller]/[action]")]
public class UserController
{
[HttpPost]
public string GetEmailAddress([Required, EmailAddress] string value)
{
return value;
}
}

自定义错误信息可通过 ErrorMessage 属性设置:

[HttpPost]
public string GetEmailAddress([Required, EmailAddress(ErrorMessage = "这不是一个有效的电子邮箱")] string value)
{
return value;
}

此外,还可使用 [ValidateWith<TValidator>] 将自定义值验证器绑定到参数:

[ApiController]
[Route("[controller]/[action]")]
public class UserController
{
[HttpPost]
public void UpdateName([ValidateWith<NameValidator>] string name)
{
}
}

public class NameValidator : AbstractValueValidator<string>
{
public NameValidator()
{
Rule().Required().MinLength(3);
}
}

当请求参数不符合规则时,框架会自动拦截请求并返回验证错误,实现声明式校验。

通过上述方式,无论是在业务逻辑中显式调用,还是在控制器中声明使用,框架均能以统一、灵活、强类型的方式完成单值验证。

8.2.8 在 ASP.NET 应用中使用

数据验证可与 ASP.NET 应用无缝集成,支持运行时配置验证选项(如规则集)以及验证服务的依赖注入。

要在 ASP.NET 应用中启用上述功能,请完成以下配置:

独立库说明

Furion 框架已内置该功能,无需额外安装 NuGet 包。若您使用 Cordon 独立库,请安装 Cordon.AspNetCore 以替代 Cordon

Startup.csProgram.cs 中注册验证服务:

services.AddControllers()
.AddCordon(); // 或进行更多配置:.AddCordon(builder => {});

1. 在 ASP.NET MVC / Web API 中的应用

在控制器或操作方法上,可通过 [ValidationOptions] 特性指定运行时验证选项(如规则集):

[ApiController]
[Route("[controller]/[action]")]
[ValidationOptions(["*"])] // 控制器级别:应用所有规则集
public class UserController
{
[HttpPost] // 自动继承控制器的规则集配置
public Task Create(User user)
{
return Task.CompletedTask;
}

[HttpPost]
[ValidationOptions(["modify", "set-password"])] // 操作方法级别:覆盖控制器配置
public Task Update(User user)
{
return Task.CompletedTask;
}
}

验证选项将自动传递给主验证器及所有嵌套验证器,确保规则集在整个验证链中生效。

2. 在 ASP.NET Razor Pages 中的应用

Razor Pages 同样支持在页面模型或处理方法上使用 [ValidationOptions]

[ValidationOptions(["*"])] // 页面模型级别
public class UserModel : PageModel
{
public void OnGet()
{
}

[ValidationOptions(["modify", "set-password"])] // 处理方法级别,覆盖页面模型配置
public void OnPost()
{
}
}

通过这种方式,验证规则可根据具体请求上下文动态应用,实现灵活、精准的控制。

除了运行时验证选项,框架还支持 IValidationService 主动验证服务(详见 8.2.6 节)以及独立验证器的依赖注入。

例如:

  1. 定义对象验证器
public class UserValidator : AbstractValidator<User>
{
public UserValidator() // 支持注入其他服务,如 IStringLocalizer<UserValidator>
{
RuleFor(u => u.Name)
.Required().WithMessage("姓名不能为空")
.MinLength(2).WithMessage("姓名不能少于 2 个字符");
}
}
  1. 注册验证器
services.AddControllers()
.AddCordon(builder =>
{
builder.AddValidator(typeof(UserValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});
  1. 通过依赖注入使用
public class UserService
{
private readonly UserValidator _userValidator;

public UserService(UserValidator userValidator)
{
_userValidator = userValidator;
}

public async Task Add(User user)
{
// 执行验证
_userValidator.Validate(user);

// 其他业务逻辑
}
}

此机制使验证逻辑既可声明式集成于请求管道,也可在业务层中显式调用,全面覆盖各类应用场景。

单值验证器

上述依赖注入机制同样适用于单值验证器,即继承自 AbstractValueValidator<T> 的验证器。

8.2.9 规则集(场景化验证)

在实际业务中,同一模型常需在不同场景下执行不同的验证逻辑。例如:

  • 用户注册:需验证用户名、邮箱及新密码与确认密码的一致性;
  • 修改密码:仅校验旧密码和新密码的合法性;
  • 更新资料:可能同时涉及用户名、邮箱、旧密码和新密码的验证。

为支持这种灵活性,验证框架提供了 规则集(Rule Set) 机制:允许在同一个验证器中按命名分组定义多套验证规则,并在运行时根据业务场景动态启用所需规则集。

定义规则集

通过 RuleSet 方法,可在验证器中声明一个命名规则集。其配置委托内使用标准链式规则(如 RuleFor)定义该场景下的验证逻辑。

方式一:在 IValidatableObject 中定义
public class User : IValidatableObject
{
// ...

/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return validationContext.With<User>()
// 默认规则集(通配符 '*')
.RuleFor(u => u.Name).Required().MinLength(3).UserName()
.RuleFor(u => u.EmailAddress).Required().EmailAddress()
// 密码设置规则集
.RuleSet("set-password", v => // 支持配置多个规则集 ["*", "set-password"]
{
v.RuleFor(u => u.Password).Required().StrongPassword().Compare(u => u.ConfirmPassword);
})
// 修改密码规则集
.RuleSet("modify-password", v =>
{
v.RuleFor(u => u.OldPassword).Required().StrongPassword();
})
.ToResults();
}
}
方式二:在独立验证器类中定义

对于复杂逻辑、需复用的验证,或需为不可修改类型(如 DTOPOCO)附加验证,推荐使用独立验证器类:

public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
// 默认规则集(通配符 '*')
RuleFor(u => u.Name).Required().MinLength(3).UserName();
RuleFor(u => u.EmailAddress).Required().EmailAddress();

// 密码设置规则集
RuleSet("set-password", () => // 支持配置多个规则集 ["*", "set-password"]
{
RuleFor(u => u.Password).Required().StrongPassword().Compare(u => u.ConfirmPassword);
});

// 修改密码规则集
RuleSet("modify-password", () =>
{
RuleFor(u => u.OldPassword).Required().StrongPassword();
});
}
}

规则集组合:验证时可传入多个规则集名称,框架将合并所有匹配规则执行验证。

  • 用户注册:["*", "set-password"]
  • 修改密码:["modify-password", "set-password"]
  • 更新用户资料:["*", "modify-password", "set-password"]

其中 "*" 是保留名称,代表默认规则集,包含所有未被 RuleSet 显式包裹的规则。

在控制器中指定规则集

ASP.NET 应用中,可通过 [ValidationOptions] 特性声明当前操作应激活的规则集:

[ApiController]
[Route("[controller]/[action]")]
public class UserController
{
[HttpPost]
[ValidationOptions(["*", "set-password"])]
public Task Create(User user)
{
return Task.CompletedTask;
}

[HttpPost]
[ValidationOptions(["modify-password", "set-password"])]
public Task UpdatePassword(User user)
{
return Task.CompletedTask;
}

[HttpPost]
[ValidationOptions(["*", "modify-password", "set-password"])]
public Task Update(User user)
{
return Task.CompletedTask;
}
}

单值验证器中的规则集

单值验证器同样支持规则集,只需配合 [ValidateWith<TValidator>][ValidationOptions] 使用:

public class AccountValidator : AbstractValueValidator<string>
{
public AccountValidator()
{
Rule().Required().EmailAddress();

RuleSet("login", () =>
{
Rule().Required().Composite(u => u.UserName().EmailAddress(), CompositeMode.Any);
});
}
}
[ApiController]
[Route("[controller]/[action]")]
public class AuthController
{
[HttpPost]
[ValidationOptions(["login"])]
public void Login([ValidateWith<AccountValidator>] string account)
{
// 仅应用 "login" 规则集
}
}
在 [ValidateWith] 中指定规则集

也可以直接在 [ValidateWith] 特性中指定规则集:

[ValidateWith<AccountValidator>(RuleSets = ["login"])]

若同时使用了 [ValidationOptions][ValidateWith] 指定规则集,[ValidateWith] 的规则集优先级更高,将覆盖 [ValidationOptions] 中的设置。

确保数据验证服务已注册

要在 ASP.NET 应用中使用上述功能,请确保完成以下配置:

services.AddControllers()
.AddCordon(); // 或进行更多配置:.AddCordon(builder => {});

设计建议

尽管规则集提供了灵活的场景化验证能力,更推荐的做法是为不同业务操作定义专用的输入模型(如 RegisterUserDtoChangePasswordDto),以显式表达各操作的数据契约,降低模型间的耦合。

规则集更适合以下场景:

  • 多个操作确实共享同一输入模型;
  • 验证逻辑高度重叠,且希望通过组合避免重复定义。

对于跨模型、跨业务的通用验证逻辑(如密码强度、手机号格式等),应将其封装为可复用的自定义验证器扩展方法。相关内容将在后续章节详细说明。

8.2.10 链式验证器继承与组合

文档编写中......

8.2.11 验证错误信息本地化(多语言)

在国际化应用中,验证错误信息应能根据用户的语言环境动态呈现,以提供一致且友好的体验。框架全面支持多语言验证错误信息,既兼容 .NET 原生的 IStringLocalizer<T> 机制,也允许通过自定义资源管理器或外部服务灵活实现本地化策略。

在使用本地化之前,请确保已注册以下服务:

services.AddLocalization(); // 本地化服务
services.AddControllers()
.AddDataAnnotationsLocalization(); // 验证特性本地化服务
关于数据验证服务

框架通过 .AddCordon() 默认启用了本地化支持(已自动注册 AddLocalization()AddDataAnnotationsLocalization()),同时也允许外部自定义覆盖相关配置。

验证特性的本地化方式

对于基于 ValidationAttribute 的内置验证特性(如 [Required][EmailAddress])以及自定义验证特性,.NET 提供了多种本地化支持方式:

方式一:使用 ErrorMessage 属性(隐式资源查找)
public class User
{
[Required(ErrorMessage = "姓名不能为空")]
[MinLength(2, ErrorMessage = "姓名不能少于 2 个字符")]
public string? Name { get; set; }
}

当使用 ErrorMessage 时,运行时将自动查找与目标类同目录下的资源文件。例如,假设:

  • 程序集(项目)名称:MyProject.Samples
  • 类完整命名空间:MyProject.Samples.Models
  • 类名:User

在这种情况下,运行时将查找名为 Models.User.[culture].resx 的资源文件,而不是包含程序集名称的完整路径。实际查找路径示例

Models.User.zh-Hans.resx
Models.User.resx

若在支持依赖注入的环境中注册了本地化服务并设置了 ResourcesPath

services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});

则会在 Resources 文件夹下查找相应文件:

Resources/Models.User.zh-Hans.resx
Resources/Models.User.resx
在 Furion 框架中

若使用 Furion 框架,默认会从 Resources 目录下加载名为 Lang.[culture].resx 的资源文件。

方式二:使用 ErrorMessageResourceTypeErrorMessageResourceName

通过 ErrorMessageResourceTypeErrorMessageResourceName 显式指定自定义的嵌入资源文件:

public class User
{
[Required(ErrorMessage = "姓名不能为空")]
[MinLength(2, ErrorMessageResourceType = typeof(YourValidationMessages), ErrorMessageResourceName = "MinLengthAttribute_ValidationError")]
public string? Name { get; set; }
}

此时,运行时将从 YourValidationMessages.[culture].resx 中读取键为 MinLengthAttribute_ValidationError 的本地化字符串。

注意事项

ErrorMessageErrorMessageResourceTypeErrorMessageResourceName 组合不可同时使用。

方式三:在自定义验证特性中动态获取本地化文本

如 8.2.3 节所示,可在 IsValid 方法中通过 validationContext.GetService<IStringLocalizer<T>>() 获取本地化字符串:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AllowedEmailDomainsAttribute : ValidationAttribute
{
private readonly string[] _allowedDomains = ["@outlook.com", "@qq.com", "@163.com"];

/// <inheritdoc />
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
if (value is null)
{
return ValidationResult.Success;
}

// 解析字符串本地化服务
var localizer = validationContext.GetService<IStringLocalizer<User>>();

if (value is not string email)
{
return new ValidationResult(localizer?["不是有效的邮箱格式。"] ?? "不是有效的邮箱格式。");
}

if (!_allowedDomains.Any(domain => email.EndsWith(domain, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult(localizer?["仅支持 outlook、qq 和 163 邮箱格式。"] ?? "仅支持 outlook、qq 和 163 邮箱格式。");
}

return ValidationResult.Success;
}
}
简化验证错误信息回退逻辑

为避免 localizernull 时重复编写回退逻辑,框架为 IStringLocalizer 提供了 GetString(name) 扩展方法:

return new ValidationResult(localizer.GetString("不是有效的邮箱格式。"));
return new ValidationResult(localizer.GetString("仅支持 outlook、qq 和 163 邮箱格式。"));

localizer 为空时,该方法将直接返回参数字符串。

验证器或链式验证中的本地化方式

在框架提供的验证器或链式验证规则中,同样支持本地化操作。

方式一:在 IValidatableObject 中使用本地化
public class User : IValidatableObject
{
public string? Name { get; set; }

/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// 解析字符串本地化服务
var localizer = validationContext.GetService<IStringLocalizer<User>>();

return validationContext.With<User>()
.RuleFor(u => u.Name)
.Required().WithMessage(localizer.GetString("姓名不能为空"))
.MinLength(2).WithMessage(localizer.GetString("姓名不能少于 2 个字符"))
.ToResults();
}
}
GetString(name) 扩展方法

GetString(name) 是框架提供的扩展方法,用于避免在 localizernull 时重复编写回退逻辑。

ASP.NET 环境中,可直接使用索引器语法,例如:localizer["姓名不能为空"]

方式二:在独立验证器中使用本地化

在独立验证器中,可通过构造函数直接注入 IStringLocalizer<T> 服务:

public class UserValidator : AbstractValidator<User>
{
public UserValidator(IStringLocalizer<User> localizer)
{
RuleFor(u => u.Name)
.Required().WithMessage(localizer["姓名不能为空"])
.MinLength(2).WithMessage(localizer["姓名不能少于 2 个字符"]);
}
}
启用依赖注入服务支持

以上操作需确保验证器已注册到服务容器:

services.AddCordon(builder =>
{
builder.AddValidator(typeof(UserValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});

或在 ASP.NET 应用中:

services.AddControllers()
.AddCordon(builder =>
{
builder.AddValidator(typeof(UserValidator));
// 或扫描程序集自动注册
// builder.AddValidatorsFromAssemblies([assembly1, assembly2, ..]);
});
方式三:WithMessage 方法支持资源类型

框架在验证器中提供了 WithMessage 的重载方法,可显式指定用于本地化信息的资源类型。

RuleFor(u => u.Name).MinLength(2)
.WithMessage(typeof(YourValidationMessages), "MinLengthAttribute_ValidationError");

这种方式允许您直接引用已定义的资源类型,简化了本地化资源的调用流程。

全局默认验证错误信息的本地化替换

.NET 内置验证特性及框架提供的验证特性默认仅提供英文验证错误信息。为避免在非英文环境中反复设置 ErrorMessage,可通过以下方式统一替换默认验证错误信息:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
// 替换 .NET 内置验证特性的默认验证错误信息
builder.ConfigureDataAnnotationValidationMessages(message =>
{
message["RequiredAttribute_ValidationError"] = "字段 {0} 是必填项。";
message["StringLengthAttribute_ValidationError"] = "字段 {0} 必须是字符串,且最大长度为 {1}。";
// 更多可替换项参考:https://github.com/dotnet/dotnet/blob/main/src/runtime/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx
});

// 替换框架提供的验证器/特性的默认验证错误信息
builder.ConfigureValidationMessages(message =>
{
message["AgeValidator_ValidationError"] = "字段 {0} 不是有效的年龄。";
message["BankCardValidator_ValidationError"] = "字段 {0} 不是有效的银行卡号。";
// 更多可替换项参考:https://gitee.com/dotnetchina/Cordon/blob/master/src/Cordon/src/Resources/ValidationMessages.resx
});
});

针对中文场景,框架提供一键启用中文验证错误信息的便捷方法:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
// 一键替换 .NET 内置验证特性的默认验证错误信息为中文
builder.UseChineseDataAnnotationMessages();

// 一键替换框架提供的验证器/特性的默认验证错误信息为中文
builder.UseChineseValidationMessages();
});
非依赖注入环境

在非依赖注入环境中,可直接使用 ValidationMessageProviderDataAnnotationMessageProvider 静态类进行配置,请确保在程序启动前完成设置:

// 替换 .NET 内置验证特性的默认验证错误信息
DataAnnotationMessageProvider.AddOverrides(new Dictionary<string, string>
{
{"RequiredAttribute_ValidationError", "字段 {0} 是必填项。"},
{"StringLengthAttribute_ValidationError", "字段 {0} 必须是字符串,且最大长度为 {1}。"},
// 更多可替换项参考:https://github.com/dotnet/dotnet/blob/main/src/runtime/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx
});

// 替换框架提供的验证器/特性的默认验证错误信息
ValidationMessageProvider.AddOverrides(new Dictionary<string, string>
{
{"AgeValidator_ValidationError", "字段 {0} 不是有效的年龄。"},
{"BankCardValidator_ValidationError", "字段 {0} 不是有效的银行卡号。"},
// 更多可替换项参考:https://gitee.com/dotnetchina/Cordon/blob/master/src/Cordon/src/Resources/ValidationMessages.resx
});

针对中文场景,框架同样提供了一键启用中文验证错误信息的静态便捷方法:

// 一键替换 .NET 内置验证特性的默认验证错误信息为中文
DataAnnotationMessageProvider.UseChineseMessages();

// 一键替换框架提供的验证器/特性的默认验证错误信息为中文
ValidationMessageProvider.UseChineseMessages();

8.3 验证器 ValidatorBase

验证器是继承自 ValidatorBase 的类。ValidatorBase 是一个抽象基类,用于封装具体的验证逻辑,作为整个验证体系的最小核心单元——所有数据验证均由验证器完成。框架支持验证器的组合、继承、优先级控制和本地化。

8.3.1 成员概览

ValidatorBase 抽象类包含以下成员:

  • 受保护构造函数
    • new()
    • new(string)
    • new(Func<string>)
  • 属性
    • ErrorMessage:错误信息,string? 类型
    • ErrorMessageResourceType:错误信息资源类型,Type? 类型
    • ErrorMessageResourceName:错误信息资源名称,string? 类型
    • RuleSets:规则集,string?[]? 类型
  • 受保护属性
    • ErrorMessageString:错误信息字符串,string 类型
    • CustomErrorMessageSet:判断是否设置了自定义错误信息,bool 类型
  • 方法
    • IsValid(object?):检查值是否有效,虚方法
    • IsValid(object?, IValidationContext?):检查值是否有效,抽象方法,需由派生类实现
    • GetValidationResults(object?, string, IEnumerable<string>?):获取验证结果列表,虚方法
    • GetValidationResults(object?, IValidationContext?):获取验证结果列表,虚方法
    • Validate(object?, string, IEnumerable<string>?):执行验证,失败时抛出 ValidationException,虚方法
    • Validate(object?, IValidationContext?):执行验证,失败时抛出 ValidationException,虚方法
    • TryValidate(object?, string, IEnumerable<string>?):尝试执行验证,返回 ValidatorResult,虚方法
    • TryValidate(object?, IValidationContext?):尝试执行验证,返回 ValidatorResult,虚方法
    • FormatErrorMessage(string?):格式化错误信息,虚方法
  • 受保护方法
    • UseResourceKey(Func<string>):使用指定资源键设置验证错误信息
    • OnPropertyChanged(object?, string?):触发属性变更事件
  • 静态方法
    • GetResourceString(string):获取支持外部覆盖的资源字符串
    • GetResourceString(Type, string):获取资源字符串
  • 受保护事件
    • PropertyChanged:属性变更事件,用于监听 ErrorMessageErrorMessageResourceTypeErrorMessageResourceNameRuleSets 的变更

ValidatorBase 提供了一个抽象方法和多个可重写的虚方法。通常只需实现 IsValid(object?, IValidationContext?) 即可快速构建一个功能完整的验证器,其他方法可根据高级需求选择性重写。

8.3.2 验证操作

使用具体验证器(即继承自 ValidatorBase 的非抽象类型)进行数据验证时,需先创建其实例,再根据需求调用 IsValidGetValidationResultsValidate 方法执行验证。这三个方法均提供多种重载形式,详见上一小节。

1. 初始化验证器实例

框架提供以下两种方式:

  • 手动 new 创建:
    var validator = new EmailAddressValidator();
  • 使用 Validators 静态类(推荐):
    Validators 是框架提供的便捷静态工厂类,提供与验证器类型同名(省略 Validator 后缀)的工厂方法,用于创建对应的验证器实例:
    var validator = Validators.EmailAddress();

2. 执行验证

验证器提供以下四种验证方法:

(1)IsValid 方法

用于判断目标值是否有效,适用于无需收集错误信息或需手动控制验证流程的场景:

var value = "support#furion.net";
var isValid = validator.IsValid(value); // => false

该方法还提供带 IValidationContext 参数的重载,可用于传递显示名称、规则集等上下文信息:

var validationContext = new ValidationContext<string>(value)
{
DisplayName = "E-mail",
RuleSets = ["*"]
};

var isValid = validator.IsValid(value, validationContext);

若验证器内部需使用依赖注入服务,可在上下文中传入 IServiceProvider

var validationContext = new ValidationContext<string>(value, serviceProvider, null);

随后在验证器中可通过 validationContext.GetService(serviceType) 解析所需服务。

(2)GetValidationResults 方法

用于获取所有验证失败结果;若验证通过则返回 null,否则返回 List<ValidationResult>

var validationResults = validator.GetValidationResults(value, "data");

其中 "data" 为字段的显示名称,用于错误信息格式化。

同样支持 IValidationContext 重载:

var validationResults = validator.GetValidationResults(value, validationContext);
(3)Validate 方法

用于立即执行验证,失败时抛出 ValidationException,是业务开发中最常用的方法之一:

validator.Validate(value, "data");

"data" 同样作为显示名称用于错误信息。

也支持 IValidationContext 重载:

validator.Validate(value, validationContext);
(4)TryValidate 方法

尝试执行验证,返回封装结果的 ValidatorResult 对象:

var validatorResult = validator.TryValidate(value, "data");

// 失败时抛出 ValidationException
validatorResult.ThrowIfInvalid();

"data" 同样作为显示名称用于错误信息。

同样支持 IValidationContext 重载:

var validatorResult = validator.TryValidate(value, validationContext);

ValidatorResult 包含以下成员:

  • 属性
    • IsValid:表示验证是否通过,bool 类型
    • ValidationResults:验证结果列表,IReadOnlyList<ValidationResult>? 类型
    • Instance:验证的对象,object?T 类型
  • 方法
    • ThrowIfInvalid():若验证未通过,抛出 ValidationException

以上四种方法均适用于框架内置及用户自定义的所有验证器。

8.3.3 验证上下文

在复杂验证场景中,验证器往往需要额外信息(如字段显示名称、当前生效的规则集、共享上下文数据)或依赖外部服务(如数据库连接、本地化资源等)。为此,框架引入了 IValidationContext 作为统一的验证上下文载体。

IValidationContext 用于在验证过程中向验证器传递运行时上下文信息。该接口继承自 IServiceProvider,从而支持在验证器内部解析依赖注入的服务。其默认实现为 ValidationContext<T>

ValidationContext<T> 包含以下成员:

  • 构造函数
    • new(T)
    • new(T, IDictionary<object, object?>?)
    • new(T, IServiceProvider?, IDictionary<object, object?>?)
    • new(T, Func<Type, object?>?, IDictionary<object, object?>?)
  • 属性
    • Instance:被验证的对象,T 类型
    • DisplayName:显示名称,string 类型
    • MemberNames:成员名称列表,IEnumerable<string>? 类型
    • RuleSets:生效的规则集,string?[]? 类型
    • Items:共享数据,IDictionary<object, object?> 类型
  • 方法
    • GetService(Type):解析注册的服务(由 IServiceProvider 定义)

通过 IValidationContext,验证器既能获取上下文信息,又能访问依赖服务,从而支持灵活、可扩展的验证逻辑。

8.3.4 错误信息

验证器 ValidatorBase 抽象类默认提供通用错误信息:The field {0} is invalid.。派生类可覆盖该默认信息以提供更具体的描述。

若需在外部自定义错误信息,框架支持以下两种方式:

1. 通过错误信息属性设置

// 直接指定错误信息
var validator = new EmailAddressValidator { ErrorMessage = "这不是有效的电子邮箱格式" };

// 或使用错误信息资源
var validator = new EmailAddressValidator
{
ErrorMessageResourceType = typeof(YourValidationMessages),
ErrorMessageResourceName = "EmailAddressValidator_ValidationError"
};
注意事项

ErrorMessageErrorMessageResourceTypeErrorMessageResourceName 组合不可同时使用。

2. 使用 .WithMessage() 扩展方法(推荐

该方法支持链式调用,语义清晰,适用于构建流式验证规则:

// 直接指定错误信息
var validator = new EmailAddressValidator().WithMessage("这不是有效的电子邮箱格式");

// 或使用错误信息资源
var validator = new EmailAddressValidator()
.WithMessage(typeof(YourValidationMessages), "EmailAddressValidator_ValidationError");

.WithMessage() 不仅语法简洁,还能确保验证器实例的不可变性,是首选的错误信息配置方式。

3. 在 Must 验证中使用 Must.WithMessage()

当使用 MustValidator<T> 进行条件验证时,可通过 Must.WithMessage() 在委托内部动态返回带自定义信息的失败结果:

var validator = new MustValidator<int?>(value => value switch
{
< 10 => false,
10 => Must.WithMessage("值不能等于 10"), // 返回 false 并附带自定义信息
_ => true
});
  • 当委托返回 false 时,验证失败并使用该 MustValidator 实例当前生效的错误信息——若已通过 .WithMessage() 配置,则使用自定义信息;否则回退到默认信息。
  • 若需在特定条件下动态指定错误信息,可返回 Must.WithMessage(...),此时将忽略原有配置并使用新信息。

同样支持资源文件重载:

Must.WithMessage(typeof(YourValidationMessages), "Custom_Validation_Error");
最佳实践

优先使用 .WithMessage() 构建验证器;仅在 Must 内部逻辑需动态反馈时使用 Must.WithMessage();避免直接设置 ErrorMessage 属性以保持代码一致性与可维护性。

8.4 内置验证器

框架提供了丰富且实用的内置验证器,覆盖绝大多数常见数据校验场景,可有效满足应用开发中的各类验证需求。
所有内置验证器均以 Validator 结尾(例如 EmailAddressValidatorAgeValidator),建议自定义验证器也遵循这一命名规范,以保持一致性与可读性

8.4.1 Age 年龄验证器

功能描述
用于验证输入值是否为有效年龄,默认允许范围为 0 到 120 岁

公开属性

属性类型默认值说明
IsAdultOnlyboolfalse是否仅允许成年人(18 岁及以上
AllowStringValuesboolfalse是否允许字符串数值

使用示例

var validator = new AgeValidator();
object? value = -1;

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");

// 高级配置
var validator = new AgeValidator { IsAdultOnly = true, AllowStringValues = true };
var isValid = validator.IsValid(16);
var isValid = validator.IsValid("20");
推荐使用 Validators 静态类

建议通过 Validators.Age() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.Age();
var validator = Validators.Age(isAdultOnly: true, allowStringValues: true);

验证错误信息资源

资源键默认信息
AgeValidator_ValidationErrorThe field {0} is not a valid age.
AgeValidator_ValidationError_IsAdultOnlyThe field {0} must be at least 18 years old.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["AgeValidator_ValidationError"] = "字段 {0} 不是有效的年龄。";
message["AgeValidator_ValidationError_IsAdultOnly"] = "字段 {0} 必须年满 18 岁。";
});
});

8.4.2 AllowedValues 允许值验证器

功能描述
用于验证输入值是否包含在预设的允许值列表中。

公开属性

属性类型默认值说明
Valuesobject?[]允许的值列表

使用示例

var validator = new AllowedValuesValidator(1, "furion", true);
object? value = "百小僧";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.AllowedValues() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.AllowedValues(1, "furion", true);

验证错误信息资源

资源键默认信息
AllowedValuesValidator_ValidationErrorThe {0} field does not equal any of the values specified in AllowedValuesValidator.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["AllowedValuesValidator_ValidationError"] = "字段 {0} 的值不在 AllowedValuesValidator 指定的允许值列表中。";
});
});

8.4.3 AttributeObject 对象验证特性验证器

功能描述
用于执行基于 .NET 验证特性的对象级验证,包括:

  • 属性上标注的验证特性(如 [Required][Range] 等);
  • 实现了 IValidatableObject 接口的自定义 Validate 方法。

公开属性

属性类型默认值说明
ValidateAllPropertiesbooltrue是否验证所有属性的验证特性。
若设置为 true,则会同时验证所有属性以及 IValidatableObject.Validate 方法;
若设置为 false,则仅验证 IValidatableObject.Validate 方法。

使用示例

User 模型为例:

public class User : IValidatableObject
{
[Range(1, int.MaxValue)]
public int Id { get; set; }

[Required, Length(3, 16)]
public string? Name { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return [];
}
}
var validator = new AttributeObjectValidator();

var user = new User { Id = 1, Name = null };
var validationContext = new ValidationContext<User>(user);

var isValid = validator.IsValid(user, validationContext);
var validationResults = validator.GetValidationResults(user, validationContext);
validator.Validate(user, validationContext);

// 仅验证 IValidatableObject.Validate
var validator = new AttributeObjectValidator(validateAllProperties: false);
推荐使用 Validators 静态类

建议通过 Validators.AttributeObject() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.AttributeObject();
var validator = Validators.AttributeObject(validateAllProperties: false);

验证错误信息资源

该验证器不生成自有错误信息,而是直接复用 .NET 内置验证特性(如 [Required][Range] 等)或 IValidatableObject.Validate 返回的 ValidationResult 中的信息,因此无需额外配置资源键

8.4.4 AttributeProperty 属性验证特性验证器

功能描述
用于对指定属性执行基于 .NET 验证特性(如 [Required][StringLength] 等)的验证,仅针对单个属性进行校验。

公开属性

属性类型默认值说明
PropertyPropertyInfo要验证的属性

使用示例

User 模型为例:

public class User
{
[Required, StringLength(16)]
public string? Name { get; set; }
}
var validator = new AttributePropertyValidator<User>(u => u.Name);

var user = new User { Name = null };
var validationContext = new ValidationContext<User>(user);

var isValid = validator.IsValid(user, validationContext);
var validationResults = validator.GetValidationResults(user, validationContext);
validator.Validate(user, validationContext);
推荐使用 Validators 静态类

建议通过 Validators.AttributeProperty<T>() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.AttributeProperty<User>(u => u.Name);

验证错误信息资源

该验证器不生成自有错误信息,而是直接使用属性上标注的 .NET 验证特性(如 [Required][StringLength] 等)所携带的错误信息,因此无需额外配置资源键

8.4.5 AttributeValue 单值验证特性验证器

功能描述
用于对单值应用一组 .NET 验证特性(如 [Required][StringLength] 等)进行校验,适用于脱离模型上下文的独立值验证场景。

公开属性

属性类型默认值说明
AttributesValidationAttribute[]验证特性列表

使用示例

using var validator = new AttributeValueValidator(new RequiredAttribute(), new StringLengthAttribute(16));

string? value = null;
var validationContext = new ValidationContext<string?>(value);

var isValid = validator.IsValid(value, validationContext);
var validationResults = validator.GetValidationResults(value, validationContext);
validator.Validate(value, validationContext);
推荐使用 Validators 静态类

建议通过 Validators.AttributeValue() 工厂方法创建实例,以提升可维护性并支持未来扩展:

using var validator = Validators.AttributeValue(new RequiredAttribute(), new StringLengthAttribute(16));
错误信息设置

AttributeValueValidator 设置的错误信息(如 ErrorMessageErrorMessageResourceNameErrorMessageResourceType)会自动同步至其内部的单个验证特性实例。

验证错误信息资源

该验证器会直接复用传入的 ValidationAttribute 实例中定义的错误信息——包括通过 ErrorMessageErrorMessageResourceTypeErrorMessageResourceName 配置的本地化信息,或自定义验证特性返回的 ValidationResult 中指定的 ErrorMessage。因此,无需额外注册资源键

8.4.6 BankCard 银行卡号验证器

功能描述
用于验证输入值是否为有效的银行卡号,依据 Luhn 算法 进行校验。

公开属性

使用示例

var validator = new BankCardValidator();
object? value = "41111111111111111111";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.BankCard() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.BankCard();

验证错误信息资源

资源键默认信息
BankCardValidator_ValidationErrorThe field {0} is not a valid bank card number.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["BankCardValidator_ValidationError"] = "字段 {0} 不是有效的银行卡号。";
});
});

8.4.7 Base64String Base64 字符串验证器

功能描述
用于验证输入值是否为符合标准格式的有效 Base64 编码字符串。

公开属性

使用示例

var validator = new Base64StringValidator();
object? value = "ZnVdyaW9u";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.Base64String() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.Base64String();

验证错误信息资源

资源键默认信息
Base64StringValidator_ValidationErrorThe {0} field is not a valid Base64 encoding.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["Base64StringValidator_ValidationError"] = "字段 {0} 不是有效的 Base64 编码。";
});
});

8.4.8 ChineseName 中文姓名验证器

功能描述
用于验证输入值是否为符合常见规范的中文姓名(支持 2–16 个汉字,包含复姓和单字名等常见形式)。

公开属性

使用示例

var validator = new ChineseNameValidator();
object? value = "蒙奇·D·路飞";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.ChineseName() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.ChineseName();

验证错误信息资源

资源键默认信息
ChineseNameValidator_ValidationErrorThe field {0} is not a valid Chinese name.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["ChineseNameValidator_ValidationError"] = "字段 {0} 不是有效的中文姓名。";
});
});

8.4.9 Chinese 中文验证器

功能描述
用于验证输入值是否完全由中文汉字(包括常见简体、繁体汉字)组成。非字符串类型或包含任何非汉字字符(如字母、数字、标点、空格等)均视为无效。

公开属性

使用示例

var validator = new ChineseValidator();
object? value = "Furion";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.Chinese() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.Chinese();

验证错误信息资源

资源键默认信息
ChineseValidator_ValidationErrorThe field {0} contains invalid Chinese characters.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["ChineseValidator_ValidationError"] = "字段 {0} 包含无效的中文字符。";
});
});

8.4.10 Color 颜色验证器

功能描述
用于验证输入值是否为有效的 CSS 颜色。支持多种常见格式,包括十六进制、RGBRGBA,并可选支持 HSLHSLA

公开属性

属性类型默认值说明
FullModeboolfalse是否启用完整模式。在完整模式下,支持的颜色格式包括:十六进制颜色、RGBRGBAHSLHSLA;若未启用,则仅支持十六进制颜色、RGBRGBA

使用示例

var validator = new ColorValidator();
object? value = "hsl(0, 100%, 50%)";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");

// 高级配置
var validator = new ColorValidator { FullMode = true };
推荐使用 Validators 静态类

建议通过 Validators.Color() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.Color();
var validator = Validators.Color(fullMode: true);

验证错误信息资源

资源键默认信息
ColorValidator_ValidationErrorThe field {0} is not a valid color.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["ColorValidator_ValidationError"] = "字段 {0} 不是有效的颜色。";
});
});

8.4.11 Compare 比较两个属性验证器

功能描述
用于验证对象中两个属性的值是否相等。

公开属性

属性类型默认值说明
PropertyPropertyInfo主要比较属性
OtherPropertyPropertyInfo被比较的另一属性

使用示例

var validator = new CompareValidator<User>(u => u.Password, u => u.ConfirmPassword);
var user = new User { Password = "q1we3", ConfirmPassword = "q1w2e3r4" };

var isValid = validator.IsValid(user);
var validationResults = validator.GetValidationResults(user, "data");
validator.Validate(user, "data");

// 也支持通过属性名指定第二个属性
var validator = new CompareValidator<User>(u => u.Password, "ConfirmPassword");
推荐使用 Validators 静态类

建议通过 Validators.Compare<T>() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.Compare<User>(u => u.Password, u => u.ConfirmPassword);
var validator = Validators.Compare<User>(u => u.Password, "ConfirmPassword");

验证错误信息资源

资源键默认信息
CompareValidator_ValidationError'{0}' and '{1}' do not match.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["CompareValidator_ValidationError"] = "“{0}”与“{1}”不匹配。";
});
});

8.4.12 CustomValidation 自定义验证特性验证器

功能描述
通过指定类型和静态方法,实现对属性或类实例的自定义验证逻辑。

公开属性

属性类型默认值说明
ValidatorTypeType执行自定义验证的类型
Methodstring验证方法

使用示例

CustomValidators 静态类为例:

public static class CustomValidators
{
// ValidationContext 参数为可选,按需添加
public static ValidationResult? ValidateValue(object? value, ValidationContext context) =>
value switch
{
null => ValidationResult.Success,
string { Length: < 3 } => new ValidationResult("字符串长度不能小于 3"),
_ => ValidationResult.Success
};
}

与其他验证器不同,CustomValidation 需通过 CustomValidationAttribute 实例初始化,并作为 AttributeValueValidator 的构造参数传入:

using var validator = new AttributeValueValidator(new CustomValidationAttribute(typeof(CustomValidators), nameof(CustomValidators.ValidateValue));
object? value = "fu";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");
推荐使用 Validators 静态类

建议通过 Validators.CustomValidation() 工厂方法创建实例,以提升可维护性并支持未来扩展:

using var validator = Validators.CustomValidation(typeof(CustomValidators), nameof(CustomValidators.ValidateValue);
错误信息设置与优先级

AttributeValueValidator 设置的错误信息(如 ErrorMessageErrorMessageResourceNameErrorMessageResourceType)会自动同步至其内部的 CustomValidationAttribute 实例。

  • 若验证方法返回非空的 ValidationResult 且其 ErrorMessage 不为空,则使用该信息,并覆盖特性或资源中配置的错误信息。
  • 若返回的 ValidationResultErrorMessagenull 或空字符串(例如 new ValidationResult(null)),则使用外部配置的错误信息(如 ErrorMessage 或本地化资源)。

验证错误信息资源

资源键默认信息
CustomValidationAttribute_ValidationError{0} is not valid.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureDataAnnotationValidationMessages(message =>
{
message["CustomValidationAttribute_ValidationError"] = "{0} 无效。";
});
});

8.4.13 DateOnly 日期验证器

功能描述
用于验证输入值是否可解析为有效的 DateOnly 实例,支持自定义日期格式、区域设置及解析行为控制。

公开属性

属性类型默认值说明
Formatsstring[]允许的日期格式列表(如 yyyy-MM-dd
ProviderIFormatProvider?CultureInfo.InvariantCulture格式提供器
StyleDateTimeStylesDateTimeStyles.None日期解析样式,需与 Formats 属性搭配使用

使用示例

var validator = new DateOnlyValidator();
object? value = "2023/09/26";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");

// 高级配置
var validator = new DateOnlyValidator("yyyy/MM/dd", "yyyy-MM-dd", "dd/MM/yyyy");
推荐使用 Validators 静态类

建议通过 Validators.DateOnly() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.DateOnly();
var validator = Validators.DateOnly("yyyy/MM/dd", "yyyy-MM-dd", "dd/MM/yyyy");

验证错误信息资源

资源键默认信息
DateOnlyValidator_ValidationErrorThe field {0} must be a valid date.
DateOnlyValidator_ValidationError_FormatsThe field {0} must be a valid date in the following format(s): {1}.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["DateOnlyValidator_ValidationError"] = "字段 {0} 必须是有效的日期。";
message["DateOnlyValidator_ValidationError_Formats"] = "字段 {0} 必须是符合以下格式之一的有效日期:{1}。";
});
});

8.4.14 DateTime 时刻验证器

功能描述
用于验证输入值是否可解析为有效的 DateTime 实例,支持自定义日期时间格式、区域设置及解析行为控制。

公开属性

属性类型默认值说明
Formatsstring[]允许的日期时间格式列表(如 yyyy-MM-dd HH:mm:ss
ProviderIFormatProvider?CultureInfo.InvariantCulture格式提供器
StyleDateTimeStylesDateTimeStyles.None日期时间解析样式,需与 Formats 属性搭配使用

使用示例

var validator = new DateTimeValidator();
object? value = "2023/09/26 13:14:15";

var isValid = validator.IsValid(value);
var validationResults = validator.GetValidationResults(value, "data");
validator.Validate(value, "data");

// 高级配置
var validator = new DateTimeValidator("yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss", "dd/MM/yyyy HH:mm:ss");
推荐使用 Validators 静态类

建议通过 Validators.DateTime() 工厂方法创建实例,以提升可维护性并支持未来扩展:

var validator = Validators.DateTime();
var validator = Validators.DateTime("yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss", "dd/MM/yyyy HH:mm:ss"));

验证错误信息资源

资源键默认信息
DateTimeValidator_ValidationErrorThe field {0} must be a valid datetime.
DateTimeValidator_ValidationError_FormatsThe field {0} must be a valid datetime in the following format(s): {1}.

可以通过上述资源键替换验证器的默认错误信息。例如:

services.AddCordon(builder => // 在 ASP.NET 应用中可使用:services.AddControllers().AddCordon
{
builder.ConfigureValidationMessages(message =>
{
message["DateTimeValidator_ValidationError"] = "字段 {0} 必须是有效的日期时间。";
message["DateTimeValidator_ValidationError_Formats"] = "字段 {0} 必须是符合以下格式之一的有效日期时间:{1}。";
});
});

8.4.15 DecimalPlaces 小数位数验证器

功能描述
用于验证数值的小数位数是否不超过指定的最大值。

公开属性

属性类型默认值说明
MaxDecimalPlacesint允许的最大有效小数位数(构造函数传入,不可变)
AllowStringValuesboolfalse是否允许字符串数值

使用示例

// 基础使用:最多 2 位小数
var validator = new DecimalPlacesValidator(2);

var isValid = validator.IsValid(123.456m); // false(3 位小数)
var validationResults = validator.GetValidationResults(123.456m, "Price"); // 返回错误
validator.Validate(123.456m, "Price"); // 抛出 ValidationException

// 允许字符串输入
var validator = new DecimalPlacesValidator(3) { AllowStringValues = true };

var isValid = validator.IsValid("123.45"); // true(2 位小数)
var isValid = validator.IsValid("123.4567"); // false(4 位小数)
推荐使用 Validators 静态类

推荐通过 Validators.DecimalPlaces(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
DecimalPlacesValidator_ValidationErrorThe field {0} must not have more than '{1}' decimal places.

8.4.16 DeniedValues 禁止值验证器

功能描述
用于验证目标值是否不在指定的禁止值列表中。

公开属性

该验证器通过构造函数传入禁止值列表,无额外公开属性。

使用示例

// 基础使用
var validator = new DeniedValuesValidator("admin", "root", "guest");

var isValid = validator.IsValid("admin"); // false
var validationResults = validator.GetValidationResults("admin", "Username"); // 返回错误
validator.Validate("admin", "Username"); // 抛出 ValidationException

// 支持混合类型值
var validator = new DeniedValuesValidator(0, -1, "", null, "N/A");

var isValid = validator.IsValid(1); // true
var isValid = validator.IsValid(""); // false
推荐使用 Validators 静态类

推荐通过 Validators.DeniedValues(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
DeniedValuesValidator_ValidationErrorThe {0} field equals one of the values specified in DeniedValuesValidator.

8.4.17 Domain 域名验证器

功能描述
用于验证字符串是否为有效的域名(不含协议,如 https://http://),支持国际化域名(IDN)并遵循 RFC 1034 标准(最大长度 253 字符)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new DomainValidator();

var isValid = validator.IsValid("example..com"); // false(连续点)
var validationResults = validator.GetValidationResults("invalid_domain", "Host"); // 返回错误
validator.Validate("_invalid.com", "Host"); // 抛出 ValidationException

// 支持国际化域名和合法格式
var validator = new DomainValidator();

var isValid = validator.IsValid("example.com"); // true
var isValid = validator.IsValid("中国.cn"); // true(自动转 Punycode 验证)
推荐使用 Validators 静态类

推荐通过 Validators.Domain() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
DomainValidator_ValidationErrorThe field {0} is not a valid domain name.

8.4.18 EmailAddress 邮箱地址验证器

功能描述
用于验证字符串是否为有效的电子邮件地址格式。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new EmailAddressValidator();

var isValid = validator.IsValid("invalid-email"); // false
var validationResults = validator.GetValidationResults("user@", "Email"); // 返回错误
validator.Validate("user@", "Email"); // 抛出 ValidationException

// 验证有效邮箱
var validator = new EmailAddressValidator();

var isValid = validator.IsValid("user@example.com"); // true
var isValid = validator.IsValid("test.email+tag@domain.co.uk"); // true
推荐使用 Validators 静态类

推荐通过 Validators.EmailAddress() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
EmailAddressValidator_ValidationErrorThe {0} field is not a valid e-mail address.

8.4.19 Empty 空值验证器

功能描述
用于验证值是否为空(null)或空集合/数组/字符串(长度为 0)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new EmptyValidator();

var isValid = validator.IsValid(new List<int>()); // true
var validationResults = validator.GetValidationResults("hello", "Data"); // 返回错误(非空)
validator.Validate("non-empty", "Data"); // 抛出 ValidationException

// 验证各种空值
var validator = new EmptyValidator();

var isValid = validator.IsValid((string?)null); // true
var isValid = validator.IsValid(new int[0]); // true
推荐使用 Validators 静态类

推荐通过 Validators.Empty() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
EmptyValidator_ValidationErrorThe field {0} must be empty.

8.4.20 EndsWith 结尾字符串验证器

功能描述
用于验证字符串是否以指定的字符或字符串结尾。

公开属性

属性类型默认值说明
SearchValuestring检索的值(通过构造函数传入,不可变)
ComparisonStringComparisonStringComparison.Ordinal字符串比较方式

使用示例

// 基础使用
var validator = new EndsWithValidator(".com");

var isValid = validator.IsValid("example.org"); // false
var validationResults = validator.GetValidationResults("test.net", "Domain"); // 返回错误
validator.Validate("invalid.io", "Domain"); // 抛出 ValidationException

// 自定义比较方式
var validator = new EndsWithValidator("TXT") { Comparison = StringComparison.OrdinalIgnoreCase };

var isValid = validator.IsValid("report.txt"); // true
var isValid = validator.IsValid("data.TXT"); // true
推荐使用 Validators 静态类

推荐通过 Validators.EndsWith(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
EndsWithValidator_ValidationErrorThe field {0} does not end with the string '{1}'.'.

8.4.21 Enum 枚举验证器

功能描述
用于验证值是否为指定枚举类型的已定义成员。支持普通枚举和 [Flags] 枚举模式。

公开属性

属性类型默认值说明
EnumTypeType枚举类型(通过构造函数传入,不可变)
SupportFlagsboolfalse是否支持 Flags 模式

使用示例

// 基础使用:验证普通枚举
var validator = new EnumValidator(typeof(Status));

var isValid = validator.IsValid("Invalid"); // false
var validationResults = validator.GetValidationResults("Pending", "Status"); // true → 无错误
validator.Validate("Unknown", "Status"); // 抛出 ValidationException

// 启用 Flags 支持
var validator = new EnumValidator(typeof(FileAccess)) { SupportFlags = true };

var isValid = validator.IsValid("Read,Write"); // true(若 FileAccess 有 [Flags])
var isValid = validator.IsValid(3); // true(组合值)
推荐使用 Validators 静态类

推荐通过 Validators.Enum<T>()Validators.Enum(typeof(T)) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
EnumValidator_ValidationErrorThe field {0} must be a defined value of enum {1}.
EnumValidator_ValidationError_SupportFlagsThe field {0} must be a valid combination of values defined in enum {1}.

8.4.22 EqualTo 相等验证器

功能描述
用于验证目标值是否与指定的值相等。

公开属性

属性类型默认值说明
CompareValueobject?用于比较的值(通过构造函数传入,不可变)

使用示例

// 基础使用:验证是否等于固定值
var validator = new EqualToValidator("approved");

var isValid = validator.IsValid("pending"); // false
var validationResults = validator.GetValidationResults("rejected", "Status"); // 返回错误
validator.Validate("draft", "Status"); // 抛出 ValidationException

// 验证其他类型
var validator = new EqualToValidator(42);

var isValid = validator.IsValid(42); // true
var isValid = validator.IsValid(null); // true(null 被视为有效)
推荐使用 Validators 静态类

推荐通过 Validators.EqualTo(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
EqualToValidator_ValidationErrorThe field {0} must be equal to '{1}'.

8.4.23 Failure 固定失败验证器

功能描述
始终返回验证失败,仅用于输出指定错误信息。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new FailureValidator();

var isValid = validator.IsValid("any value"); // false
var validationResults = validator.GetValidationResults("data", "Field"); // 返回错误
validator.Validate("anything", "Field"); // 抛出 ValidationException

// 通常配合自定义错误信息使用
var validator = new FailureValidator();
validator.ErrorMessage = "This field is temporarily disabled.";

var isValid = validator.IsValid(null); // false
推荐使用 Validators 静态类

推荐通过 Validators.Failure() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
ValidatorBase_ValidationErrorThe field {0} is invalid.

8.4.24 FileExtensions 文件扩展名验证器

功能描述
用于验证文件名是否具有指定的扩展名(如 "jpg,png,gif"),支持自动忽略大小写和前导点号。

公开属性

属性类型默认值说明
Extensionsstring允许的文件扩展名列表,以逗号分隔(通过构造函数传入,不可变)

注:输入时可带或不带点号(如 "jpg"".jpg"),系统会自动标准化处理。

使用示例

// 基础使用
var validator = new FileExtensionsValidator("jpg,jpeg,png");

var isValid = validator.IsValid("photo.gif"); // false
var validationResults = validator.GetValidationResults("image.bmp", "Avatar"); // 返回错误
validator.Validate("document.txt", "Avatar"); // 抛出 ValidationException

// 支持带点号或混合格式
var validator = new FileExtensionsValidator(".pdf, DOCX, xls");

var isValid = validator.IsValid("report.pdf"); // true
var isValid = validator.IsValid("data.XLS"); // true(自动忽略大小写)
推荐使用 Validators 静态类

推荐通过 Validators.FileExtensions(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
FileExtensionsValidator_ValidationErrorThe {0} field only accepts files with the following extensions: {1}.

8.4.25 GreaterThanOrEqualTo 大于等于验证器

功能描述
用于验证数值是否大于或等于指定的值。

公开属性

属性类型默认值说明
CompareValueIComparable比较基准值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:验证数字是否 ≥ 100
var validator = new GreaterThanOrEqualToValidator(100);

var isValid = validator.IsValid(99); // false
var validationResults = validator.GetValidationResults(50, "Score"); // 返回错误
validator.Validate(0, "Score"); // 抛出 ValidationException

// 验证日期是否 ≥ 某个时间点
var validator = new GreaterThanOrEqualToValidator(new DateTime(2025, 1, 1));

var isValid = validator.IsValid(new DateTime(2026, 1, 1)); // true
var isValid = validator.IsValid("2024-12-31"); // false(类型不匹配)
推荐使用 Validators 静态类

推荐通过 Validators.GreaterThanOrEqualTo(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
GreaterThanOrEqualToValidator_ValidationErrorThe field {0} must be greater than or equal to '{1}'.

8.4.26 GreaterThan 大于验证器

功能描述
用于验证数值是否大于指定的值。

公开属性

属性类型默认值说明
CompareValueIComparable比较基准值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:验证数字是否 > 0
var validator = new GreaterThanValidator(0);

var isValid = validator.IsValid(0); // false
var validationResults = validator.GetValidationResults(-5, "Quantity"); // 返回错误
validator.Validate(-1, "Quantity"); // 抛出 ValidationException

// 验证日期是否 > 某个时间点
var validator = new GreaterThanValidator(new DateTime(2025, 1, 1));

var isValid = validator.IsValid(new DateTime(2025, 1, 2)); // true
var isValid = validator.IsValid("2025-01-01"); // false(类型不匹配或等于)
推荐使用 Validators 静态类

推荐通过 Validators.GreaterThan(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
GreaterThanValidator_ValidationErrorThe field {0} must be greater than '{1}'.

8.4.27 HaveLength 固定长度验证器

功能描述
用于验证字符串、数组或集合的长度是否等于指定值。可选允许空值(长度为 0)。

公开属性

属性类型默认值说明
Lengthint期望的固定长度(通过构造函数传入,不可变)
AllowEmptyboolfalse是否允许空集合、数组或字符串(即长度为 0)

使用示例

// 基础使用:必须恰好 6 个字符
var validator = new HaveLengthValidator(6);

var isValid = validator.IsValid("12345"); // false
var validationResults = validator.GetValidationResults("1234567", "Code"); // 返回错误
validator.Validate("1234", "Code"); // 抛出 ValidationException

// 允许空值
var validator = new HaveLengthValidator(8) { AllowEmpty = true };

var isValid = validator.IsValid(""); // true
var isValid = validator.IsValid(new int[8]); // true
推荐使用 Validators 静态类

推荐通过 Validators.HaveLength(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
HaveLengthValidator_ValidationErrorThe field {0} must be a string or collection type with a length of exactly '{1}'.
HaveLengthValidator_ValidationError_AllowEmptyThe field {0} must be empty or have a length of exactly '{1}'.

8.4.28 IDCard 身份证号验证器

功能描述
用于验证字符串是否为符合中国大陆身份证号码格式(18 位,含校验码)的有效身份证号。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new IDCardValidator();

var isValid = validator.IsValid("11010119900307XXXX"); // false(格式不完整)
var validationResults = validator.GetValidationResults("123", "ID"); // 返回错误
validator.Validate("invalid-id", "ID"); // 抛出 ValidationException

// 验证有效身份证
var validator = new IDCardValidator();

var isValid = validator.IsValid("110101199003072316"); // true
var isValid = validator.IsValid("11010119900307231X"); // true(末位 X 合法)
推荐使用 Validators 静态类

推荐通过 Validators.IDCard() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
IDCardValidator_ValidationErrorThe field {0} is not a valid Id card number format.

8.4.29 IpAddress IP 地址验证器

功能描述
用于验证字符串是否为有效的 IPv4 或 IPv6 地址。默认仅支持 IPv4,可启用 IPv6 支持。

公开属性

属性类型默认值说明
AllowIPv6boolfalse是否允许 IPv6 地址

使用示例

// 基础使用:仅验证 IPv4
var validator = new IpAddressValidator();

var isValid = validator.IsValid("192.168.1.256"); // false(无效 IPv4)
var validationResults = validator.GetValidationResults("invalid-ip", "Host"); // 返回错误
validator.Validate("10.0.0.1", "Host"); // true → 无异常

// 启用 IPv6 支持
var validator = new IpAddressValidator { AllowIPv6 = true };

var isValid = validator.IsValid("::1"); // true
var isValid = validator.IsValid("2001:db8::1"); // true
推荐使用 Validators 静态类

推荐通过 Validators.IpAddress() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
IpAddressValidator_ValidationErrorThe field {0} is not a valid IPv4 address.
IpAddressValidator_ValidationError_AllowIPv6The field {0} is not a valid IP address (IPv4 or IPv6).

8.4.30 Json JSON 格式验证器

功能描述
用于验证字符串是否为有效的 JSON 对象({...})或数组([...])。

公开属性

属性类型默认值说明
AllowTrailingCommasboolfalse是否允许末尾多余逗号

使用示例

// 基础使用:严格 JSON 格式
var validator = new JsonValidator();

var isValid = validator.IsValid("{ name: 'test' }"); // false(缺少引号)
var validationResults = validator.GetValidationResults("invalid", "Payload"); // 返回错误
validator.Validate("[]", "Payload"); // true → 无异常

// 允许末尾逗号
var validator = new JsonValidator { AllowTrailingCommas = true };

var isValid = validator.IsValid(@"{""a"":1,""b"":2,}"); // true
var isValid = validator.IsValid(@"[""x"",""y"",]"); // true
推荐使用 Validators 静态类

推荐通过 Validators.Json() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
JsonValidator_ValidationErrorThe {0} field must be a valid JSON object or array.

8.4.31 Length 长度验证器

功能描述
用于验证字符串、数组或集合的长度是否在指定的最小值和最大值之间(含边界)。

公开属性

属性类型默认值说明
MinimumLengthint最小允许长度(通过构造函数传入,不可变)
MaximumLengthint最大允许长度(通过构造函数传入,不可变)

注:仅适用于字符串、数组、列表等可计算长度的类型。

使用示例

// 基础使用:长度必须在 2 到 10 之间
var validator = new LengthValidator(2, 10);

var isValid = validator.IsValid("A"); // false(长度不足)
var validationResults = validator.GetValidationResults("TooLongString", "Name"); // 返回错误
validator.Validate("", "Name"); // 抛出 ValidationException

// 验证集合
var validator = new LengthValidator(1, 5);

var isValid = validator.IsValid(new[] { "a", "b" }); // true
var isValid = validator.IsValid(new int[6]); // false(超出最大长度)
推荐使用 Validators 静态类

推荐通过 Validators.Length(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
LengthValidator_ValidationErrorThe field {0} must be a string or collection type with a minimum length of '{1}' and maximum length of '{2}'.

8.4.32 LessThanOrEqualTo 小于等于验证器

功能描述
用于验证数值是否小于或等于指定的值。

公开属性

属性类型默认值说明
CompareValueIComparable比较基准值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:验证数字是否 ≤ 100
var validator = new LessThanOrEqualToValidator(100);

var isValid = validator.IsValid(101); // false
var validationResults = validator.GetValidationResults(150, "Score"); // 返回错误
validator.Validate(200, "Score"); // 抛出 ValidationException

// 验证日期是否 ≤ 某个时间点
var validator = new LessThanOrEqualToValidator(new DateTime(2025, 12, 31));

var isValid = validator.IsValid(new DateTime(2025, 6, 1)); // true
var isValid = validator.IsValid("2026-01-01"); // false(类型不匹配或超出)
推荐使用 Validators 静态类

推荐通过 Validators.LessThanOrEqualTo(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
LessThanOrEqualToValidator_ValidationErrorThe field {0} must be less than or equal to '{1}'.

8.4.33 LessThan 小于验证器

功能描述
用于验证数值是否小于指定的值。

公开属性

属性类型默认值说明
CompareValueIComparable比较基准值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:验证数字是否 < 10
var validator = new LessThanValidator(10);

var isValid = validator.IsValid(10); // false
var validationResults = validator.GetValidationResults(15, "Count"); // 返回错误
validator.Validate(10, "Count"); // 抛出 ValidationException

// 验证日期是否 < 某个时间点
var validator = new LessThanValidator(new DateTime(2026, 1, 1));

var isValid = validator.IsValid(new DateTime(2025, 12, 31)); // true
var isValid = validator.IsValid("2026-01-01"); // false(类型不匹配或等于)
推荐使用 Validators 静态类

推荐通过 Validators.LessThan(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
LessThanValidator_ValidationErrorThe field {0} must be less than '{1}'.

8.4.34 MaxLength 最大长度验证器

功能描述
用于验证字符串、数组或集合的长度是否不超过指定的最大值。

公开属性

属性类型默认值说明
Lengthint最大允许长度(通过构造函数传入,不可变)

注:仅适用于字符串、数组、列表等可计算长度的类型。

使用示例

// 基础使用:最大长度为 50
var validator = new MaxLengthValidator(50);

var isValid = validator.IsValid(new string('x', 51)); // false
var validationResults = validator.GetValidationResults("This is too long...", "Description"); // 返回错误
validator.Validate("A".PadRight(51), "Description"); // 抛出 ValidationException

// 验证数组
var validator = new MaxLengthValidator(3);

var isValid = validator.IsValid(new[] { "a", "b" }); // true
var isValid = validator.IsValid(new int[4]); // false
推荐使用 Validators 静态类

推荐通过 Validators.MaxLength(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
MaxLengthValidator_ValidationErrorThe field {0} must be a string or array type with a maximum length of '{1}'.

8.4.35 Max 最大值验证器

功能描述
用于验证数值是否小于或等于指定的最大值。

公开属性

属性类型默认值说明
CompareValueIComparable允许的最大值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:最大值为 100
var validator = new MaxValidator(100);

var isValid = validator.IsValid(101); // false
var validationResults = validator.GetValidationResults(150, "Score"); // 返回错误
validator.Validate(200, "Score"); // 抛出 ValidationException

// 验证日期不超过某个时间点
var validator = new MaxValidator(new DateTime(2025, 12, 31));

var isValid = validator.IsValid(new DateTime(2025, 6, 1)); // true
var isValid = validator.IsValid("2026-01-01"); // false(类型不匹配或超出)
推荐使用 Validators 静态类

推荐通过 Validators.Max(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
MaxValidator_ValidationErrorThe field {0} must be less than or equal to '{1}'.

8.4.36 MD5String MD5 字符串验证器

功能描述
用于验证字符串是否为有效的 MD5 哈希值(标准 32 位格式),可选支持 16 位截断格式。

公开属性

属性类型默认值说明
AllowShortFormatboolfalse是否允许 16 位截断的 MD5 格式

使用示例

// 基础使用:仅允许 32 位标准格式
var validator = new MD5StringValidator();

var isValid = validator.IsValid("d41d8cd98f00b204e9800998ecf8427e"); // true
var validationResults = validator.GetValidationResults("invalid-md5", "Hash"); // 返回错误
validator.Validate("short", "Hash"); // 抛出 ValidationException

// 允许 16 位或 32 位格式
var validator = new MD5StringValidator { AllowShortFormat = true };

var isValid = validator.IsValid("d41d8cd98f00b204"); // true(16 位)
var isValid = validator.IsValid("d41d8cd98f00b204e9800998ecf8427e"); // true(32 位)
推荐使用 Validators 静态类

推荐通过 Validators.MD5String() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
MD5StringValidator_ValidationErrorThe field {0} is not a valid MD5 string.

8.4.37 MinLength 最小长度验证器

功能描述
用于验证字符串、数组或集合的长度是否不小于指定的最小值。

公开属性

属性类型默认值说明
Lengthint最小允许长度(通过构造函数传入,不可变)

注:仅适用于字符串、数组、列表等可计算长度的类型。

使用示例

// 基础使用:最小长度为 5
var validator = new MinLengthValidator(5);

var isValid = validator.IsValid("1234"); // false
var validationResults = validator.GetValidationResults("Hi", "Username"); // 返回错误
validator.Validate("", "Username"); // 抛出 ValidationException

// 验证数组
var validator = new MinLengthValidator(2);

var isValid = validator.IsValid(new[] { "a", "b" }); // true
var isValid = validator.IsValid(new int[1]); // false
推荐使用 Validators 静态类

推荐通过 Validators.MinLength(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
MinLengthValidator_ValidationErrorThe field {0} must be a string or array type with a minimum length of '{1}'.

8.4.38 Min 最小值验证器

功能描述
用于验证数值是否大于或等于指定的最小值。

公开属性

属性类型默认值说明
CompareValueIComparable允许的最小值(通过构造函数传入,不可变)

注:仅当被验证值与 CompareValue 类型兼容时才进行比较,否则视为无效。

使用示例

// 基础使用:最小值为 0
var validator = new MinValidator(0);

var isValid = validator.IsValid(-1); // false
var validationResults = validator.GetValidationResults(-5, "Quantity"); // 返回错误
validator.Validate(-10, "Quantity"); // 抛出 ValidationException

// 验证日期不早于某个时间点
var validator = new MinValidator(new DateTime(2020, 1, 1));

var isValid = validator.IsValid(new DateTime(2025, 1, 1)); // true
var isValid = validator.IsValid("2019-12-31"); // false(类型不匹配或小于)
推荐使用 Validators 静态类

推荐通过 Validators.Min(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
MinValidator_ValidationErrorThe field {0} must be greater than or equal to '{1}'.

8.4.39 Must 自定义条件验证器

功能描述
用于通过自定义委托(Func<T, bool>Func<T, ValidationContext<T>, bool>)验证对象是否满足特定业务逻辑条件。支持在条件不满足时抛出带自定义信息的异常。

公开属性

该验证器通过构造函数传入条件委托,无额外公开属性。

使用示例

// 基础使用:简单条件
var validator = new MustValidator<User>(u => u.Age >= 18);

var user = new User { Age = 16 };
var isValid = validator.IsValid(user); // false
var validationResults = validator.GetValidationResults(user, "User"); // 返回错误
validator.Validate(user, "User"); // 抛出 ValidationException

// 高级使用:带上下文和自定义错误信息
var validator = new MustValidator<User>((u, ctx) =>
{
if (u.Age < 18)
{
return Must.WithMessage("{0} must be at least 18 years old.");
}
return true;
});

var user = new User { Age = 15 };
validator.Validate(user, new ValidationContext<User>(user) { DisplayName = "Profile" }); // 抛出自定义信息
推荐使用 Validators 静态类

推荐通过 Validators.Must(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
ValidatorBase_ValidationErrorThe field {0} is invalid.

注:若在条件委托中调用 Must.WithMessage(),将覆盖默认信息。

8.4.40 NotBlank 非空白字符串验证器

功能描述
用于验证值是否为非空且非空白的字符串或非空白字符(不接受仅包含空格、制表符、换行等空白字符的输入)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new NotBlankValidator();

var isValid = validator.IsValid(" "); // false
var validationResults = validator.GetValidationResults("", "Name"); // 返回错误
validator.Validate("\t\n", "Name"); // 抛出 ValidationException

// 验证有效输入
var validator = new NotBlankValidator();

var isValid = validator.IsValid("John"); // true
var isValid = validator.IsValid('A'); // true
推荐使用 Validators 静态类

推荐通过 Validators.NotBlank() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
NotBlankValidator_ValidationErrorThe field {0} cannot be empty or whitespace.

8.4.41 NotEmpty 非空验证器

功能描述
用于验证值是否为非空的集合、数组或字符串(即长度大于 0)。null 值被视为有效。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new NotEmptyValidator();

var isValid = validator.IsValid(new List<int>()); // false(空集合)
var validationResults = validator.GetValidationResults("", "Name"); // 返回错误
validator.Validate(new int[0], "Items"); // 抛出 ValidationException

// 验证有效输入
var validator = new NotEmptyValidator();

var isValid = validator.IsValid("Hello"); // true
var isValid = validator.IsValid(new[] { 1, 2, 3 }); // true
推荐使用 Validators 静态类

推荐通过 Validators.NotEmpty() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
NotEmptyValidator_ValidationErrorThe field {0} does not allow empty values.

8.4.42 NotEqualTo 不相等验证器

功能描述
用于验证目标值是否不等于指定的值。

公开属性

属性类型默认值说明
CompareValueobject?用于比较的值(通过构造函数传入,不可变)

使用示例

// 基础使用:不能等于 "admin"
var validator = new NotEqualToValidator("admin");

var isValid = validator.IsValid("admin"); // false
var validationResults = validator.GetValidationResults("admin", "Username"); // 返回错误
validator.Validate("admin", "Username"); // 抛出 ValidationException

// 验证其他类型
var validator = new NotEqualToValidator(0);

var isValid = validator.IsValid(1); // true
var isValid = validator.IsValid(null); // true(null 被视为有效)
推荐使用 Validators 静态类

推荐通过 Validators.NotEqualTo(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
NotEqualToValidator_ValidationErrorThe field {0} cannot be equal to '{1}'.

8.4.43 NotNull 非 null 验证器

功能描述
用于验证值是否不为 null

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new NotNullValidator();

var isValid = validator.IsValid(null); // false
var validationResults = validator.GetValidationResults(null, "Name"); // 返回错误
validator.Validate(null, "Name"); // 抛出 ValidationException

// 验证非 null 值
var validator = new NotNullValidator();

var isValid = validator.IsValid("Hello"); // true
var isValid = validator.IsValid(0); // true
推荐使用 Validators 静态类

推荐通过 Validators.NotNull() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
NotNullValidator_ValidationErrorThe field {0} does not allow null values.

8.4.44 Null null 验证器

功能描述
用于验证值是否为 null

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new NullValidator();

var isValid = validator.IsValid("not null"); // false
var validationResults = validator.GetValidationResults("value", "Field"); // 返回错误
validator.Validate(new object(), "Field"); // 抛出 ValidationException

// 验证 null 值
var validator = new NullValidator();

var isValid = validator.IsValid(null); // true
var isValid = validator.IsValid((string?)null); // true
推荐使用 Validators 静态类

推荐通过 Validators.Null() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
NullValidator_ValidationErrorThe field {0} must be null.

8.4.45 Password 密码验证器

功能描述
用于验证密码是否符合安全策略,支持普通模式(8–64 位,含字母和数字)和强密码模式(12–64 位,必须包含大小写字母、数字和特殊字符)。

公开属性

属性类型默认值说明
Strongboolfalse是否启用强密码验证模式

使用示例

// 基础使用:普通密码规则
var validator = new PasswordValidator();

var isValid = validator.IsValid("12345678"); // false(无字母)
var validationResults = validator.GetValidationResults("weak", "Password"); // 返回错误
validator.Validate("pass", "Password"); // 抛出 ValidationException

// 启用强密码模式
var validator = new PasswordValidator { Strong = true };

var isValid = validator.IsValid("SecurePass123!"); // true
var isValid = validator.IsValid("Weak123"); // false(缺少大写或特殊字符)
推荐使用 Validators 静态类

推荐通过 Validators.Password() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
PasswordValidator_ValidationErrorThe field {0} has an invalid password format. It must be 8 to 64 characters long and contain at least one letter and one number.
PasswordValidator_ValidationError_StrongThe field {0} has an invalid password format. It must be 12 to 64 characters long and contain uppercase letters, lowercase letters, numbers, and special characters.

8.4.46 PhoneNumber 手机号(中国)验证器

功能描述
用于验证字符串是否为有效的中国大陆手机号码,支持带或不带国际区号(如 13800138000+8613800138000008613800138000)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new PhoneNumberValidator();

var isValid = validator.IsValid("1380013800"); // false(10 位)
var validationResults = validator.GetValidationResults("12345678901", "Phone"); // 返回错误
validator.Validate("invalid-phone", "Phone"); // 抛出 ValidationException

// 支持国际格式
var validator = new PhoneNumberValidator();

var isValid = validator.IsValid("13800138000"); // true
var isValid = validator.IsValid("+8613912345678"); // true
var isValid = validator.IsValid("008615012345678"); // true
推荐使用 Validators 静态类

推荐通过 Validators.PhoneNumber() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
PhoneNumberValidator_ValidationErrorThe field {0} is not a valid phone number.

8.4.47 PostalCode 邮政编码(中国)验证器

功能描述
用于验证字符串是否为有效的中国大陆邮政编码(6 位数字,符合中国邮政区域分配规则)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new PostalCodeValidator();

var isValid = validator.IsValid("10000"); // false(5 位)
var validationResults = validator.GetValidationResults("123456", "Zip"); // 返回错误(123456 不在有效区段)
validator.Validate("000000", "Zip"); // 抛出 ValidationException

// 验证有效邮编
var validator = new PostalCodeValidator();

var isValid = validator.IsValid("100000"); // true
var isValid = validator.IsValid("518000"); // true(深圳)
推荐使用 Validators 静态类

推荐通过 Validators.PostalCode() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
PostalCodeValidator_ValidationErrorThe field {0} is not a valid postal code.

8.4.48 Range 数值范围验证器

功能描述
用于验证数值是否在指定的最小值和最大值之间(可配置是否包含边界)。支持整数、浮点数及通过字符串指定的任意数值类型。

公开属性

属性类型默认值说明
Minimumobject允许的最小值(构造函数传入,不可变)
Maximumobject允许的最大值(构造函数传入,不可变)
OperandTypeType数值类型(如 typeof(int)typeof(double) 等)
MinimumIsExclusiveboolfalse是否排除最小值(即 > 而非 ≥)
MaximumIsExclusiveboolfalse是否排除最大值(即 < 而非 ≤)
ParseLimitsInInvariantCultureboolfalse是否使用固定区域性解析 Minimum/Maximum 字符串
ConvertValueInInvariantCultureboolfalse是否使用固定区域性转换被验证值

注:MinimumMaximumOperandType 由构造函数确定,不可修改;其余属性可在实例创建后设置。

使用示例

// 基础使用:整数范围 [0, 100]
var validator = new RangeValidator(0, 100);

var isValid = validator.IsValid(-1); // false
var validationResults = validator.GetValidationResults(150, "Score"); // 返回错误
validator.Validate(200, "Score"); // 抛出 ValidationException

// 排除边界:(0, 10)
var validator = new RangeValidator(0, 10)
{
MinimumIsExclusive = true,
MaximumIsExclusive = true
};

var isValid = validator.IsValid(0); // false
var isValid = validator.IsValid(10); // false
var isValid = validator.IsValid(5); // true
推荐使用 Validators 静态类

推荐通过 Validators.Range(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
RangeValidator_ValidationErrorThe field {0} must be between '{1}' and '{2}'.
RangeValidator_ValidationError_MinExclusiveThe field {0} must be between '{1}' exclusive and '{2}'.
RangeValidator_ValidationError_MaxExclusiveThe field {0} must be between '{1}' and '{2}' exclusive.
RangeValidator_ValidationError_MinExclusive_MaxExclusiveThe field {0} must be between '{1}' exclusive and '{2}' exclusive.

8.4.49 RegularExpression 正则表达式验证器

功能描述
用于验证字符串是否匹配指定的正则表达式模式。

公开属性

属性类型默认值说明
Patternstring正则表达式模式(通过构造函数传入,不可变)
MatchTimeoutInMillisecondsint2000单次匹配操作的超时时间(毫秒),可防止正则表达式回溯攻击

使用示例

// 基础使用:仅允许数字
var validator = new RegularExpressionValidator(@"^\d+$");

var isValid = validator.IsValid("abc"); // false
var validationResults = validator.GetValidationResults("12a3", "Code"); // 返回错误
validator.Validate("12.34", "Code"); // 抛出 ValidationException

// 自定义超时
var validator = new RegularExpressionValidator(@"^[A-Za-z0-9]{6,20}$")
{
MatchTimeoutInMilliseconds = 5000
};

var isValid = validator.IsValid("User123"); // true
var isValid = validator.IsValid("user@name"); // false
推荐使用 Validators 静态类

推荐通过 Validators.RegularExpression(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
RegularExpressionValidator_ValidationErrorThe field {0} must match the regular expression '{1}'.

8.4.50 Required 必填验证器

功能描述
用于验证值是否已提供(非 null)。默认情况下,空字符串也被视为无效,但可通过配置允许。

公开属性

属性类型默认值说明
AllowEmptyStringsboolfalse是否将空字符串("")视为有效值

注:该验证器具有高优先级(Priority = 10),通常在其他验证前执行。

使用示例

// 基础使用:不允许 null 或空字符串
var validator = new RequiredValidator();

var isValid = validator.IsValid(null); // false
var validationResults = validator.GetValidationResults("", "Name"); // 返回错误
validator.Validate(" ", "Name"); // true(空白字符串视为非空)

// 允许空字符串
var validator = new RequiredValidator { AllowEmptyStrings = true };

var isValid = validator.IsValid(""); // true
var isValid = validator.IsValid(null); // false
推荐使用 Validators 静态类

推荐通过 Validators.Required() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
RequiredValidator_ValidationErrorThe {0} field is required.

8.4.51 Single 单项验证器

功能描述
用于验证集合、数组或字符串是否仅包含一个元素(长度为 1)。null 值被视为有效。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new SingleValidator();

var isValid = validator.IsValid(new List<int>()); // false(空集合)
var validationResults = validator.GetValidationResults(new[] { 1, 2 }, "Items"); // 返回错误(多于一项)
validator.Validate("AB", "Code"); // 抛出 ValidationException

// 验证有效输入
var validator = new SingleValidator();

var isValid = validator.IsValid(new[] { "A" }); // true
var isValid = validator.IsValid("X"); // true(单字符字符串)
推荐使用 Validators 静态类

推荐通过 Validators.Single() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
SingleValidator_ValidationErrorThe field {0} only allows a single item.

8.4.52 StartsWith 开头字符串验证器

功能描述
用于验证字符串是否以指定的字符或字符串开头。

公开属性

属性类型默认值说明
SearchValuestring检索的值(通过构造函数传入,不可变)
ComparisonStringComparisonStringComparison.Ordinal字符串比较方式

使用示例

// 基础使用
var validator = new StartsWithValidator("https://");

var isValid = validator.IsValid("http://example.com"); // false
var validationResults = validator.GetValidationResults("ftp://site", "Url"); // 返回错误
validator.Validate("file://path", "Url"); // 抛出 ValidationException

// 自定义比较方式
var validator = new StartsWithValidator("ID") { Comparison = StringComparison.OrdinalIgnoreCase };

var isValid = validator.IsValid("id123"); // true
var isValid = validator.IsValid("Id_456"); // true
推荐使用 Validators 静态类

推荐通过 Validators.StartsWith(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
StartsWithValidator_ValidationErrorThe field {0} does not start with the string '{1}'.

8.4.53 StringContains 字符串包含验证器

功能描述
用于验证字符串是否包含指定的字符或子字符串。

公开属性

属性类型默认值说明
SearchValuestring要查找的字符或子字符串(通过构造函数传入,不可变)
ComparisonStringComparisonStringComparison.Ordinal字符串比较方式

使用示例

// 基础使用
var validator = new StringContainsValidator("@");

var isValid = validator.IsValid("userexample.com"); // false
var validationResults = validator.GetValidationResults("user#example", "Email"); // 返回错误
validator.Validate("user.example", "Email"); // 抛出 ValidationException

// 忽略大小写
var validator = new StringContainsValidator("ADMIN") { Comparison = StringComparison.OrdinalIgnoreCase };

var isValid = validator.IsValid("system_admin"); // true
var isValid = validator.IsValid("UserAdminRole"); // true
推荐使用 Validators 静态类

推荐通过 Validators.StringContains(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
StringContainsValidator_ValidationErrorThe field {0} does not contain the string '{1}'.

8.4.54 StringLength 字符串长度验证器

功能描述
用于验证字符串长度是否在指定范围内。默认仅设置最大长度,可额外配置最小长度。

公开属性

属性类型默认值说明
MaximumLengthint最大允许长度(通过构造函数传入,不可变)
MinimumLengthint0最小允许长度(可后续设置)

注:仅适用于字符串类型。若同时设置了最小和最大长度,将使用包含两者的错误信息。

使用示例

// 基础使用:最大长度为 10
var validator = new StringLengthValidator(10);

var isValid = validator.IsValid("12345678901"); // false
var validationResults = validator.GetValidationResults("TooLongString", "Name"); // 返回错误
validator.Validate("A".PadRight(11), "Name"); // 抛出 ValidationException

// 设置最小和最大长度
var validator = new StringLengthValidator(20) { MinimumLength = 5 };

var isValid = validator.IsValid("Hi"); // false(小于最小长度)
var isValid = validator.IsValid("ValidInput"); // true
推荐使用 Validators 静态类

推荐通过 Validators.StringLength(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
StringLengthValidator_ValidationErrorThe field {0} must be a string with a maximum length of '{1}'.
StringLengthValidator_ValidationError_MinimumLengthThe field {0} must be a string with a minimum length of '{2}' and a maximum length of '{1}'.

8.4.55 StringNotContains 字符串不包含验证器

功能描述
用于验证字符串是否不包含指定的字符或子字符串。

公开属性

属性类型默认值说明
SearchValuestring禁止出现的字符或子字符串(通过构造函数传入,不可变)
ComparisonStringComparisonStringComparison.Ordinal字符串比较方式

使用示例

// 基础使用:禁止包含 "<script>"
var validator = new StringNotContainsValidator("<script>");

var isValid = validator.IsValid("Hello <script>alert(1)</script>"); // false
var validationResults = validator.GetValidationResults("Click <script>", "Content"); // 返回错误
validator.Validate("Run<script>", "Content"); // 抛出 ValidationException

// 忽略大小写禁止关键词
var validator = new StringNotContainsValidator("ADMIN") { Comparison = StringComparison.OrdinalIgnoreCase };

var isValid = validator.IsValid("System admin panel"); // false
var isValid = validator.IsValid("User dashboard"); // true
推荐使用 Validators 静态类

推荐通过 Validators.StringNotContains(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
StringNotContainsValidator_ValidationErrorThe field {0} must not contain the string '{1}'.

8.4.56 StrongPassword 强密码验证器

功能描述
用于验证密码是否符合强密码策略:长度为 12–64 位,且必须包含大写字母、小写字母、数字和特殊字符(如 !@#$%^&*)。

公开属性

该验证器无额外公开属性(内部固定启用 Strong = true)。

使用示例

// 基础使用
var validator = new StrongPasswordValidator();

var isValid = validator.IsValid("weak123"); // false(缺少大写和特殊字符)
var validationResults = validator.GetValidationResults("Pass123!", "Password"); // 返回错误(长度不足 12)
validator.Validate("Short1!", "Password"); // 抛出 ValidationException

// 验证强密码
var validator = new StrongPasswordValidator();

var isValid = validator.IsValid("SecurePass123!"); // true
var isValid = validator.IsValid("MyP@ssw0rd2025#"); // true
推荐使用 Validators 静态类

推荐通过 Validators.StrongPassword() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
PasswordValidator_ValidationError_StrongThe field {0} has an invalid password format. It must be 12 to 64 characters long and contain uppercase letters, lowercase letters, numbers, and special characters.

8.4.57 Telephone 座机(电话)验证器

功能描述
用于验证字符串是否为有效的中国大陆座机号码格式,支持带或不带区号及分机号(如 010-12345678021-87654321-123 等)。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new TelephoneValidator();

var isValid = validator.IsValid("123456789"); // false(无区号且位数不符)
var validationResults = validator.GetValidationResults("010-1234567", "Phone"); // 返回错误(本地号不足 8 位)
validator.Validate("invalid-phone", "Phone"); // 抛出 ValidationException

// 验证有效座机
var validator = new TelephoneValidator();

var isValid = validator.IsValid("010-12345678"); // true
var isValid = validator.IsValid("021-87654321-123"); // true(含分机)
var isValid = validator.IsValid("400-123-4567"); // false(不符合座机格式)
推荐使用 Validators 静态类

推荐通过 Validators.Telephone() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
TelephoneValidator_ValidationErrorThe field {0} is not a valid telephone.

8.4.58 TimeOnly 时间验证器

功能描述
用于验证值是否为有效的 TimeOnly 类型或符合指定格式的时间字符串。

公开属性

属性类型默认值说明
Formatsstring[]允许的时间格式(如 "HH:mm:ss"
ProviderIFormatProvider?CultureInfo.InvariantCulture格式提供器
StyleDateTimeStylesDateTimeStyles.None日期解析样式,需与 Provider 搭配使用

注:Formats 通过构造函数传入,不可变;ProviderStyle 可在实例创建后修改。

使用示例

// 基础使用:允许任意标准时间格式
var validator = new TimeOnlyValidator();

var isValid = validator.IsValid("14:30:00"); // true
var validationResults = validator.GetValidationResults("25:00:00", "Time"); // 返回错误(无效时间)
validator.Validate("invalid", "Time"); // 抛出 ValidationException

// 指定允许的格式
var validator = new TimeOnlyValidator("HH:mm", "hh:mm tt")
{
Provider = CultureInfo.InvariantCulture,
Style = DateTimeStyles.None
};

var isValid = validator.IsValid("14:30"); // true
var isValid = validator.IsValid("02:30 PM"); // true
推荐使用 Validators 静态类

推荐通过 Validators.TimeOnly(...) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
TimeOnlyValidator_ValidationErrorThe field {0} must be a valid time.
TimeOnlyValidator_ValidationError_FormatsThe field {0} must be a valid time in the following format(s): {1}.

8.4.59 Url URL 地址验证器

功能描述
用于验证字符串是否为有效的 HTTP、HTTPS(默认)或 FTP(可选)协议的完整 URL 地址。

公开属性

属性类型默认值说明
SupportsFtpboolfalse是否允许 FTP 协议

注:URL 必须包含有效主机名(如 http://example.com),不接受 http:///path 等无效格式。

使用示例

// 基础使用:仅支持 HTTP/HTTPS
var validator = new UrlValidator();

var isValid = validator.IsValid("ftp://files.example.com"); // false
var validationResults = validator.GetValidationResults("invalid-url", "Link"); // 返回错误
validator.Validate("http:///missing-host", "Link"); // 抛出 ValidationException

// 启用 FTP 支持
var validator = new UrlValidator { SupportsFtp = true };

var isValid = validator.IsValid("https://api.example.com"); // true
var isValid = validator.IsValid("ftp://download.site/file.zip"); // true
推荐使用 Validators 静态类

推荐通过 Validators.Url() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
UrlValidator_ValidationErrorThe {0} field is not a valid fully-qualified http, https URL.
UrlValidator_ValidationError_SupportsFtpThe {0} field is not a valid fully-qualified http, https, or ftp URL.

8.4.60 UserName 用户名验证器

功能描述
用于验证用户名是否符合安全命名规范:长度为 4–16 位,以字母开头,仅允许字母、数字、下划线(_)和连字符(-),且不能包含空格、其他特殊字符或连续的特殊字符(如 __--),结尾必须为字母或数字。

公开属性

该验证器无额外公开属性。

使用示例

// 基础使用
var validator = new UserNameValidator();

var isValid = validator.IsValid("user__name"); // false(连续下划线)
var validationResults = validator.GetValidationResults("123user", "Username"); // 返回错误(未以字母开头)
validator.Validate("user name", "Username"); // 抛出 ValidationException(含空格)

// 验证有效用户名
var validator = new UserNameValidator();

var isValid = validator.IsValid("john_doe"); // true
var isValid = validator.IsValid("Admin-01"); // true
推荐使用 Validators 静态类

推荐通过 Validators.UserName() 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

资源键默认信息
UserNameValidator_ValidationErrorThe field {0} is not a valid username.

8.4.61 ValidatorProxy 验证器代理

功能描述
用于动态创建并代理另一个验证器实例,支持在运行时配置其属性或构造参数,适用于需要延迟初始化、依赖注入或上下文感知验证的场景。

公开属性

该验证器本身不直接暴露业务属性,而是通过 Configure 方法将配置转发给被代理的验证器。

使用示例

// 基础代理:包装一个 EmailAddressValidator
var proxy = new ValidatorProxy<EmailAddressValidator>();

var isValid = proxy.IsValid("user@example.com"); // true
var validationResults = proxy.GetValidationResults("invalid", "Email"); // 返回错误
proxy.Validate("bad-email", "Email"); // 抛出 ValidationException

// 配置被代理验证器
var proxy = new ValidatorProxy<RangeValidator>(0, 100)
.Configure(v => v.MinimumIsExclusive = true);

var isValid = proxy.IsValid(0); // false(已排除最小值)

高级用法:对象级代理(带上下文)

// 根据对象动态创建验证器
var proxy = new ValidatorProxy<User, RangeValidator>(
user => user.Age, // 被验证的值:Age 属性
(user, ctx) => new object[] { 0, user.MaxAllowedAge } // 动态构造参数
).Configure(v => v.MinimumIsExclusive = false);

var user = new User { Age = 25, MaxAllowedAge = 30 };
var isValid = proxy.IsValid(user, new ValidationContext<User>(user)); // true
推荐使用 Validators 静态类

虽然 ValidatorProxy 通常用于高级场景,但若需统一入口,可通过自定义扩展方法封装。

验证错误信息资源键

由被代理的验证器决定,代理本身不定义独立错误信息。

8.4.62 Composite 组合验证器

功能描述
用于将多个验证器组合为一个整体,并支持三种验证模式:

  • FailFast(默认):任一验证失败即停止,返回失败结果;
  • All:所有验证器必须全部通过;
  • Any:任意一个验证器通过即视为整体通过。

公开属性

属性类型默认值说明
ModeCompositeModeCompositeMode.FailFast验证执行模式

使用示例

// 基础使用:所有规则必须通过
var validator = new CompositeValidator<User>(builder =>
{
builder.Required().WithMessage("用户名不能为空");
builder.StringLength(3, 20).WithMessage("用户名长度必须在 3-20 之间");
});

var user = new User { Name = "" };
var isValid = validator.IsValid(user, new ValidationContext<User>(user)); // false
validator.Validate(user, new ValidationContext<User>(user)); // 抛出 ValidationException

// 使用 Any 模式:满足其一即可
var validator = new CompositeValidator<User>(builder =>
{
builder.EmailAddress();
builder.PhoneNumber();
}).UseRuleMode(RuleMode.Any);

var user1 = new User { Contact = "user@example.com" }; // 通过(邮箱有效)
var user2 = new User { Contact = "13800138000" }; // 通过(手机号有效)
var user3 = new User { Contact = "invalid" }; // 失败
推荐使用 Validators 静态类

推荐通过 Validators.Composite<T>(Action<FluentValidatorBuilder<T>>) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

默认使用各子验证器的错误信息。若设置了 ErrorMessage,则在结果首部插入自定义信息,其默认资源键为:

资源键默认信息
ValidatorBase_ValidationErrorThe field {0} is invalid.

8.4.63 Conditional 条件验证器

功能描述
用于根据运行时条件动态选择一组验证规则执行。支持多个条件分支,以及一个可选的默认规则(当所有条件都不满足时使用)。

公开属性

该验证器通过 ConditionBuilder<T> 链式构建,无直接公开属性。

使用示例

// 基础使用:根据用户类型选择不同规则
var validator = new ConditionalValidator<User>(builder =>
{
builder.When(u => u.Type == UserType.Admin)
.Then(v => v.Required().EmailAddress());
builder.When(u => u.Type == UserType.Guest)
.Then(v => v.StringLength(1, 10));
builder.Otherwise(v => v.Required().UserName());
});

var admin = new User { Type = UserType.Admin, Email = "" };
validator.Validate(admin, new ValidationContext<User>(admin)); // 抛出 Required/Email 错误

var guest = new User { Type = UserType.Guest, Name = "A".PadRight(11) };
validator.Validate(guest, new ValidationContext<User>(guest)); // 抛出 StringLength 错误

// 仅返回错误信息(不执行验证)
var validator = new ConditionalValidator<Order>(builder =>
{
builder.When(o => o.Amount <= 0)
.ThenMessage("订单金额必须大于 0");
builder.OtherwiseMessage("未知订单状态");
});
推荐使用 Validators 静态类

推荐通过 Validators.Conditional<T>(Action<ConditionBuilder<T>>) 工厂方法创建实例,便于未来扩展。

验证错误信息资源键

默认使用各子验证器的错误信息。若在 ThenMessageOtherwiseMessage 中设置了自定义信息,则直接使用该信息;若在 ConditionalValidator 上设置了 ErrorMessage,则在结果首部插入:

资源键默认信息
ValidatorBase_ValidationErrorThe field {0} is invalid.

8.4.64 Comparison 比较验证器抽象基类

功能描述
为所有基于值比较的验证器(如 GreaterThanLessThanOrEqualTo 等)提供统一的基类。它封装了空值处理、类型匹配检查和错误信息格式化逻辑,要求派生类实现具体的比较逻辑。

公开属性

属性类型默认值说明
CompareValueIComparable用于比较的基准值(通过构造函数传入,不可变)

使用示例

该类为抽象基类,不直接用于实例化,而是作为以下验证器的父类:

  • GreaterThanValidator
  • GreaterThanOrEqualToValidator
  • LessThanValidator
  • LessThanOrEqualToValidator
  • MaxValidator
  • MinValidator
// 示例:创建一个自定义比较验证器
public class NotEqualValidator : ComparisonValidator
{
public NotEqualValidator(IComparable compareValue)
: base(compareValue, nameof(ValidationMessages.NotEqualValidator_ValidationError))
{
}

protected override bool IsValid(IComparable value, IValidationContext? validationContext) =>
IsTypeMatchedToCompareValue(value) && value.CompareTo(CompareValue) != 0;
}

// 使用
var validator = new NotEqualValidator(0);
var isValid = validator.IsValid(1); // true
设计说明

此基类确保所有比较操作仅在类型一致时进行,避免跨类型比较导致的意外行为或异常。

验证错误信息资源键

由具体派生类指定,通常格式为:

资源键(示例)默认信息(示例)
{ValidatorName}_ValidationErrorThe field {0} must be {condition} '{1}'.

8.4.65 NumericComparison 数值比较验证器抽象基类

功能描述
为需要将输入值和比较基准值统一转换为 decimal 类型后再进行比较的验证器提供抽象基类。适用于需处理多种数值类型(如 intfloatdouble)并确保精度一致性的场景。

公开属性

属性类型默认值说明
CompareValueIComparable原始比较值(通过构造函数传入,不可变)

使用示例

// 自定义一个“必须为正数”的验证器
public class PositiveNumberValidator : NumericComparisonValidator
{
public PositiveNumberValidator()
: base(0m, nameof(ValidationMessages.PositiveNumberValidator_ValidationError))
{
}

protected override bool IsValid(decimal value, decimal compareValue) => value > compareValue;
}

// 使用
var validator = new PositiveNumberValidator();
var isValid = validator.IsValid(5); // true
var isValid = validator.IsValid(-1.5); // false
var isValid = validator.IsValid(0); // false
设计优势
  • 类型泛化:自动将 intlongfloatdoubledecimal 等转换为 decimal,避免类型不匹配。
  • 精度安全:使用 decimal 作为中间类型,适合金融、计量等对精度敏感的场景。
  • 简化实现:派生类只需实现 IsValid(decimal, decimal),无需处理类型转换逻辑。

验证错误信息资源键

由具体派生类指定,通常格式为:

资源键(示例)默认信息(示例)
{ValidatorName}_ValidationErrorThe field {0} must be {condition} '{1}'.

8.5 自定义验证器

文档编写中....