ASP.NET Core MVC如何实现基于公司选项的自定义邮箱域名验证
解决方案
你需要的关联字段校验可通过自定义Validation Attribute实现,分为服务端校验(必做,可防止前端绕过校验)和客户端校验(可选,提升用户体验)两部分:
第一步:实现自定义校验特性
新建CompanyEmailDomainAttribute.cs类,代码如下:
using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; public class CompanyEmailDomainAttribute : ValidationAttribute, IClientModelValidator { private readonly string _companyPropertyName; // 公司与对应邮箱后缀的映射,可按需抽到配置文件/数据库中更灵活 private readonly Dictionary<string, string> _companyDomainMap = new() { {"ibm", "@ibm.com"}, {"microsoft", "@microsoft.com"}, {"apple", "@apple.com"} }; public CompanyEmailDomainAttribute(string companyPropertyName) { _companyPropertyName = companyPropertyName; } // 服务端校验逻辑 protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 获取当前提交的模型实例 var model = validationContext.ObjectInstance; // 读取关联的公司字段取值 var companyProperty = model.GetType().GetProperty(_companyPropertyName); if (companyProperty == null) { return new ValidationResult($"找不到关联字段{_companyPropertyName}"); } var selectedCompany = companyProperty.GetValue(model)?.ToString(); var emailValue = value?.ToString(); // 空值校验已经由[Required]、[EmailAddress]特性处理,此处仅做非空时的后缀匹配 if (string.IsNullOrEmpty(selectedCompany) || string.IsNullOrEmpty(emailValue)) { return ValidationResult.Success; } // 匹配邮箱后缀 if (_companyDomainMap.TryGetValue(selectedCompany.ToLower(), out var requiredSuffix)) { if (!emailValue.EndsWith(requiredSuffix, StringComparison.OrdinalIgnoreCase)) { return new ValidationResult(ErrorMessage ?? $"所选公司对应的邮箱后缀必须为{requiredSuffix}"); } } return ValidationResult.Success; } // 注入客户端校验需要的参数 public void AddValidation(ClientModelValidationContext context) { context.Attributes.Add("data-val", "true"); context.Attributes.Add("data-val-companyemaildomain", ErrorMessage ?? "邮箱后缀与所选公司不匹配"); context.Attributes.Add("data-val-companyemaildomain-companyfield", _companyPropertyName); } }
第二步:修改模型绑定特性
给Email属性加上刚才实现的自定义校验特性即可:
[Required] [EmailAddress] [Display(Name = "Email")] // 新增这行,传入关联的公司字段名 [CompanyEmailDomain(nameof(Company), ErrorMessage = "邮箱后缀与所选公司不匹配")] public string Email { get; set; } [Required(ErrorMessage = "Please choose which Company you are working for")] [DataType(DataType.Text)] [Display(Name = "Company")] public string Company{ get; set; }
到这里服务端校验已经完全生效,即使用户禁用JS、绕过前端校验,提交请求时服务端也会自动完成校验逻辑。
第三步:实现客户端实时校验(可选)
如果需要前端实时提示错误,不需要提交表单就能校验,可按如下步骤操作:
- 确保页面已经引入默认校验依赖的JS文件:
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
- 新增自定义校验的JS规则:
// 注册自定义校验规则 $.validator.addMethod("companyemaildomain", function (value, element, params) { if (!value) return true; // 读取下拉选项自定义属性的域名配置 var selectedOption = $(`#${params.companyFieldId}`).find("option:selected"); var requiredSuffix = "@" + selectedOption.attr("email-domain"); if (!requiredSuffix || requiredSuffix == "@") return true; // 不区分大小写匹配后缀 return value.toLowerCase().endsWith(requiredSuffix.toLowerCase()); }); // 注册Unobtrusive适配器,适配自动生成的data属性 $.validator.unobtrusive.adapters.add("companyemaildomain", ["companyfield"], function (options) { options.rules["companyemaildomain"] = { companyFieldId: options.element.name.replace(options.propertyName, options.params.companyfield).replaceAll(".", "_") }; options.messages["companyemaildomain"] = options.message; });
小提示:你提供的表单代码里IBM的option标签少了左尖括号,修正为
<option value="ibm" email-domain="ibm.com">IBM</option>即可正常使用。
内容的提问来源于stack exchange,提问作者Mohammed Abed
相关产品推荐
相关产品推荐

