私は、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);
}
}
EmailAttribute クラス:
[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 が返されず、アサーションと一致しません。