views:

730

answers:

3

As far as I know the System.ComponentModel.DataAnnotations.DataTypeAttribute not works in model validation in MVC v1. For example,

public class Model
{
  [DataType("EmailAddress")]
  public string Email {get; set;}
}

In the codes above, the Email property will not be validated in MVC v1. Is it working in MVC v2?

Thanks in advance.

+4  A: 

Like LukLed pointed out, DataTypeAttribute doesn't do any validation by default. But it does influence templates regarding how the data is presented.

For example if you call Html.DisplayFor() method on a model that has DataType(DataType.EmailAddress) attribute, it'll format its value with <a href="mailto:{0}">{0}</a> (at least in MVC RC2).

çağdaş
Thanks for point out that DataTypeAttribute is not a validation attribute.
Wen Q.
@Wayne: It actually is ValidationAttribute. It inherits from ValidationAttribute, but always returns true. You can override IsValid method and define your own, as it is in David Hayden's solution.
LukLed
@LukLed, It indeed inherits from ValidationAttribute. I wonder why. Anyway, will correct that part.
çağdaş
@çağdaş: `DataAnnotationsModelValidator` goes through every ValidationAttribute. DataTypeAttribute is ValidationAttribute, so it could be easily inherited and validation introduced. When you define your own data type, you can easily add validation.
LukLed
@LukLed, Thanks. I edited the answer again to delete the part where it said it's not used for validation.
çağdaş
+5  A: 

[DataType("EmailAddress")] doesn't influence validation by default. This is IsValid method of this attribute (from reflector):

public override bool IsValid(object value)
{
    return true;
}

This is example of custom DataTypeAttribute to validate Emails (taken from this site http://davidhayden.com/blog/dave/archive/2009/08/12/CustomDataTypeAttributeValidationCustomDisplay.aspx):

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple  = false)]
public class EmailAddressAttribute : DataTypeAttribute
{
    private readonly Regex regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compile

    public EmailAddressAttribute() : base(DataType.EmailAddress)
    {

    }

    public override bool IsValid(object value)
    {

        string str = Convert.ToString(value, CultureInfo.CurrentCulture);
        if (string.IsNullOrEmpty(str))
            return true;

        Match match = regex.Match(str);   
        return ((match.Success && (match.Index == 0)) && (match.Length == str.Length));
    }
}
LukLed
Thanx for this.
George Handlin
I think you want to make that regex static because setting the compiled option may cause compilation to be done everwhere the attribute is used and, if memory serves, generating a new in-memory assembly each time.
Mike Scott
@Mike Scott: New in-memory assembly? What do you mean by that?
LukLed
LukLed, what it says on the tin - an assembly created on the fly in memory ;-) Regex with the compiled option emits IL into an in-memory assembly. So to be sure you don't use up memory with each invocation, you should save the compiled regex instance and reuse it. see http://blogs.msdn.com/b/bclteam/archive/2004/11/12/256783.aspx.
Mike Scott
A: 

Check out Scott Guthrie's blog post on MVC 2 validation. It is excellent. http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

Rick