如何:在数据模型中自定义数据字段验证
更新: 2008 年 7 月
利用 ASP.NET 动态数据,可以在数据模型中自定义和扩展数据验证。本主题介绍如何采用以下方法在数据模型中添加数据字段验证:
通过对各个数据字段应用动态数据 System.ComponentModel.DataAnnotations 属性来自定义这些字段的验证。这些属性用于定义常见的验证模式,例如范围检查和必填字段。利用此方法,只需编写很少的代码,就可使用预定义的验证检查。如果要对已由动态数据提供的内容应用其他验证,并且默认 System.ComponentModel.DataAnnotations 属性足以满足您的需求,则应使用此方法。
说明: 还可以创建自定义验证属性。这样就可以扩展由 System.ComponentModel.DataAnnotations 属性提供的验证。如果可用属性不满足特定数据字段的验证需求,则此方法很有用。有关更多信息,请参见如何:使用自定义属性在数据模型中自定义数据字段验证。
通过重写处理单个数据字段的更改的分部类方法(或通过处理对应的事件)来自定义该数据字段的验证。利用此方法,可以为单个字段添加验证和业务逻辑。
通过重写 OnValidate 方法(或通过处理 Validate 事件)来自定义任何数据字段的验证。当处理表中的任何数据字段时,将调用此方法。与为单个字段添加验证相比,此方法更为通用。当可以将同一个验证逻辑应用于多个数据字段时,此方法很有用。利用此方法,还可以执行涉及多个字段的验证检查。
数据模型中引发的任何验证异常都由 DynamicValidator 控件捕捉。如果页面中包含 DynamicValidator 控件,则可以在该页面中显示错误。
- 对于添加到数据模型中的所有验证检查,都必须在数据模型中创建一个扩展表类的分部类。然后向该分部类中添加验证检查。
运行此功能的在线示例。
针对验证创建一个分部类
必须先实现一个扩展数据模型的分部类,才能在数据模型层自定义验证。这样您就可以执行以下操作:
通过属性添加元数据信息来自定义验证。
通过实现分部类方法来自定义验证,利用这些方法,您可以创建自己的验证逻辑。
针对验证创建分部类
在**“解决方案资源管理器”中,右击 App_Code 文件夹,然后单击“添加新项”**。
在**“Visual Studio 已安装的模板”之下单击“类”**。
在**“名称”**框中,输入要添加验证的数据表的名称。
类名必须与表示表的实体类名匹配。例如,如果要为 Customers 表添加验证,则必须将文件命名为 Customer.cs(在 Visual C# 中)或 Customer.vb(在 Visual Basic 中),并且必须将类命名为 Customer。
将 Partial 关键字(在 Visual Basic 中)或 partial 关键字(在 Visual C# 中)添加到类定义中,使它成为分部类。
下面的示例显示更新后的类声明。
public partial class Customer { }
Partial Public Class Customer End Class
如果是在 Visual C# 中创建该类,请删除默认的构造函数。
使用 Imports 关键字(在 Visual Basic 中)或 using 关键字(在 Visual C# 中),添加对 System.Web.DynamicData 和 System.ComponentModel.DataAnnotations 命名空间的引用,如下面的示例所示:
using System.Web.DynamicData; using System.ComponentModel.DataAnnotations;
Imports System.Web.DynamicData Imports System.ComponentModel.DataAnnotations
在同一个文件中,创建将充当关联的元数据类的另一个类。可以将任何有效且尚未使用的名称用于该类。
下面的示例显示元数据类声明。
[C#]
public class CustomerMetadata { }
Public Class CustomerMetadata End Class
关联的元数据类提供一个可以应用验证属性的对象。
将 MetadataTypeAttribute 属性应用于分部类定义。对于此属性的参数,请使用上一步中创建的关联元数据类的名称。
下面的示例显示已添加此属性的分部类定义。
[MetadataType(typeof(CustomerMetadata))] public partial class Customer { }
<MetadataType(GetType(CustomerMetadata))> _ Partial Public Class Customer End Class
使用属性来自定义验证
本节演示如何使用由动态数据 System.ComponentModel.DataAnnotations 属性提供的默认验证规则来自定义验证。
使用验证属性来验证特定的数据字段
在元数据类中,创建一个其名称与要验证的数据字段相对应的属性或字段。
对该属性 (Property) 应用 System.ComponentModel.DataAnnotations 命名空间中的属性 (Attribute) 之一。
下面的示例演示如何将 System.ComponentModel.DataAnnotations.RequiredAttribute 属性应用于关联的元数据类中的 Title 数据字段。如果用户输入一个空字符串,则 IsValid 方法将引发验证异常并生成错误消息。
说明: 通过应用 RequiredAttribute 属性,要求用户输入一个值,即使数据库本身无此要求也是如此。
public class CustomerMetadata { [Required()] public object Title; }
Public Class CustomerMetadata <Required()> _ Public Title As Object End Class
通过使用分部类方法来自定义单个数据字段的验证
本节演示如何通过重写分部类方法来自定义验证,该方法处理对单个数据字段所做的更改。利用此类型的验证,您可以创建自己的规则来执行验证,而不依赖于在 System.ComponentModel.DataAnnotations 属性中实现的内置动态数据验证检查。
使用分部类方法验证特定的数据字段
重写分部类方法,该方法处理对数据字段所做的更改。
添加自定义验证逻辑。
下面的示例演示如何在 Customer 分部类中重写 OnTitleChanging 方法。当更改 Customer 数据表的 Title 字段时,将调用此方法。示例中的代码检查用户输入的新职称是否以大写字母开头。如果数据没有通过验证,该方法将引发异常。要验证的值作为唯一参数传递给该方法。键入参数,使其与要验证的数据的数据类型匹配。
说明: 数据模型中引发的任何验证异常都由 DynamicValidator 控件捕捉。如果页面中包含 DynamicValidator 控件,则可以在该页面中显示错误。
public partial class Customer { partial void OnTitleChanging(string value) { if (!Char.IsUpper(value[0])) { throw new ValidationException( "Title must start with an uppercase letter.");} } }
Public Partial Class Customer Private Sub OnTitleChanging(ByVal value As String) If Not [Char].IsUpper(value(0)) Then Throw New ValidationException( _ "Title must start with an uppercase letter.") End If End Sub End Class
通过使用分部类方法来自定义所有数据字段的验证
本节演示如何通过重写分部类方法来自定义验证,该方法处理对表中任何数据字段所做的更改。利用此类型的验证,您可以创建自己的规则来执行验证,而不依赖于在 System.ComponentModel.DataAnnotations 属性中实现的内置动态数据验证检查。当可以将同一个验证逻辑应用于多个数据字段时,此方法很有用。利用此方法,还可以执行涉及多个字段的验证检查。
使用分部类方法来验证任何数据字段
重写对表中的任何数据字段进行更改时将调用的 OnValidate 分部类方法。
添加自定义验证逻辑。
下面的示例显示如何重写 OnValidate 方法。此代码示例检查用户输入的名字和姓氏是否以大写字母开头。如果数据没有通过验证,该方法将引发异常。
说明: 数据模型中引发的任何验证异常都由 DynamicValidator 控件捕捉。如果页面中包含 DynamicValidator 控件,则可以在该页面中显示错误。
partial void OnValidate( System.Data.Linq.ChangeAction action) { if (!Char.IsUpper(this._LastName[0]) || !Char.IsUpper(this._FirstName[0])) throw new ValidationException( "Name must start with an uppercase letter."); }
Private Sub OnValidate(ByVal action As _ System.Data.Linq.ChangeAction) If Not [Char].IsUpper(Me._LastName(0)) OrElse _ Not [Char].IsUpper(Me._FirstName(0)) Then Throw New ValidationException( _ "Name must start with an uppercase letter.") End If End Sub
示例
此示例演示如何使用 RequiredAttribute 属性来验证 Customer 表的 Title 数据。此示例使用 OnValidate 分部类方法来确保用户输入的 Title、FirstName 和 LastName 数据字段的值以大写字母开头。此示例还使用 OnOderQtyChanging 分部类方法来确保用户输入的 SalesOrderDetails 表的 OrderQty 数据字段的值大于指定的最小值。
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.DynamicData
Imports System.ComponentModel.DataAnnotations
<MetadataType(GetType(CustomerMetadata))> _
Partial Public Class Customer
Private Sub OnValidate(ByVal action As System.Data.Linq.ChangeAction)
If Not Char.IsUpper(Me._LastName(0)) _
OrElse Not Char.IsUpper(Me._FirstName(0)) _
OrElse Not Char.IsUpper(Me._Title(0)) Then
Throw New ValidationException( _
"Data value must start with an uppercase letter.")
End If
End Sub
End Class
Public Class CustomerMetadata
<Required()> _
Public Title As Object
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.DynamicData;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CustomerMetadata))]
public partial class Customer
{
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (!char.IsUpper(this._LastName[0]) ||
!char.IsUpper(this._FirstName[0]) ||
!char.IsUpper(this._Title[0]))
throw new ValidationException(
"Data value must start with an uppercase letter.");
}
}
public class CustomerMetadata
{
[Required()]
public object Title;
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.DynamicData
Imports System.ComponentModel.DataAnnotations
Partial Public Class SalesOrderDetail
Private Sub OnOrderQtyChanging(ByVal value As Short)
If value < 100 Then
Throw New ValidationException( _
"Quantity is less than the allowed minimum of 100.")
End If
End Sub
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.DynamicData;
using System.ComponentModel.DataAnnotations;
public partial class SalesOrderDetail
{
partial void OnOrderQtyChanging(short value)
{
if (value < 100)
{
throw new ValidationException(
"Quantity is less than the allowed minimum of 100.");
}
}
}
<%@ Page Language="VB"
AutoEventWireup="true" CodeFile="CustomValidation.aspx.vb"
Inherits="CustomValidation" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<link href="~/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h2>Example: <%=Title%></h2>
<!-- Enable dynamic behavior. The GridView must be
registered with the manager. See code-behind file. -->
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server"
AutoLoadForeignKeys="true" />
<form id="form1" runat="server">
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
runat="server" />
<asp:DynamicValidator ID="DynamicValidator1" ControlToValidate="GridView2"
runat="server" />
<table>
<tr>
<td align="left" valign="top" style="font-weight:bold">
Customize Validation Using the Table OnValidate
</td>
<td>
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="Title" />
<asp:DynamicField DataField="FirstName" />
<asp:DynamicField DataField="LastName" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</td>
</tr>
<tr>
<td align="left" valign="top" style="font-weight:bold">
Customize Validation Using OnOrderQtyChanging
</td>
<td>
<asp:GridView ID="GridView2"
runat="server"
DataSourceID="GridDataSource2"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="OrderQty" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</td>
</tr>
</table>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource" runat="server"
TableName="Customers" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource2" runat="server"
TableName="SalesOrderDetails" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="CustomValidation.aspx.cs"
Inherits="CustomValidation" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<link href="~/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h2>Example: <%=Title%></h2>
<!-- Enable dynamic behavior. The GridView must be
registered with the manager. See code-behind file. -->
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server"
AutoLoadForeignKeys="true" />
<form id="form1" runat="server">
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
runat="server" />
<asp:DynamicValidator ID="DynamicValidator1" ControlToValidate="GridView2"
runat="server" />
<table>
<tr>
<td align="left" valign="top" style="font-weight:bold">
Customize Validation Using the Table OnValidate
</td>
<td>
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="Title" />
<asp:DynamicField DataField="FirstName" />
<asp:DynamicField DataField="LastName" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</td>
</tr>
<tr>
<td align="left" valign="top" style="font-weight:bold">
Customize Validation Using OnOrderQtyChanging
</td>
<td>
<asp:GridView ID="GridView2"
runat="server"
DataSourceID="GridDataSource2"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="OrderQty" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</td>
</tr>
</table>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource" runat="server"
TableName="Customers" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource2" runat="server"
TableName="SalesOrderDetails" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
Imports System
Imports System.Collections
Imports System.Configuration
Imports System.Web.DynamicData
Partial Public Class CustomValidation
Inherits System.Web.UI.Page
Protected _table1 As MetaTable, _table2 As MetaTable
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
' Register data controls with the data manager.
DynamicDataManager1.RegisterControl(GridView1)
DynamicDataManager1.RegisterControl(GridView2)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Get the table entities.
_table1 = GridDataSource.GetTable()
_table2 = GridDataSource2.GetTable()
' Assign title dynamically.
Title = String.Concat("Customize Validation of the ", _
_table1.Name, " and ", _table2.Name, " Tables")
End Sub
End Class
using System;
using System.Collections;
using System.Configuration;
using System.Web.DynamicData;
public partial class CustomValidation : System.Web.UI.Page
{
protected MetaTable _table1, _table2;
protected void Page_Init(object sender, EventArgs e)
{
// Register data controls with the data manager.
DynamicDataManager1.RegisterControl(GridView1);
DynamicDataManager1.RegisterControl(GridView2);
}
protected void Page_Load(object sender, EventArgs e)
{
// Get the table entities.
_table1 = GridDataSource.GetTable();
_table2 = GridDataSource2.GetTable();
// Assign title dynamically.
Title = string.Concat("Customize Validation of the ",
_table1.Name, " and ", _table2.Name, " Tables");
}
}
编译代码
若要编译代码示例,您需要以下各项:
Microsoft Visual Studio 2008 Service Pack 1 或 Visual Web Developer 2008 速成版 Service Pack 1。
AdventureWorksLT 示例数据库。有关如何下载和安装 SQL Server 示例数据库的信息,请参见 CodePlex 站点上的 Microsoft SQL Server Product Samples: Database(Microsoft SQL Server 产品示例:数据库)。请确保针对所运行的 SQL Server 版本(Microsoft SQL Server 2005 或 Microsoft SQL Server 2008)安装正确版本的示例数据库。
动态数据网站。这允许您为数据库创建数据上下文,以及创建包含要自定义的数据字段和要重写的方法的类。有关更多信息,请参见 Walkthrough: Creating a New Dynamic Data Web Site Using Scaffolding。
请参见
概念
参考
修订记录
日期 |
修订历史记录 |
原因 |
---|---|---|
2008 年 7 月 |
新增主题。 |
SP1 功能更改。 |