我一直在努力使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并匹配我的断言。
答案 0 :(得分:0)
我曾经使用过类似的东西,实现IClientValidatable接口只是第一步。然后我不得不在客户端添加jQuery验证。我认为自定义验证只能使用jQuery在客户端上执行
这是一个例子:
<script type="text/javascript">
(function ($) {
$.validator.addMethod("yourValidationTypeName", function (value, element) {
//do validation here
});
$.validator.unobtrusive.adapters.addBool("yourValidationTypeName");
} (jQuery));
</script>
使用内置属性[Regularexpression]启用不支持的javascript和客户端验证可能会解决您的问题。
如果我错了,请纠正我,但我不是MVC3的专家