Tuesday, March 27, 2012

ASP.Net MVC 3 : Why [DataType] is not validating email?

When we search for how to do validations in MVC 3 we normally get sites which tell to put a DataType attribute on the model property. It is pretty straight forward. Last week I was doing some customization to the thinktecture's identityserver to have users registration and used the same attributes for validation. The requirement is to have e-mail as username. So I just accept the email and used the same to pass to Membership as username while creating user.I didn't give much time for unit testing the validation as I am in an impression that it is from the framework and it should work.

When the app reached next stage an issue popped up related to sending the confirmation mail. I was using the framework classes for sending mails along with the mail server credentials in the web.config. That was an issue with the credential but it made me to unit test missed features too. It was a shock that the email validation is not happening. Its allowing users to register with non-email format as username.Below is the model for the user registration.

    public class RegisterUserModel
    {
        [Required]
        [DataType(DataType.Password)]
        [DisplayName("Password")]
        [StringLength(25,MinimumLength = 6,ErrorMessage ="Password length should be between 6-25")]
        public string Password { getset; }
 
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { getset; }
 
        [Required]
        [DataType(DataType.EmailAddress, ErrorMessage = "Please enter valid email address")]
        [DisplayName("E-mail")]
        public string eMail { getset; }
 
        [Required]
        [DisplayName("Password question")]
        public string PasswordQuestion { getset; }
 
        [DataType(DataType.Password)]
        [Display(Name = "Password question answer")]
        public string PasswordQuestionAnswer { getset; }
    }

The google started from there. First suggestion was to enable the client side validation in web.config.It was already present

   <add key="ClientValidationEnabled" value="true"/>
   <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
 
Then people were suggesting to have the correct js files in the view.That too was there.

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

Another suggestion was to put the type attribute forcefully. I tried as below but didn't give any positive result.
@Html.TextBoxFor(m => m.Email, new { type = "email" })


Finally there were suggestions to use ASP.Net MVC 3 futures which is coming through a nuget package. But I was not interested to add one more nuget package to the application as it is already flooded with nuget packs.So I decided to reflect the code of DataType attribute. It was another shock the DataAttribute.IsValid method is at all implemented.


Yes its time to install the MVC 3 futures which has the [EmailAddress] attribute which does the real validation.Below are the steps to install and get the email validation working in Asp.Net MVC 3
  1. Install the nuget package for MVC3 futures.
  2. Import the namespace Microsoft.Web.Mvc into our model.
  3. Add the EmailAddress attribute to the property which corresponds to email address.
[Required]
[EmailAddress(ErrorMessage = "Please enter valid email address")]
[DataType(DataType.EmailAddress, ErrorMessage = "Please enter valid email address")]
[DisplayName("E-mail")]
public string eMail { getset; }


This silly thing took my 3Hrs. I would have completed writing a validation class myself if the DataType attribute was not there with DataType.EmailAddress.

No comments: