You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:41:22