服务器端自定义数据注释验证MVC 3

时间:2012-07-13 13:31:16

标签: c# asp.net-mvc-3 email-validation

我一直在努力使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并匹配我的断言。

1 个答案:

答案 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的专家