This is a field located in my viewmodel:
[Required(ErrorMessage = "Email is missing."), EmailAddress(ErrorMessage = "Email is not valid.")]
public string Email { get; set; }
(EmailAddress
is from the EmailAddressAttribute.EmailAddressAttribute()
type)
This is the relevant part from the HTML:
<div>
<label for="inputEmail">EMAIL</label>
<input id="inputEmail" ng-model="email" asp-for="Email" class="form-control" />
</div>
<div>
<span asp-validation-for="Email" class="text-danger"></span>
</div>
When I type myemail
in the email text box, it will say
Email is invalid
However, when typing myemail@email
, it will be viewed as correct by the view-model (only on the front-end).
public async Task<JsonResult> Register([FromForm]VisitViewModel vm)
Casting like this properly puts the ModelState
on invalid and rejects the email, so that part is okay.
According to this answer though, the frontend should indicate this as invalid
Can anybody explain what is happening here? I'm at an absolute loss.
There are inconsistencies in the way emails are validated between client and server.
jQuery Validation uses a regular expression defined in the HTML standard. According to that expression, email@email
is a valid email address.
The .Net EmailAddressAttribute
has it's own regular expression, which you can find here. According that that expression, email@email
is an invalid email address.
But it gets even more confusing! If you're creating a .Net Core app, targeting cross platform uses the CoreFX version of the attribute which doesn't appear to use a regular expression at all. According to that method, email@email
is a valid email address.
You see it for yourself by switching around values in the project.json
of a Core Console App:
public static void Main(string[] args)
{
var attr = new EmailAddressAttribute();
var email = "email@email";
var isValid = attr.IsValid(email); // false with "net452", true with "netcoreapp1.0"
}
The quickest fix that I can think of would be to change the regular expression in the jQuery Validate email method to match the one from .Net, or create your own validation method to add to it which checks for this particular case.
You can also just fallback on returning errors from the server which would show them a validation message for whatever is wrong with the ModelState
. It wouldn't be a real-time error but they would still get a nice message to deal with the improper email.