我正在使用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; }
}
我非常喜欢Phone
和Url
属性的验证机制,但遗憾的是,当标记有这些属性的字段是我实际想要允许的空字符串时,验证失败。 [Required(AllowEmptyStrings = true)]
似乎不适用于Phone
或Url
属性。这似乎适用于其他一些DataAnnotations属性,如EmailAddress
。
是否有办法为标有此类属性的字段允许空字符串?
答案 0 :(得分:33)
使用以下两个数据注释:
[Required(AllowEmptyStrings = true)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
答案 1 :(得分:20)
[Phone]
和[EmailAddress]
等验证属性将检查任何非空字符串值。由于string
类型本质上是可空的,因此传递给ModelBinder的空字符串将被读取为null
,它将通过验证检查。
添加[Required]
属性时,字符串实际上变为不可为空。 (如果使用Code First,EF将编写一个不可为空的数据库列。)ModelBinder现在将空值解释为String.Empty
- 这将无法通过属性验证检查。
因此无法允许带有验证属性的空字符串,但您可以允许 null 字符串。您需要做的就是删除[Required]
属性。空值将为null
,并且将验证非空值。
在我的情况下,我从CSV文件导入记录,并且遇到了这个问题,因为我正在跳过普通的ModelBinder。如果您正在执行此类异常操作,请确保在保存到数据模型之前包含手动检查:
Email = (record.Email == String.Empty) ? null : record.Email
答案 2 :(得分:0)
我在下面做了类似的事情。
functions:
api:
name: an-existing-function-name-created-by-my-devops
答案 3 :(得分:0)
我能够完成这项工作的唯一方法是获取 .Net 的源代码并自己调整它以允许电子邮件属性的值为空。
[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; }