31

我正在使用 CodeFirst Entitty 框架 5。我有一个代表用户的类。

public class User
{
    [Key]
    public int UserId { get; set; }

    [Url]
    [DataType(DataType.Url)]
    [Required(AllowEmptyStrings= true)]
    public string WebSite { get; set; }

    [Phone]
    [DataType(DataType.PhoneNumber)]
    [Required(AllowEmptyStrings = true)]
    public string Phone { get; set; }

    [Phone]
    [DataType(DataType.PhoneNumber)]
    [Required(AllowEmptyStrings = true)]
    public string Fax { get; set; }
}

我非常喜欢PhoneUrl属性的验证机制,但不幸的是,当标有这些属性的字段是我真正想要允许的空字符串时,验证失败。[Required(AllowEmptyStrings = true)]似乎不适用于PhoneUrl属性。这似乎也适用于其他一些 DataAnnotations 属性,例如EmailAddress.

有没有办法允许用此类属性标记的字段为空字符串?

4

4 回答 4

41

使用以下两个数据注释:

[Required(AllowEmptyStrings = true)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
于 2016-01-14T19:09:11.857 回答
23

验证属性[Phone][EmailAddress]将检查任何非空字符串值。因为该string类型本质上可以为空,所以传递给 ModelBinder 的空字符串被读取为null,从而通过了验证检查。

添加 [Required]属性时,字符串实际上变为不可为空。(如果使用 Code First,EF 将编写一个不可为空的数据库列的脚本。)ModelBinder 现在将一个空值解释为String.Empty- 这将使属性验证检查失败。

所以没有办法允许带有验证属性的空字符串,但是你可以允许字符串。您需要做的就是删除该[Required]属性。空白值null将被验证,非空白值将被验证。

就我而言,我正在从 CSV 文件中导入记录,并且遇到了这个问题,因为我跳过了普通的 ModelBinder。如果您正在做一些不寻常的事情,请务必在保存到数据模型之前进行手动检查:

Email = (record.Email == String.Empty) ? null : record.Email
于 2013-12-18T20:50:17.697 回答
1

我在下面做了类似的事情。

  [JsonProperty("phone")]
  [NullablePhone]
  public string Phone { get; set; }

/// <summary>
/// Validation attribute for phone numbers.
/// </summary>
/// <seealso cref="ValidationAttribute" />
public class NullablePhoneAttribute : ValidationAttribute
{
    /// <summary>
    /// Returns true if phone is empty or valid.
    /// </summary>
    /// <param name="value">The value of the object to validate.</param>
    /// <returns>
    ///   <see langword="true" /> if the specified value is valid; otherwise, <see langword="false" />.
    /// </returns>
    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }
        if (string.IsNullOrEmpty(value.ToString()))
        {
            return true;
        }
        PhoneAttribute phone = new PhoneAttribute();
        return phone.IsValid(value);
    }

}
于 2020-06-17T19:11:43.853 回答
0

我可以完成这项工作的唯一方法是获取 .Net 的源代码并自己调整它以允许电子邮件属性的可为空值。

代码可以在这里找到:https ://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/EmailAddressAttribute.cs

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class NullableEmailAddressAttribute : DataTypeAttribute
{

    // This attribute provides server-side email validation equivalent to jquery validate,
    // and therefore shares the same regular expression.  See unit tests for examples.
    private static Regex _regex = CreateRegEx();

    public NullableEmailAddressAttribute()
        : base(DataType.EmailAddress)
    {

        // DevDiv 468241: set DefaultErrorMessage not ErrorMessage, allowing user to set
        // ErrorMessageResourceType and ErrorMessageResourceName to use localized messages.
        // DefaultErrorMessage = DataAnnotationsResources.EmailAddressAttribute_Invalid;
    }

    public override bool IsValid(object value)
    {
        if (value == null)
            return true;

        string valueAsString = value as string;

        if (string.IsNullOrEmpty(valueAsString))
            return true;

        // Use RegEx implementation if it has been created, otherwise use a non RegEx version.
        if (_regex != null)
        {
            return valueAsString != null && _regex.Match(valueAsString).Length > 0;
        }
        else
        {
            int atCount = 0;

            foreach (char c in valueAsString)
            {
                if (c == '@')
                {
                    atCount++;
                }
            }

            return (valueAsString != null
            && atCount == 1
            && valueAsString[0] != '@'
            && valueAsString[valueAsString.Length - 1] != '@');
        }
    }

    private static Regex CreateRegEx()
    {
        // We only need to create the RegEx if this switch is enabled.
        //if (AppSettings.DisableRegEx)
        //{
        //    return null;
        //}

        const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
        const RegexOptions options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;

        // Set explicit regex match timeout, sufficient enough for email parsing
        // Unless the global REGEX_DEFAULT_MATCH_TIMEOUT is already set
        TimeSpan matchTimeout = TimeSpan.FromSeconds(2);

        try
        {
            if (AppDomain.CurrentDomain.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") == null)
            {
                return new Regex(pattern, options, matchTimeout);
            }
        }
        catch
        {
            // Fallback on error
        }

        // Legacy fallback (without explicit match timeout)
        return new Regex(pattern, options);
    }
}

用法是这样的:

    [NullableEmailAddress]
    public string DigitalInvoiceEmail { get; set; }
于 2021-06-24T20:34:46.317 回答