C# DataTypeAttribute验证是否在MVC2中工作?

C# DataTypeAttribute验证是否在MVC2中工作?,c#,asp.net-mvc,validation,email,data-annotations,C#,Asp.net Mvc,Validation,Email,Data Annotations,据我所知,System.ComponentModel.DataAnnotations.DataTypeAttribute在MVC v1的模型验证中不起作用。比如说, public class Model { [DataType("EmailAddress")] public string Email {get; set;} } public class Model { [EmailAddress(ErrorMessage = "INVALID EMAIL")] publ

据我所知,System.ComponentModel.DataAnnotations.DataTypeAttribute在MVC v1的模型验证中不起作用。比如说,

public class Model
{
  [DataType("EmailAddress")]
  public string Email {get; set;}
}
public class Model
{
    [EmailAddress(ErrorMessage = "INVALID EMAIL")]
    public string Email {get; set;}
}
在上面的代码中,电子邮件属性将不会在MVC v1中验证。它在MVC v2中工作吗?

与此类似,默认情况下DataTypeAttribute不进行任何验证。但它确实会影响有关数据呈现方式的模板

例如,如果在具有
数据类型(DataType.EmailAddress)
属性的模型上调用
Html.DisplayFor()
方法,它将使用
格式化其值(至少在MVC RC2中是这样)。

[DataType(“EmailAddress”)]
默认情况下不会影响验证。这是此属性的
IsValid
方法(来自反射器):

这是用于验证电子邮件的自定义DataTypeAttribute示例(取自此网站):


查看Scott Guthrie关于MVC 2验证的博客文章。非常好。

或者,您可以直接在字段上使用RegularExpression属性,而不是创建自己的属性,该属性最终将检查正则表达式匹配

[RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = PaErrorMessages.InvalidEmailAddress)]
public string Email { get; set; }

从.NET 4.5开始,有,它正确地实现了
IsValid
方法。因此,如果您的目标是.NET 4.5,那么为了验证,请考虑使用“代码> EMAADADESREST属性< /代码>,而不是自定义的。比如说,

public class Model
{
  [DataType("EmailAddress")]
  public string Email {get; set;}
}
public class Model
{
    [EmailAddress(ErrorMessage = "INVALID EMAIL")]
    public string Email {get; set;}
}
如果您对
EmailAddressAttribute
的实现感到好奇,那么下面是该类的反编译(使用反编译器)源代码:

using System;
using System.ComponentModel.DataAnnotations.Resources;
using System.Text.RegularExpressions;

namespace System.ComponentModel.DataAnnotations
{
  [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
  public sealed class EmailAddressAttribute : DataTypeAttribute
  {
    private static Regex _regex = new Regex("^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);

    static EmailAddressAttribute()
    {
    }

    public EmailAddressAttribute()
      : base(DataType.EmailAddress)
    {
      this.ErrorMessage = DataAnnotationsResources.EmailAddressAttribute_Invalid;
    }

    public override bool IsValid(object value)
    {
      if (value == null)
        return true;
      string input = value as string;
      if (input != null)
        return EmailAddressAttribute._regex.Match(input).Length > 0;
      else
        return false;
    }
  }
}

感谢您指出DataTypeAttribute不是验证属性。@韦恩:它实际上是ValidationAttribute。它继承自ValidationAttribute,但始终返回true。您可以重写IsValid方法并定义自己的方法,就像在David Hayden的解决方案中一样。@LukLed,它确实继承自ValidationAttribute。我想知道为什么。无论如何,将更正该部分。
DataAnnotationsModelValidator
将遍历每个ValidationAttribute。DataTypeAttribute是ValidationAttribute,因此可以很容易地继承和引入验证。定义自己的数据类型时,可以轻松添加验证。@LukLed,谢谢。我再次编辑了答案,以删除其中表示不用于验证的部分。我认为您希望将该正则表达式设置为静态,因为设置compiled选项可能会导致编译在每个使用属性的位置都进行,并且,如果内存可用,则每次都会生成一个新的内存中程序集。@Mike Scott:新的内存中程序集?你这是什么意思?LukLed,它在锡上写的是什么-一个在内存中动态创建的程序集;-)带有compiled选项的正则表达式将IL发送到内存中的程序集中。因此,为了确保每次调用都不会耗尽内存,应该保存已编译的regex实例并重用它。看。@Mike Scott:你说得对,但如果我没弄错的话,一个属性在每个类中只实例化一次,而不是每个对象。这意味着在实践中,成本非常小。然而,你是对的,它是静态的,没有成本。如果语言允许,应该是常量。@skrebbel,那么如果您将属性放在10个类上,这是否意味着该属性有10个实例化,因此为同一正则表达式创建了10个内存程序集?