【问题标题】:EmailAddress DataAnnotation marking as valid on View but ModelState.IsValid = false?EmailAddress DataAnnotation 在 View 上标记为有效但 ModelState.IsValid = false?
【发布时间】:2017-09-16 12:10:52
【问题描述】:

我正在使用 MVC5 并尝试验证表单。

当我在字段中插入无效的电子邮件地址时,它会显示错误消息

如果我插入 a@a(这是一个有效的电子邮件地址),则前端验证通过,但在后端,我的 ModelState 在 E-mail 字段中显示错误,说明这是无效的。

如果我插入 a@a.com,验证双方都会通过!

注意:与“电子邮件验证不适用于 MVC”相关的其他 SO 答案的很大一部分,解决方案是使用我已经在使用的 EmailAddress 属性。

查看

@using (Ajax.BeginForm("EnviarMensagemContato", "home", new AjaxOptions { HttpMethod = "POST", OnBegin = "showLoading", OnComplete = "showJsonModalMessage" }, new { @id = "contact-form" }))
{
    @Html.AntiForgeryToken()
    <div class="col-md-6 lateral-division">
        <div class="form-group">
            @Html.TextBoxFor(m => m.ContatoViewModel.Nome, new { @class = "form-control required", placeholder = "nome" })
            @Html.ValidationMessageFor(m => m.ContatoViewModel.Nome)
        </div>
        <div class="form-group">
            @Html.TextBoxFor(m => m.ContatoViewModel.EmailAddress, new { @class = "form-control required", placeholder = "email" })
            @Html.ValidationMessageFor(m => m.ContatoViewModel.EmailAddress)
        </div>
        <div class="form-group">
            @Html.TextAreaFor(m => m.ContatoViewModel.Mensagem, 4, 4, new { @class = "form-control required", placeholder = "mensagem" })
            @Html.ValidationMessageFor(m => m.ContatoViewModel.Mensagem)
        </div>
    </div>
    <div class="btn-group pull-right btn-send-message">
    <input type="submit" value="enviar" id="enviar-mensagem" class="btn btn-default" />
    </div>
}

型号

public class ContatoViewModel
{
    [Required(ErrorMessage="campo obrigatório"), 
    Display(Name = "nome")]
    public String Nome { get; set; }

    [Required(ErrorMessage = "campo obrigatório"), 
    Display(Name = "nome"), MaxLength(254,ErrorMessage="email inválido"), 
    EmailAddress(ErrorMessage="email inválido")]
    public String EmailAddress { get; set; }

    [Required(ErrorMessage = "campo obrigatório"), 
    Display(Name = "nome"), MaxLength(500, ErrorMessage = "maximo de 500 caracteres")]
    public String Mensagem { get; set; }
}

控制器

public JsonResult EnviarMensagemContato(ModelContainer model)
{
    try
    {
        if (ModelState.IsValid)
        {
            //zalgo
        } 
    }
}

【问题讨论】:

  • 您的视图模型似乎没有 EmailAddress 属性。
  • @qamar 它有,但 asp.net 出于某种原因将数据注释连接在一行中,即:[required(..), maxlength(..)] 而不是单独的行。它在代码上。问候”
  • a@a 不是有效的电子邮件地址。作为旁注,您可以看到属性 here 使用的正则表达式

标签: c# jquery asp.net-mvc validation


【解决方案1】:

我假设您在 ASP.NET MVC 项目中使用默认的 jQuery Validation 库。如果是这种情况,问题就在于用于验证电子邮件的正则表达式在 jQuery Validation 库和 EmailAddressAttribute 中不同,属性更严格。我的建议是覆盖 jQuery Validation 电子邮件方法,如下所示:

$.validator.methods.email = function (value, element) { 
     return this.optional(element) || /^((([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])))\.?$/.test(value);
}

正则表达式直接取自EmailAddressAttribute 源代码here。如果您更喜欢允许不带 TLD 的电子邮件(例如 user@localhost),您可以编写自己的属性,如 in this answer 讨论的那样,并从 jQuery Validation 库中放入正则表达式。这样,您将拥有相同的验证结果客户端和服务器端。

【讨论】:

    【解决方案2】:
        [Required(ErrorMessage = "The Email address is required")]
        [RegularExpression(RegularExpression.RegexEmail, ErrorMessage = "Invalid Email address")]
        public string Email { get; set; }
    

    在 RegularExpression.cs 文件中包含

        /// <summary>
        /// Regular expression for email
        /// </summary>
        public const string RegexEmail = @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}";
    

    【讨论】:

      【解决方案3】:

      我不认为 a@a 是一个有效的电子邮件地址,或者如果是,我认为属性不会考虑它。

      经过测试,如果我输入 a@a,我会收到客户端验证错误。我不输入 a@a.a

      如果您需要此类电子邮件有效,您可以使用自己的正则表达式。

      【讨论】:

        【解决方案4】:

        如果您需要细粒度的控制并让您的代码在您面前透明,我建议您不要依赖 HTML 助手来绘制您的控件并为您在客户端和服务器端执行验证。

        我将使用以下常规 exp 作为 mvc 模型属性。

        [Required]
        [RegularExpression(BusinessRules.Email,ErrorMessage = Messages.EmailNotValid)]
        public string LoginEmail { get; set; }
        

        BusinessRules.Email 在哪里

        public const string Email = "^[\\w!#$%&'*+\\-/=?\\^_`{|}~]+(\\.[\\w!#$%&'*+\\-/=?\\^_`{|}~]+)*@((([\\-\\w]+\\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\\.){3}[0-9]{1,3}))$";
        

        在客户端验证中,您只能根据需要确保电子邮件不为空。最后,客户端验证不如服务器端验证重要,因为它很容易被欺骗。

        【讨论】:

          【解决方案5】:

          像下面的代码一样一次表示一个数据注释是一种很好的做法,这也可能有助于解决您的错误。

              [Required(ErrorMessage="campo obrigatório")] 
              [Display(Name = "nome")]
              public String Nome { get; set; }
          

          【讨论】:

            【解决方案6】:

            有两个独立的控制点。如果您使用正确的比较一次,则不必再次检查该值以供以后使用。然后,使用正则表达式将解决问题。

            【讨论】:

              猜你喜欢
              • 2019-05-20
              • 2010-12-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多