我一直在尝试使 EmailAddress 自定义数据注释属性正确验证电子邮件,但在我的测试中它似乎对我不起作用。
这是测试:
[Test]
public void ModelStateValidation()
{
var invalidEmails = new[] { "testtestcom", "test@testcom", "testtest.com" };
var validEmail = "test@test.com";
//Invalid Email addresses
foreach (var invalidEmail in invalidEmails)
{
var subscription = new SubscriberModel() { FirstName = "f", LastName = "l", Email = invalidEmail, ConfirmEmail = invalidEmail, DateSubscribed = DateTime.Now };
ValidateModelAsFalse(subscription);
}
var subscription2 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = "t", ConfirmEmail = "t", DateSubscribed = DateTime.Now };
ValidateModelAsFalse(subscription2);
//Valid Email address
var subscription3 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
ValidateModelAsTrue(subscription3);
//Last Name doesn't exists
var subscription4 = new SubscriberModel() { FirstName = "f", LastName = "", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
ValidateModelAsFalse(subscription4);
//First Name doesn't exists
var subscription5 = new SubscriberModel() { FirstName = "", LastName = "l", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
ValidateModelAsFalse(subscription5);
//Email addresses are equal
var subscription6 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = "test@test.com", ConfirmEmail = "test2@test.com", DateSubscribed = DateTime.Now };
ValidateModelAsFalse(subscription6);
}
private static void ValidateModelAsFalse(SubscriberModel subscription3)
{
SubscriptionController controller = new SubscriptionController();
controller.ValidateModel(subscription3);
AssertIsFalse(controller);
}
private static void ValidateModelAsTrue(SubscriberModel subscription3)
{
SubscriptionController controller = new SubscriptionController();
controller.ValidateModel(subscription3);
AssertIsTrue(controller);
}
private static void AssertIsTrue(SubscriptionController controller)
{
Assert.That(controller.ModelState.IsValid, Is.True);
}
private static void AssertIsFalse(SubscriptionController controller)
{
Assert.That(controller.ModelState.IsValid, Is.False);
}
这是 ValidateModel 方法:
<!-- language: c# -->
public static void ValidateModel<T>(this Controller controller, T model)
{
var validationContext = new ValidationContext(model, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(model, validationContext, validationResults);
foreach (var validationResult in validationResults)
{
controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
}
}
模型:
<!-- language: c# -->
public partial class SubscriberModel
{
public int SubscriberID { get; set; }
[Required]
[DisplayName("First Name")]
public string FirstName { get; set; }
[Required]
[DisplayName("Last Name")]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Compare("ConfirmEmail", ErrorMessage = "The emails must match")]
[DisplayName("E-mail")]
public string Email { get; set; }
[Required]
[DisplayName("Confirm E-mail")]
public string ConfirmEmail { get; set; }
[Required]
[DisplayName("Date Subscribed")]
public DateTime DateSubscribed { get; set; }
}
控制器:
public partial class SubscriptionController : Controller
{
public ActionResult Index()
{
return View();
}
[CaptchaValidator]
[HttpPost]
public ActionResult Index(SubscriberModel subscription, bool captchaValid)
{
subscription.DateSubscribed = DateTime.Now;
ModelStateValid = ModelState.IsValid;
if(captchaValid)
{
if (ModelState.IsValid)
{
var test = "";
}
}
return View(subscription);
}
}
电子邮件属性类:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public sealed class EmailAddressAttribute : ValidationAttribute, IClientValidatable
{
private static Regex _regex = new Regex(@"^((([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])))\.?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public EmailAddressAttribute()
: base()
{
ErrorMessage = "Invalid Email";
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
yield return new ModelClientValidationRule {
ValidationType = "email",
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
};
}
public override bool IsValid(object value)
{
if (value == null) {
return false;
}
string valueAsString = value as string;
return _regex.Match(valueAsString).Success;
}
}
IsValid 方法似乎可以按照我的意图验证电子邮件地址,但由于某种原因,当我在 Controller.ValidateModel 上运行单元测试时,它不会返回 false 并且与我的断言匹配。