undefined is our god
undefined is our god

Reputation: 511

EmailAddress DataAnnotation marking as valid on View but ModelState.IsValid = false?

I'm using MVC5 and trying to validate a form.

When I insert an invalid email address on the field, it shows the error message

enter image description here

If I insert a@a (which is a valid email address), the front-end validation pass, but on back end, my ModelState shows an error on the E-mail field, telling that is invalid.

If I insert [email protected], both validation sides pass!

Note: Great part of the other SO answers related to "email validation not working on MVC", the solution was to use the EmailAddress attribute, which i'm already using.

View

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

Model

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

Controller

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

Upvotes: 1

Views: 2013

Answers (6)

ebejko
ebejko

Reputation: 36

I presume you're using the default jQuery Validation library in an ASP.NET MVC project. If that's the case, the problem resides in the fact that the regular expression used to validate an email is different in the jQuery Validation library and the EmailAddressAttribute, with the attribute being more strict. My suggestion would be to override the jQuery Validation email method as follows:

$.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);
}

The regular expression is taken directly from the EmailAddressAttribute source code here. If you prefer to allow emails without a TLD (like user@localhost), you could write your own attribute as discussed in this answer and put the regular expression from the jQuery Validation library. This way you would have the same validation result client and server side.

Upvotes: 2

Mayank Prajapati
Mayank Prajapati

Reputation: 37

    [Required(ErrorMessage = "The Email address is required")]
    [RegularExpression(RegularExpression.RegexEmail, ErrorMessage = "Invalid Email address")]
    public string Email { get; set; }

In RegularExpression.cs file include

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

Upvotes: 1

Tunahan
Tunahan

Reputation: 303

There are two separate control points. If you use the correct comparison once, you don't have to check the value again for later usage. Then, using regular expression will solve the problem.

Upvotes: 0

Plumbus
Plumbus

Reputation: 31

It is good practice to represent you data annotations one at a time like the following code, this may also help with your error.

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

Upvotes: 0

Houssam Hamdan
Houssam Hamdan

Reputation: 908

If you need fine grained control and have your code transparent in front of you, i recommend you dont rely on HTML helpers to draw your controls and perform the validation on client side and server side for you.

I would use the following regular exp as mvc model attribute.

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

Where BusinessRules.Email is

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

On the client side validation, you can only make sure that email is not empty if you want. At the end, client side validation is not as important as server side validation since it can be easily spoofed.

Upvotes: 1

Etienne
Etienne

Reputation: 1106

I don't think a@a is a valid email address, or if it is, I don't think the Attribute takes it into account.

Having tested this, if I enter a@a I get client side validation error. I don't if I enter [email protected]

If you need this kind of email to be valid you can probably use your own regex expression.

Upvotes: 0

Related Questions