使用RegularExpressionAttribute时,客户端验证无效

时间:2011-03-28 11:36:53

标签: c# asp.net-mvc regex asp.net-mvc-3

我无法获得使用MVC3RTM的正则表达式的客户端验证。当我注释掉RegularExpression属性时,所有其他客户端验证都有效,所以我知道它是导致我出现问题的那个。

我有一个简单的模型。 (SiteText和SiteErrors只是资源文件)

 public class NewUser {

        [Required]
        [MultiCulturalDisplayName("UserName", typeof(SiteText))]
        public string UserName { get; set; }

        [Required]
        [AllowHtml]
        [RegularExpression(RegExConstants.EmailRegEx, ErrorMessageResourceType = typeof(SiteErrors), ErrorMessageResourceName = "EmailInvalid")]
        [DataType(DataType.EmailAddress)]
        [MultiCulturalDisplayName("EmailAddress", typeof(SiteText))]
        public string Email { get; set; }

        [Required]
        [ValidatePasswordLength]
        [DataType(DataType.Password)]
        [MultiCulturalDisplayName("Password", typeof(SiteText))]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [MultiCulturalDisplayName("PasswordConfirm", typeof(SiteText))]
        [Compare("Password", ErrorMessageResourceType = typeof(SiteErrors), ErrorMessageResourceName = "PasswordCompare")]
        public string ConfirmPassword { get; set; }
    }

这是我存储在常量中的C#转义正则表达式字符串。

^((?>[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+\\x20*|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\"\\x20*)*(?<angle><))?((?!\\.)(?>\\.?[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+)+|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\")@(((?!-)[a-zA-Z\\d\\-]+(?<!-)\\.)+[a-zA-Z]{2,}|\\[(((?(?<!\\[)\\.)(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)){4}|[a-zA-Z\\d\\-]*[a-zA-Z\\d]:((?=[\\x01-\\x7f])[^\\\\\\[\\]]|\\\\[\\x01-\\x7f])+)\\])(?(angle)>)$

这是未转义的版本。

^((?>[a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]+\x20*|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]+)+|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$

正则表达式可能太长了吗?

3 个答案:

答案 0 :(得分:3)

除了正则表达式参数 - 请查看我的博客文章,了解如何使用ASP.NET MVC 3和不显眼的验证在客户端上进行电子邮件验证。

此方法使用内置的jQuery Validation电子邮件验证,而不是您自己的正则表达式。但是会在服务器端使用你的正则表达式。我不知道jQuery验证使用什么样的正则表达式,所以这可能是好事还是坏事。

ASP.NET MVC 3 Email Validation with Unobtrusive jQuery Validation

这非常简单,如果你想改变正则表达式,只需插入你自己的正则表达式。

这是它的内脏:

namespace PageDesigners.Library.ValidationAttributes
{
    public class EmailAttribute : RegularExpressionAttribute, IClientValidatable
    {
        public EmailAttribute()
            : base(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                   @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                   @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")
        {
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var errorMessage = FormatErrorMessage(metadata.GetDisplayName());

            yield return new EmailValidationRule(errorMessage);
        }
    }

    public class EmailValidationRule : ModelClientValidationRule
    {
        public EmailValidationRule(string errorMessage)
        {
            ErrorMessage = errorMessage;
            ValidationType = "email";
        }
    }
}

答案 1 :(得分:2)

首先让我们以详细,评论很好的格式仔细研究你的正则表达式:

Regex regexObj = new Regex(
    @"# Match an email address with optional leading words.
    ^                                    # Anchor to start of string
    (                                    # $1: Stuff preceding email address.
      (?>                                # Either...
        [a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]   # A 'word' followed by
        +\x20*                           # zero or more spaces,
      | ""                               # or a double quoted string
        ( (?=[\x01-\x7f])[^""\\]         # consisting of either one regular
        | \\[\x01-\x7f]                  # or one escaped character,
        )*                               # zero or more, followed by
        ""\x20*                          # zero or more spaces.
      )*                                 # Zero or more preceding stuff.
      (?<angle><)                        # $angle: < required before email
    )?                                   # address if there is stuff before.
    (                                    # $2: Email address name portion.
      (?!\.)                             # Must not start with literal dot.
      (?>\.?                             # A dot separates each
        [a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]+  # name-word.
      )+                                 # One or more dot-separated name-words.
    | ""                                 # or a double quoted string
      ( (?=[\x01-\x7f])[^""\\]           # consisting of either one regular
      | \\[\x01-\x7f]                    # or one escaped character,
      )*                                 # zero or more.
      ""                                 # Closing quote.
    )                                    # End $2: Email address name portion.
    @                                    # @ separates name and domain portions.
    (                                    # $3: Email domain portion.
      ((?!-)[a-zA-Z\d\-]+(?<!-)\.)+      # One or more dot separated subdomains
      [a-zA-Z]{2,}                       # followed by top level domain,
    | \[                                 # or a IP literal host address
      (                                  # $4: A literal IP address.
        (                                # $5: An IPv4 address
          (?(?<!\[)\.)                   # Dot comes before all but first digit.
          (25[0-5]|2[0-4]\d|[01]?\d?\d)  # ($6:) Each digit is from 0-255.
        ){4}                             # Four dotted-quad numbers required.
      | [a-zA-Z\d\-]*[a-zA-Z\d]:         # Or a word followed by a colon
        (                                # ($6:) followed by
          (?=[\x01-\x7f])[^\\[\]]        # non-escaped ASCII char except '[]'
        |\\[\x01-\x7f]                   # or any escaped non-NULL, ASCII char
        )+                               # One or more of these following colon.
      )\]                                # End $4: The literal IP address.
    )                                    # End $3: Email domain portion.
    (?(angle)>)                          # If there was a <, match closing >.
    $                                    # Anchor to start of string.
    ", 
    RegexOptions.IgnorePatternWhitespace);

请注意,此正则表达式允许在实际电子邮件地址之前显示多个单词。我的测试显示这个电子邮件匹配子表达式实际上工作得很好(尽管我对文字IP域子表达式有严重怀疑。)

但在您的问题得到解答之前,我们需要了解正则表达式是如何在您的代码中实际编译和应用的......

P.S。我见过的最准确的(仅仅是人类可读的)电子邮件验证码是:PHP : Parsing Email Adresses in PHP作者:Cal Henderson。

答案 2 :(得分:0)

试试这个:

[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = " Invalid Email")]