1

I am trying MVC's datatype attributes, and just created a simple scenario like the following:

The View:

@model MVC4.Models.Model

@{
    ViewBag.Title = "DataTypeAttribute";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

<h2>DataTypeAttribute</h2>


@using (Html.BeginForm("SubmitData", "Home"))
{
    <div>
        @Html.ValidationSummary()
    </div>

    @Html.EditorFor(m => m.Email)
    <br />
    <br />
    @Html.EditorFor(m => m.PostalCode)

    <br />
    <br />
    @Html.EditorFor(m => m.TextOnly)
    <br />
    <br />

    <button type="submit">Submit</button>
}

The Model:

public class Model
{
    [DataType(DataType.EmailAddress)]

    [Required]
    //[EmailAddress]
    public string Email { get; set; }

    [DataType(DataType.PostalCode)]
    public string PostalCode { get; set; }


    public string TextOnly { get; set; }
}

"SubmitData" is just a controller that, returns View(..., model) if ModelState.IsValid is false.

Although posts like this do a good job in tackling the differences between Html.TextBoxFor and Html.EditorFor, I could not find an answer as to why validation for the datatype EmailAddress will not work when using TextBoxFor. I did find people mentioning TextBoxFor does not take metadata into account, while EditorFor does.

But does this make sense ? So TextBoxFor does not offer support for client validations ?!

I wonder what is the reason for the difference between the two ?

1
  • Summarizing the answer: the new input types introduced with HTML 5, such as <input type='email' /> add automatic validation. TextBoxFor always generate inputs of type 'text', and therefore no built in validation is generated. On the other hand, EditorFor takes model fields metadata (data annotations) into account when generating the html for them, so a field marked with "DataType(DataType.EmailAddress)" will generate an input type='email', and thus the new built-in HTML 5 validation along with it. Commented Jun 25, 2015 at 9:45

1 Answer 1

3

TextBoxFor() does work with validations.

[DataType(DataType.EmailAddress)] is not a validation attribute. Its an attribute that determines the type of input to display by setting the type attribute in the rendered html. For example <input type="text" ..>, <input type="date" ..>, <input type="email" ..> in order to render the browsers implementation of a HTML4 datepicker, email input etc.. It works only for EditorFor() because TextBoxFor() as its name suggest generates and input with type="text"

If you want validation for an email address, then you use the [EmailAddress] attribute on your property.

[Required]
[EmailAddress]
public string Email { get; set; }

Edit (further to the comments)

One of the features of HTML5 is the ability to validate user data without relying on scripts. One such form of browser validation is using the type attribute. The use of [DataType(DataType.EmailAddress)] on a property that is rendered with @Html.EditorFor() adds type="email" to the input element. From the MDN documentation

email: The element represents one email address. Line breaks are automatically stripped from the input value. An invalid email address can be set, but the input field will only satisfy its constraints if the email address satisfies the ABNF production 1*( atext / "." ) "@" ldh-str 1*( "." ldh-str ) where atext is defined in RFC 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section 3.5.

If your are currently seeing a validation error message associated with the property, and you have not added the [EmailAddress] attribute, then it means that jquery.validate.js is not loaded and you are seeing the browsers error message associated with type="email".

When jquery.validate.js is loaded (correctly), the novalidate="novalidate" attribute is added to the form element, which specifies that form is not to be validated (using the HTML5 validation) when submitted. The relevant code from jquery.validate.js is (approx line 35)

// Add novalidate tag if HTML5.
this.attr('novalidate', 'novalidate');

This is added to prevent possible confusion between error messages displayed by browser validation and jquery unobtrusive validation.

As to why DataTypeAttribute attribute inherits ValidationAttribute when it does not actually do validation, from Brad Wilson himself in this answer

The reason it derives from ValidationAttribute is so that you could create a new custom data type class, which was both a DataType and a Validation, all wrapped up into one. It's an unfortunate side-effect of .NET not allowing multiple inheritance.

Sign up to request clarification or add additional context in comments.

16 Comments

At first your answer looked very promising, but after some testing I can say: 1) using [EmailAddress] and DataType(EmailAddress) has exactly the same effect. In other words, you say DataType is not a validation attribute, but it does add validation in this case. 2) using DataType(Text) or PostalCode create input which type is "text" in both cases, and look the same... if validations are not at stake, what's the point in using them ? In this case we know beforehand we will end up with text inputs anyway...
No it does not. I see the only script you have is jquery.validate.unobtrusive.min.js which on its own will do absolutely nothing. You need jquery.js and jquery.validate.js and jquery.validate.unobtrusive.js (in that order). And I also suggest you use @Html.ValidationMessageFor() associated with each control and change @Html.ValidationSummary() to @Html.ValidationSummary(true)
You should also inspect the html you generate. Validation attributes add various data-val attributes to the rendered html. All the [DataType] attribute does id set the appropriate type attribute
what about DataTypes such as Text and PostalCode, which render input which types are text ? What is the purpose of such datatypes then?
And from this link which I suggest you study. The DataType attributes are not validation attributes, they are used to tell the view engine how to render the HTML. In the example above, the DataType.Date attribute displays the movie dates as dates only, without time. For example, the following DataType attributes don't validate the format of the data:
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.