返回首页

简介
这是一个很基本的介绍,使用新的功能发布。NET 3.5.1 SP1中引入了一个新的DLL,System.ComponentModel.DataAnnotations。这个新的DLL允许你添加属性对象的属性执行验证,而不是正常的ASP.NET验证程序。背景
主要的原因,我开始寻找到System.ComponentModel.DataAnnotations命名空间,所以我可以清理我的ASPX页面。虽然新的属性没有(至少不是从我所发现的)客户端验证,它极大的帮助,在您的验证逻辑保存在一个地方。您的网站可能会使用相同的对象上的许多页面,如果该字段是可编辑的,你必须quot;剪切/ pastequot;从一页页的验证逻辑。使用新的属性,你可以保持您的验证逻辑与财产本身,而开发商只需要添加一个自定义验证。使用代码
我喜欢容易阅读的代码,所以希望我在这里已经提出了一些。这是一个标准的VS 2008文件系统网站。解压,添加一个引用System.ComponentModel.DataAnnotations.dll,并运行。
注意,Default.aspx页面上,我有几个控件与最后一个使用正常的验证控件(结束日期),。
让我们开始这个项目最重要的一条,自定义验证类。我创建了一个标准的类称为"CustomValidatorquot;从BaseValidator继承。有一个方法,必须重写,EvaluateIsValid,我已经添加了两个属性举行的属性的名称和验证时要使用的对象类型。

public class CustomValidator : BaseValidator

{

    protected override bool EvaluateIsValid()

    {

    }



    ///<summary>

    /// Name of property in our object that has the DataAnnotation 

    /// attributes to use for validation

    ///</summary>

    public string PropertyName { get; set; }



    /// <summary>

    /// Object type we need to get so we can use reflection to find the property

    /// </summary>

    public string ObjectType { get; set; }



}

上面显示的是基本的类的定义,我们实施验证逻辑。我们需要添加一些基本的逻辑的EvaluateIsValid方法,以确保用户给了我们所需要的最低限度的信息。{C}
关于这点没什么特别的,只是确保用户给我们的属性的名称和拥有财产的对象的名称。这是设置。aspx页面中,我们将得到那块位。下一步,我们需要找到网页上的控制,我们需要验证。在这一点上,我们只验证的文本框(虽然我也没有把DropDownList的一些逻辑)。
// Find the control to validate so we can get the value to validate

Control Ctrl = FindControl(ControlToValidate);

string value;



if (Ctrl is TextBox)

{

    value = ((TextBox)Ctrl).Text;

}

else if (Ctrl is DropDownList)

{

    value = ((DropDownList)Ctrl).SelectedValue;

}

else

{

    // At this point we are only using this for Textbox and DropDown

    return false;

}

再次没什么特别的,只要找到控制和得到的值进行验证。使用标准"; FindControlquot方法所有ASP.NET开发人员应该使用。
现在到了有趣的东西。现在,我们已确保用户给我们的对象/属性的名称,我们有我们需要得到一个值对象。
// Find the object type that has our property

Type t = Type.GetType(ObjectType);



if (t == null)

    throw new NullReferenceException("Failed to find type.");



// Get the property we need to find the attributes for validation



PropertyInfo prop = t.GetProperty(PropertyName);



if(prop == null)

   throw new NullReferenceException("Failed to find property.");

如果你还没有使用反射之前,上面的代码可能是神秘的。这是相当简单的。 Type.GetType()得到我们的类的类型,对我们来说,这是我创建的一个成员类。 t.GetProperty()得到的属性的名称,在这种情况下,财产,我们在我们的aspx页面。指定。
这些行未来数可以排除在外,如果你不使用的DisplayNameAttribute,但他们都得心应手,如果你的属性的名称是类似"; MemberBillingZipCodequot;,你真的宁愿以显示";邮编Codequot;到用户,而不是。
string FriendlyName;



// This maps back to the DisplayName() attribute on the property

DisplayNameAttribute display = prop.GetCustomAttributes(

  typeof(DisplayNameAttribute), true).OfType<DisplayNameAttribute>().FirstOrDefault();



// If the developer added a DisplayName attribute then use it instead of the

// standard property name

if (display != null)

    FriendlyName = display.DisplayName;

else

    FriendlyName = prop.Name;

DisplayNameAttribute是,我们就可以对我们的物业使用,以表明我们要显示我们的用户更友好的名称。如果开发人员添加了这个属性,我们使用它,如果没有,我们使用的属性的名称。
现在到真正的验证:
// Find only the ValidationAttribute for this property. If you leave off the

// "typeof(ValidationAttribute)" you would get all custom attributes on this property.

// Also note the "as ValidationAttribute[]"

ValidationAttribute[] attribs = prop.GetCustomAttributes(

     typeof(ValidationAttribute), true) as ValidationAttribute[];



// Iterate over attributes and evaluate each DataAnnotation.

// Note I stop once I find the first failure. You can change this to build

// a list of all failures in validation for a property.

for (int i = 0; i < attribs.Length; i++)

{

     if (!attribs[i].IsValid(value))

     {

       // You can use the ErrorMessage param of the Required, StringLength etc

       // attribute if you have a very specific error message you want shown

       // but take a look at not adding it and letting the built in function

       // FormatErrorMessage do it.

       ErrorMessage = attribs[i].FormatErrorMessage(FriendlyName);

       ToolTip = ErrorMessage;

       return false;

     }

}

