【问题标题】:Client side validation not working when using the RegularExpressionAttribute使用 RegularExpressionAttribute 时客户端验证不起作用
【发布时间】:2011-03-28 11:36:52
【问题描述】:

我无法对使用 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)>)$

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

【问题讨论】:

  • 到底是什么问题?该站点是否无法正常工作,或者验证是否总是失败?如果是这样,请举例说明应该匹配的字符串。

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


【解决方案1】:

除了正则表达式参数 - 请查看我的博客文章,了解如何使用 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";
        }
    }
}

【讨论】:

  • 自从您的代码发布和今天发布的 ASP.NET MVC 3 以来,一定发生了一些变化。在尝试编译您的代码时,您的方法“GetClientValidationRules”无法实现,因为它没有错误'System.Collections.Generic.IEnumerable' 的匹配返回类型。足够简单的修复,只需将 public IEnumerable GetClientValidationRules 更改为 public IEnumerable
  • @Charlino 链接已关闭
【解决方案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 域子表达式有严重的怀疑。)

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

附言我见过的最准确(并且人类可读的)电子邮件验证代码是:PHP : Parsing Email Adresses in PHPCal Henderson。

【讨论】:

  • 我删除了我过于自以为是的评论。我很抱歉。我只是想帮忙!
  • 感谢您的帮助相信我,冗长的解释肯定会对某人有用。有些人可能不喜欢被告知他们应该被枪杀:-)
【解决方案3】:

试试这个:

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

【讨论】:

  • 我可能应该提到我尝试了一个更简单的正则表达式并且它有效。感谢您的解决方案,尽管 reg ex 没有我希望的那么广泛。
  • 此正则表达式具有常用(但已过时且错误)的 TLD 表达式:\.[A-Za-z]{2,4},它无法匹配具有超过 4 个字符的有效域,例如.museum.travel.
  • 还要注意,这个正则表达式可能匹配一个电子邮件地址,但它不会验证它。验证电子邮件地址的正则表达式要复杂得多
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 2013-01-09
  • 2014-03-25
相关资源
最近更新 更多