0

On an asp.net mvc 5.2.4 model I have an email address field decorated thusly, with the System.ComponentModel.DataAnnotations.EmailAddressAttribute:

    [DataType(DataType.EmailAddress)]
    [EmailAddress(ErrorMessageResourceName = "EmailField", ErrorMessageResourceType = typeof(Messages))]
    public string EmailAddress { get; set; }

It renders html that looks like this, an input of type "email":

<input type="email".../>

If I enter an email address without a full domain (eg "tom@yahoo") it passes client side validation, but it fails server-side validation. I only have to worry about 2 browsers (Chrome and IE 11), and it passes both of them client-side.

I think I understand what is happening. jquery.validate.js, the client-side validation, is following the international standard, which allows for emails without domains. The server-side is using a RegEx expression as long as my arm (see https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/EmailAddressAttribute.cs) and throwing a validation error.

I'm guessing I'm not the first person to bump into this. Is there an attribute I can decorate an email address field with that corresponds exactly to input type="email" in the browser, so that if an email address passes client-side validation it will always pass server-side validation?

Tom Regan
  • 3,580
  • 4
  • 42
  • 71
  • Not quite sure what you claiming here. If you have client side validation enabled, then exactly the same regex is used on the client and server side, and including `[DataType(DataType.EmailAddress)]` is not required. Have you disabled mvc's client side validation (or not include the `jquery.validate.js` and `jquery.validate.unobtrusive.js` scripts)? –  Feb 26 '18 at 22:26
  • @StephenMuecke, yes, I am using jquery unobtrusive validation. The client and server are obviously using different validation though, that is why I posted the question. Are you saying I should remove the DataType attribute? – Tom Regan Feb 26 '18 at 22:29
  • Yes, remove it. –  Feb 26 '18 at 22:31
  • Even with the unnecessary `[DataType]` attribute, "tom@" will not pass mvc client side validation, so I can only assume it must be disabled, or not implemented correctly –  Feb 26 '18 at 22:49
  • I apologize, you are correct of course, "tom@" does not pass client-side validation, I mis-typed the example. What DOES pass client-side validation is "tom@yahoo", but this fails server-side validation. I do have client-side validation implemented correctly. I'm using jquery.validate v1.16.0 and putting a breakpoint on line 1356, and I can see that "tom@yahoo.com" passes client-side validation. I can also see that client-side validation uses a different regex than the validation attribute uses on the server-side. – Tom Regan Feb 27 '18 at 14:13
  • P.S. I tried removing the [DataType] attribute. As you noted it is not necessary, the input still renders of type "email", but unfortunately the problem of inconsistent validation remains. I assume the only fix here is to replace the EmailAddress validation attribute with a RegularExpression validation attribute and copy the regular expression from jquery.validate into the attribute. – Tom Regan Feb 27 '18 at 14:26
  • Either that, or override the `$.validator` to use the regex from the attribute –  Feb 28 '18 at 00:54

2 Answers2

1

You could write your own validator. You already know the regex that MS is using and if you feel it is the more accurate/correct for your needs then you can "reuse" (in quotes as you will likely have to format it differently) the regex in your client side validator. This requires that you create your own ValidationAttribute for server side validation & to wire up to the client side you'll implement the IClientValidatable interface & add a method on the js validator.

You have a leg up in that you don't have to write it from scratch either. You can use the source code for the EmailAddressAttribute to get you started.

http://ezzylearning.com/tutorial/creating-custom-validation-attribute-in-asp-net-mvc has a nice writeup.

MVC custom validation: compare two dates has another example of doing both server & client side with comparing two dates but the idea of what to implement & how is the same.

Kevin LaBranche
  • 20,908
  • 5
  • 52
  • 76
0

My workaround is to remove the EmailAddress attribute, copy the regular expression used by client-side validation (jquery.validate.js v1.16.0 line 1356) and use that in a RegularExpression validation attribute, so my code now looks like this:

    [DataType(DataType.EmailAddress)]
    [RegularExpression(EmailRegEx, ErrorMessageResourceName = "EmailField", ErrorMessageResourceType = typeof(Messages))]

Where "EmailRegEx" is a constant with this value:

^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
Tom Regan
  • 3,580
  • 4
  • 42
  • 71