这是真正的逻辑肉。我们有我们的支柱变量,这是我们的财产,所以我们可以检查它,得到它的所有ValidationAttributes和迭代它们。每个属性都有其自己的"; IsValidquot;我们通过我们的价值,如果验证失败,我们让框架为我们建立一个错误消息,除非我们已经指定了一个方法。
所以,现在,我们需要一个对象来验证。我创建了一个"; Memberquot;类如下所示:
namespace DA.Examples

{

   public class Member

   {

      [Required(), StringLength(20), DisplayName("First Name")]

      public string FirstName { get; set; }



      [Required(), StringLength(20), DisplayName("Last Name")]

      public string LastName { get; set; }



      /// Notice this one has a "ErrorMessage" param

      [Required(), Range(18, 99, ErrorMessage = 

         "We don't want you"), DisplayName("Age")]

      public int Age { get; set; }



      [Required(), DisplayName("Join Date"), 

        RegularExpression(@"\d{2}/\d{2}/\d{4}")]

      public DateTime JoinDate { get; set; }

   }

}

这是一个非常基本的类,没有太特殊了,除了我们的新的属性。确保你添加System.ComponentModel和System.ComponentModel.DataAnnotations usings。此外,命名空间,使这项工作更容易。看看在FirstName和LastName属性,它们各有所需,StringLength和DisplayName属性。 DisplayName的("")允许您选择一个用户更友好的名称。必需()使得该领域所需的(容易吧),StringLength不正是你想它。
现在到我们的网页。创建一个标准的网页,并加入我们的田野。我们需要添加我们的CustomValidator的引用,所以我们可以用它像任何其他的控制,所以我们添加了一个注册:
<%@ Register TagPrefix="CVal" Namespace="CustomValidations" %>

现在添加一个TextBox和我们新的验证器控制:
<asp:TextBox ID="txtFirstName" runat="server" />

<CVal:CustomValidator ID="valFirstName" runat="server" 

      ControlToValidate="txtFirstName" 

      Text="*" Display="Dynamic" PropertyName="FirstName" 

      ObjectType="DA.Examples.Member" />

TextBox是没有什么特别的,让我们来看看我们的控制。我们使用像任何其他的进口控制,给予其的TagPrefix。给它一个ID,RUNAT ="serverquot;,的ControlToValidate,文本,显示 - 这些都是你已经使用任何ASP.NET验证控制标准。这两个新的属性quot; PropertyNamequot;和"; ObjectTypequot";如果你看看我们的CustomValidator创建。这是两个公共属性在类的底部。我们只需要我们要用于验证的对象/属性映射这些值。挂接此之后,当页面回发和的CausesValidation是真实的,这是发射,并为我们验证用户输入。
上面的代码强制用户只进不出的第一个名字的价值,但它也使确保用户不输入一个值,时间越长,20个字符长。要做到这与当前的验证控件,你可以这样做:
<asp:TextBox ID="txtFirstName" runat="server" />

<!-- This is the normal way to add validators -->

<!-- Great thing about this is the client side validation -->

<asp:RequiredFieldValidator ID="reqFirstName" ControlToValidate="txtFirstName" 

       Text="*" Display="Dynamic" InitialValue="" 

       ErrorMessage="First Name is required" runat="server" 

       ToolTip="First Name is required" />

<asp:RangeValidator ID="rngFirstName" ControlToValidate="txtFirstName" 

       runat="server" Text="*" 

       ErrorMessage="First name can not be over 20 characters." 

       ToolTip="First name can not be over 20 characters" 

       MinimumValue="0" 

       MaximumValue="20" Type="String" />

现在,使用标准验证控件的伟大的事情是在客户端验证。坏事是有一个输入字段使用多个验证控件。兴趣点
爱新的功能和清理您的ASPX页面。

回答

评论会员:Donsw 时间:2012/01/25
好文章,你可能想看看在4.0 dataannotations如何,如果他们已经改变
。欢呼声中,
Donsw
我最近的一篇文章:疾病预防控制中心 - 变更数据捕获
评论会员:ptmcomp 时间:2012/01/25
也有一个包含整个业务规则的属性来注释类?有关集合和列表
评论会员:?肖恩罗纳 时间:2012/01/25
我有没有机会尝试,但它看起来像你可以使用一个类,它具有所有这些属性MetadataTypeAttribute。上周末,我会尝试和测试了这一点,并让你知道我的发现
评论会员:。理查德推定 时间:2012/01/25
您可以取代您的控制特定的代码来获取值来验证一个简单的调用{A1}]

/*

Control Ctrl = FindControl(ControlToValidate);

string value;

 

if (Ctrl is TextBox)

{

    value = ((TextBox)Ctrl).Text;

}

else if (Ctrl is DropDownList)

{

    value = ((DropDownList)Ctrl).SelectedValue;

}

else

{

    return false;

}

*/

 

string value = base.GetControlValidationValue(base.ControlToValidate);


"看着这些人在我的灵魂深处,并分配给我我加入的顺序为基础的数字。"
- 荷马

| MR_SAM_PIPER
评论会员:游客 时间:2012/01/25
文章标题是误导-确实没有任何现有的属性数据注释的讨论,它们是如何工作的
肖恩罗纳
评论会员:游客 时间:2012/01/25
好吧,我不知道为什么你说,因为整个文章是关于使用新的命名空间中的属性来验证属性,而这正是新的命名空间