使用数据注解构建 ASP.NET 验证器
本文描述了一种使用 .NET 3.5 SP1 中引入的 System.ComponentModel.DataAnnotations 程序集实现的 ASP.NET 验证器。
引言
在本文中,我将描述一种使用 .NET 3.5 SP1 中引入的 System.ComponentModel.DataAnnotations 程序集实现的 ASP.NET 验证器。
验证器
为了创建验证器,你需要从 BaseValidator
抽象类继承并实现其 EvaluateIsValid
方法。 我创建了一个 ASP.NET 服务器控件 项目,并添加了一个执行此操作的控件类。 你需要引用 System.ComponentModel.DataAnnotations 程序集才能使其工作。 实现方式如下:
namespace Validators
{
[ToolboxData("<{0}:DataAnnotationValidator
runat="server"></{0}:DataAnnotationValidator>")]
public class DataAnnotationValidator : BaseValidator
{
#region Properties
/// <summary>
/// The type of the source to check
/// </summary>
public string SourceTypeName { get; set; }
/// <summary>
/// The property that is annotated
/// </summary>
public string PropertyName { get; set; }
#endregion
#region Methods
protected override bool EvaluateIsValid()
{
// get the type that we are going to validate
Type source = GetValidatedType();
// get the property to validate
PropertyInfo property = GetValidatedProperty(source);
// get the control validation value
string value = GetControlValidationValue(ControlToValidate);
foreach (var attribute in property.GetCustomAttributes(
typeof(ValidationAttribute), true)
.OfType<ValidationAttribute>())
{
if (!attribute.IsValid(value))
{
ErrorMessage = attribute.ErrorMessage;
return false;
}
}
return true;
}
private Type GetValidatedType()
{
if (string.IsNullOrEmpty(SourceTypeName))
{
throw new InvalidOperationException(
"Null SourceTypeName can't be validated");
}
Type validatedType = Type.GetType(SourceTypeName);
if (validatedType == null)
{
throw new InvalidOperationException(
string.Format("{0}:{1}",
"Invalid SourceTypeName", SourceTypeName));
}
return validatedType;
}
private PropertyInfo GetValidatedProperty(Type source)
{
PropertyInfo property = source.GetProperty(PropertyName,
BindingFlags.Public | BindingFlags.Instance);
if (property == null)
{
throw new InvalidOperationException(
string.Format("{0}:{1}",
"Validated Property Does Not Exists", PropertyName));
}
return property;
}
#endregion
}
}
如你所见,我在验证器中使用两个主要属性,它们帮助我获取相关的源类型名称和要验证的属性。
测试验证器
为了测试验证器,我创建了一个 Web 应用程序 项目,并在其中放置了一个简单的 Person
类,该类使用 数据注解 进行验证。
namespace ASPNETDataAnnotation
{
public class Person
{
[Required(ErrorMessage="ID is requiered")]
public string ID { get; set; }
[StringLength(20, ErrorMessage = "First name is too long!")]
public string FirstName { get; set; }
[StringLength(20, ErrorMessage="Last name is too long!")]
public string LastName { get; set; }
[RegularExpression(
@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+*",
ErrorMessage="Must be a valid e-mail address")]
public string Email { get; set; }
}
}
此外,我创建了一个使用验证器的 Web 表单。
lt;%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs" Inherits="ASPNETDataAnnotation.WebForm1" %>
<%@ Register Assembly="Validators" Namespace="Validators" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div>
<asp:Label ID="lblID" Text="ID: " runat="server" />
<asp:TextBox ID="txtID" runat="server" />
<cc1:DataAnnotationValidator ID="valID"
runat="server" ControlToValidate="txtID"
PropertyName="ID"
SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
</div>
<div>
<asp:Label ID="lblFirstName" Text="First Name: " runat="server" />
<asp:TextBox ID="txtFirstName" runat="server" />
<cc1:DataAnnotationValidator ID="valFirstName"
runat="server" ControlToValidate="txtFirstName"
PropertyName="FirstName"
SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
</div>
<div>
<asp:Label ID="lblLastName" Text="Last Name: " runat="server" />
<asp:TextBox ID="txtLastName" runat="server" />
<cc1:DataAnnotationValidator ID="valLastName"
runat="server" ControlToValidate="txtLastName"
PropertyName="LastName"
SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
</div>
<div>
<asp:Label ID="lblEmail" Text="E-Mail: " runat="server" />
<asp:TextBox ID="txtEmail" runat="server" />
<cc1:DataAnnotationValidator ID="valEmail"
runat="server" ControlToValidate="txtEmail"
PropertyName="Email"
SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
</div>
<div>
<asp:Button ID="btnValidate" Text="Validate" runat="server" />
</div>
</div>
</form>
</body>
</html>
运行 Web 表单并在数据错误时单击按钮,将如预期的那样生成验证错误。
摘要
在文章中,我展示了一种创建 ASP.NET 数据注解验证器的方法。 在其他框架(如 ASP.NET MVC 或 WCF RIA Services)中,你已经实现了此类验证器。