如何:在数据模型中自定义数据字段验证

更新: 2008 年 7 月

利用 ASP.NET 动态数据,可以在数据模型中自定义和扩展数据验证。本主题介绍如何采用以下方法在数据模型中添加数据字段验证:

  • 通过对各个数据字段应用动态数据 System.ComponentModel.DataAnnotations 属性来自定义这些字段的验证。这些属性用于定义常见的验证模式,例如范围检查和必填字段。利用此方法,只需编写很少的代码,就可使用预定义的验证检查。如果要对已由动态数据提供的内容应用其他验证,并且默认 System.ComponentModel.DataAnnotations 属性足以满足您的需求,则应使用此方法。

    Cc488527.alert_note(zh-cn,VS.90).gif说明:

    还可以创建自定义验证属性。这样就可以扩展由 System.ComponentModel.DataAnnotations 属性提供的验证。如果可用属性不满足特定数据字段的验证需求,则此方法很有用。有关更多信息,请参见如何:使用自定义属性在数据模型中自定义数据字段验证

  • 通过重写处理单个数据字段的更改的分部类方法(或通过处理对应的事件)来自定义该数据字段的验证。利用此方法,可以为单个字段添加验证和业务逻辑。

  • 通过重写 OnValidate 方法(或通过处理 Validate 事件)来自定义任何数据字段的验证。当处理表中的任何数据字段时,将调用此方法。与为单个字段添加验证相比,此方法更为通用。当可以将同一个验证逻辑应用于多个数据字段时,此方法很有用。利用此方法,还可以执行涉及多个字段的验证检查。

数据模型中引发的任何验证异常都由 DynamicValidator 控件捕捉。如果页面中包含 DynamicValidator 控件,则可以在该页面中显示错误。

  • 对于添加到数据模型中的所有验证检查,都必须在数据模型中创建一个扩展表类的分部类。然后向该分部类中添加验证检查。

运行此功能的在线示例。

针对验证创建一个分部类

必须先实现一个扩展数据模型的分部类,才能在数据模型层自定义验证。这样您就可以执行以下操作:

  • 通过属性添加元数据信息来自定义验证。

  • 通过实现分部类方法来自定义验证,利用这些方法,您可以创建自己的验证逻辑。

针对验证创建分部类

  1. 在**“解决方案资源管理器”中,右击 App_Code 文件夹,然后单击“添加新项”**。

  2. 在**“Visual Studio 已安装的模板”之下单击“类”**。

    在**“名称”**框中,输入要添加验证的数据表的名称。

    类名必须与表示表的实体类名匹配。例如,如果要为 Customers 表添加验证,则必须将文件命名为 Customer.cs(在 Visual C# 中)或 Customer.vb(在 Visual Basic 中),并且必须将类命名为 Customer。

  3. 将 Partial 关键字(在 Visual Basic 中)或 partial 关键字(在 Visual C# 中)添加到类定义中,使它成为分部类。

    下面的示例显示更新后的类声明。

    public partial class Customer {
    
    }
    
    Partial Public Class Customer
    
    End Class
    
  4. 如果是在 Visual C# 中创建该类,请删除默认的构造函数。

  5. 使用 Imports 关键字(在 Visual Basic 中)或 using 关键字(在 Visual C# 中),添加对 System.Web.DynamicDataSystem.ComponentModel.DataAnnotations 命名空间的引用,如下面的示例所示:

    using System.Web.DynamicData;
    using System.ComponentModel.DataAnnotations;
    
    Imports System.Web.DynamicData
    Imports System.ComponentModel.DataAnnotations
    
  6. 在同一个文件中,创建将充当关联的元数据类的另一个类。可以将任何有效且尚未使用的名称用于该类。

    下面的示例显示元数据类声明。

    [C#]

    public class CustomerMetadata
    {
    
    }
    
    Public Class CustomerMetadata 
    
    End Class
    

    关联的元数据类提供一个可以应用验证属性的对象。

  7. MetadataTypeAttribute 属性应用于分部类定义。对于此属性的参数,请使用上一步中创建的关联元数据类的名称。

    下面的示例显示已添加此属性的分部类定义。

    [MetadataType(typeof(CustomerMetadata))]
    public partial class Customer {
    
    }
    
    <MetadataType(GetType(CustomerMetadata))> _
    Partial Public Class Customer
    
    End Class
    

使用属性来自定义验证

本节演示如何使用由动态数据 System.ComponentModel.DataAnnotations 属性提供的默认验证规则来自定义验证。

使用验证属性来验证特定的数据字段

  1. 在元数据类中,创建一个其名称与要验证的数据字段相对应的属性或字段。

  2. 对该属性 (Property) 应用 System.ComponentModel.DataAnnotations 命名空间中的属性 (Attribute) 之一。

    下面的示例演示如何将 System.ComponentModel.DataAnnotations.RequiredAttribute 属性应用于关联的元数据类中的 Title 数据字段。如果用户输入一个空字符串,则 IsValid 方法将引发验证异常并生成错误消息。

    Cc488527.alert_note(zh-cn,VS.90).gif说明:

    通过应用 RequiredAttribute 属性,要求用户输入一个值,即使数据库本身无此要求也是如此。

    public class CustomerMetadata
    {
      [Required()]
      public object Title;
    }
    
    Public Class CustomerMetadata 
      <Required()> _
      Public Title As Object
    End Class
    

通过使用分部类方法来自定义单个数据字段的验证

本节演示如何通过重写分部类方法来自定义验证,该方法处理对单个数据字段所做的更改。利用此类型的验证,您可以创建自己的规则来执行验证,而不依赖于在 System.ComponentModel.DataAnnotations 属性中实现的内置动态数据验证检查。

使用分部类方法验证特定的数据字段

  1. 重写分部类方法,该方法处理对数据字段所做的更改。

  2. 添加自定义验证逻辑。

    下面的示例演示如何在 Customer 分部类中重写 OnTitleChanging 方法。当更改 Customer 数据表的 Title 字段时,将调用此方法。示例中的代码检查用户输入的新职称是否以大写字母开头。如果数据没有通过验证,该方法将引发异常。要验证的值作为唯一参数传递给该方法。键入参数,使其与要验证的数据的数据类型匹配。

    Cc488527.alert_note(zh-cn,VS.90).gif说明:

    数据模型中引发的任何验证异常都由 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 属性中实现的内置动态数据验证检查。当可以将同一个验证逻辑应用于多个数据字段时,此方法很有用。利用此方法,还可以执行涉及多个字段的验证检查。

使用分部类方法来验证任何数据字段

  1. 重写对表中的任何数据字段进行更改时将调用的 OnValidate 分部类方法。

  2. 添加自定义验证逻辑。

    下面的示例显示如何重写 OnValidate 方法。此代码示例检查用户输入的名字和姓氏是否以大写字母开头。如果数据没有通过验证,该方法将引发异常。

    Cc488527.alert_note(zh-cn,VS.90).gif说明:

    数据模型中引发的任何验证异常都由 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

请参见

概念

ASP.NET 动态数据字段模板概述

ASP.NET 动态数据模型概述

ASP.NET 动态数据概述

参考

RequiredAttribute

DynamicValidator

分部类和方法(C# 编程指南)

修订记录

日期

修订历史记录

原因

2008 年 7 月

新增主题。

SP1 功能更改。