如何用正则验证C#模型类的逗号分隔字符串并检测重复
要解决这个问题,我们得拆分两个核心需求:格式合法性验证(无空项、无末尾逗号、项符合规则)和重复项检测。正则表达式在处理重复项时局限性很大,尤其是当项的长度不固定时,所以最佳方案是结合正则做格式验证,再用自定义验证属性处理重复项。
1. 格式合法性的正则验证
首先,我们需要一个正则来确保字符串符合以下要求:
- 没有空的分隔项(比如
,,这种情况) - 末尾没有多余的逗号
- 每个项都是字母数字组合(匹配你给出的合法示例)
对应的正则表达式是:
^[A-Za-z0-9]+(,[A-Za-z0-9]+)*$
正则解释:
^[A-Za-z0-9]+:字符串开头必须是至少一个字母或数字(确保第一个项非空)(,[A-Za-z0-9]+)*:后面可以跟着零或多个「逗号+至少一个字母/数字」的组合(避免末尾逗号和空项)$:字符串必须在这里结束,确保没有多余字符
2. 重复项检测的自定义验证属性
正则很难直接检测任意长度项的重复,所以我们需要写一个自定义的ValidationAttribute来处理这个逻辑:
using System.ComponentModel.DataAnnotations; using System.Linq; public class NoDuplicateItemsAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 如果字段为空,Required属性会先处理,这里直接返回成功 if (value == null) return ValidationResult.Success; var inputString = value.ToString(); // 分割字符串,同时移除空项(防止正则漏检的情况) var items = inputString.Split(',', StringSplitOptions.RemoveEmptyEntries); // 检查去重后的数量是否和原数量一致,判断是否有重复 // 如果需要区分大小写,去掉StringComparer.OrdinalIgnoreCase即可 if (items.Distinct(StringComparer.OrdinalIgnoreCase).Count() != items.Length) { return new ValidationResult(ErrorMessage ?? "Duplicate Code."); } return ValidationResult.Success; } }
3. 最终的模型类
把这几个验证属性组合起来,应用到你的模型字段上:
using System.ComponentModel.DataAnnotations; public class YourModel { [Required(ErrorMessage = "Comma Separated String Required")] [RegularExpression(@"^[A-Za-z0-9]+(,[A-Za-z0-9]+)*$", ErrorMessage = "Invalid Comma Separated String.")] [NoDuplicateItems(ErrorMessage = "Duplicate Code.")] public string CommaSeparatedString { get; set; } }
验证效果测试
针对你给出的场景:
- ✅ 合法输入:
ASAEW1,ASAEW2,ASA,S4,ASAEW5,ASAEW6,ASAEW7→ 所有验证通过 - ❌ 重复项:
ASAEW1,ASAEW2,ASA,S4,ASAEW5,ASAEW6,ASAEW7,ASAEW6→ 自定义属性触发,返回「Duplicate Code.」 - ❌ 末尾逗号:
ASAEW1,ASAEW2,ASA,S4,ASAEW5,ASAEW6,ASAEW7,→ 正则不匹配,返回「Invalid Comma Separated String.」 - ❌ 空项:
ASAEW1,ASAEW2,,ASA,S4,ASAEW5,ASAEW6,ASAEW7→ 正则不匹配,返回「Invalid Comma Separated String.」
如果你的项允许其他字符(比如下划线),只需要调整正则中的字符集,比如把[A-Za-z0-9]改成[A-Za-z0-9_]即可。
内容的提问来源于stack exchange,提问作者Sachith Wickramaarachchi
相关产品推荐
相关产品推荐

