.NET 8中可空EmailAddress验证失效问题求助
问题:.NET 8中EmailAddress验证对NULL字段触发错误
场景还原
Debtor模型包含两个带EmailAddress验证的可空字符串字段:
[EmailAddress(ErrorMessage = "Contact e-mailadres moet een geldig formaat zijn.")] public string? ContactEmail { get; set; } [EmailAddress(ErrorMessage = "Factuur e-mailadres moet een geldig formaat zijn.")] public string? InvoiceEmail { get; set; }
通过EF Core从SQL数据库获取数据:
Context = _dbContext.CreateDbContext(); _debtor = await Context.Debtors?.SingleOrDefaultAsync(c => c.Id == DebtorId);
数据库中这两个字段的值为NULL,但进入编辑页面后,字段值变为空字符串,保存时触发EmailAddress的验证错误。相同代码在.NET 7中无此问题。
已尝试添加DisplayFormat特性,但问题未解决:
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Null]")] [EmailAddress(ErrorMessage = "Contact e-mailadres moet een geldig formaat zijn.")] public string? ContactEmail { get; set; } [DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Null]")] [EmailAddress(ErrorMessage = "Factuur e-mailadres moet een geldig formaat zijn.")] public string? InvoiceEmail { get; set; }
.NET 8相关变更
.NET 8对数据验证和模型绑定逻辑做了两处关键调整:
EmailAddressAttribute现在会对空字符串执行格式验证,而.NET 7及更早版本中空字符串会被视为有效;- ASP.NET Core默认模型绑定行为变更:表单提交的空值会被绑定为空字符串,而非NULL,即使字段是可空字符串类型。
解决方法
方法1:自定义可选Email验证特性
创建忽略空值的自定义验证特性,替代默认的EmailAddressAttribute:
public class OptionalEmailAddressAttribute : EmailAddressAttribute { public OptionalEmailAddressAttribute() { ErrorMessage = "Contact e-mailadres moet een geldig formaat zijn."; } public override bool IsValid(object? value) { // 空值或空字符串直接判定为有效 if (value is null || string.IsNullOrWhiteSpace(value.ToString())) { return true; } return base.IsValid(value); } }
替换模型中的特性:
[OptionalEmailAddress] public string? ContactEmail { get; set; } [OptionalEmailAddress(ErrorMessage = "Factuur e-mailadres moet een geldig formaat zijn.")] public string? InvoiceEmail { get; set; }
方法2:全局配置模型绑定转空值为NULL
在Program.cs中配置模型绑定选项,将表单提交的空字符串自动转为NULL:
builder.Services.AddControllersWithViews() .AddMvcOptions(options => { options.ModelMetadataDetailsProviders.Add(new EmptyStringFormValueMetadataProvider()); });
方法3:手动控制验证逻辑
让模型实现IValidatableObject,在自定义验证逻辑中跳过空值的Email格式检查:
public class Debtor : IValidatableObject { [EmailAddress(ErrorMessage = "Contact e-mailadres moet een geldig formaat zijn.")] public string? ContactEmail { get; set; } [EmailAddress(ErrorMessage = "Factuur e-mailadres moet een geldig formaat zijn.")] public string? InvoiceEmail { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { if (!string.IsNullOrWhiteSpace(ContactEmail) && !new EmailAddressAttribute().IsValid(ContactEmail)) { yield return new ValidationResult("Contact e-mailadres moet een geldig formaat zijn.", new[] { nameof(ContactEmail) }); } if (!string.IsNullOrWhiteSpace(InvoiceEmail) && !new EmailAddressAttribute().IsValid(InvoiceEmail)) { yield return new ValidationResult("Factuur e-mailadres moet een geldig formaat zijn.", new[] { nameof(InvoiceEmail) }); } } }
总结
优先推荐方法1或方法2:方法1针对单个字段灵活控制验证规则,方法2全局统一处理空值绑定行为,都能彻底解决问题。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

