开发者

Client side validation not working when using the RegularExpressionAttribute

I can't get client side validation of regular expressions working with MVC3RTM. All other client side validation works when I comment out the RegularExpression attribute so I know it's the one causing me problems.

I have a simple model. (SiteText and SiteErrors are just resource files)

 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; }
    }

Here is the C# escaped regex string that I store in a constant.

^((?>[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)>)$

Here is the un-escaped version.

^((?>[a-zA-Z\d开发者_JAVA技巧!#$%&'*+\-/=?^_`{|}~]+\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)>)$

Could the regex perhaps be too long?


Regular expression arguments aside - have a look at my blog post about how to get Email validation working on the client using ASP.NET MVC 3 and unobtrusive validation.

This approach uses the built-in jQuery Validation email validation and not your own regex. But will use your regex on the server side. I don't know what sort of regex jQuery validation uses, so this could be a good or bad thing.

ASP.NET MVC 3 Email Validation with Unobtrusive jQuery Validation

It's extremely simply and if you want to change the regex, just plug your own one in there.

This is the guts of it:

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";
        }
    }
}


First lets take a closer look at that regex of yours in a verbose, well commented format:

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);

Note that this regex allows multiple words to appear before the actual email address. My testing shows that this email matching sub-expression actually works kinda' ok (although I have serious doubts about the literal IP domain subexpression.)

But before your question can be answered, we need to see how the regex is actually being compiled and applied in your code...

p.s. The most accurate (and readable by mere humans) email validation code I've seen is: PHP : Parsing Email Adresses in PHP By Cal Henderson.


try this instead:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