Gewusst wie: Anpassen der Datenfeldvalidierung im Datenmodell mit benutzerdefinierten Attributen
Aktualisiert: Juli 2008
ASP.NET Dynamic Data ermöglicht Ihnen, die Datenfeldvalidierung auf Datenebene anzupassen und zu erweitern. In diesem Thema erfahren Sie, wie Sie die Datenfeldvalidierung im Datenmodell hinzufügen. Führen Sie hierzu die folgenden Schritte aus:
Erstellen Sie ein benutzerdefiniertes Validierungsattribut. Mit diesem Attribut können Sie benutzerdefinierte Metadaten erstellen, die Sie im Datenmodell für die Validierung verwenden können.
Wenden Sie das benutzerdefinierte Validierungsattribut an. Nachdem Sie das benutzerdefinierte Attribut erstellt haben, wenden Sie es auf die zu validierenden Datenfelder an.
Führen Sie ein Online-Beispiel für dieses Feature aus.
Erstellen eines benutzerdefinierten Validierungsattributs
Mit einem benutzerdefinierten Validierungsattribut können Sie Metadaten erstellen, die Sie im Datenmodell für die Validierung der Datenfelder verwenden können. Das benutzerdefinierte Attribut wird aus der ValidationAttribute-Basisklasse abgeleitet.
So erstellen Sie ein benutzerdefiniertes Validierungsattribut
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner App_Code, und klicken Sie dann auf Neues Element hinzufügen.
Klicken Sie unter Neues Element hinzufügen auf Klasse.
Geben Sie im Feld Name den Namen der benutzerdefinierten Validierungsattributklasse ein. Sie können einen beliebigen, bisher nicht verwendeten Namen eingeben. Sie können beispielsweise in Visual C# den Namen CustomAttribute.vb oder in Visual Basic den Namen CustomAttribute.vb eingeben, um eine benutzerdefinierte Attributklasse mit dem Namen CustomAttribute zu erstellen.
Fügen Sie den Namespaces System, System.Web.Globalization und System.ComponentModel.DataAnnotations mithilfe des Imports-Schlüsselworts in Visual Basic bzw. des using-Schlüsselworts in Visual C# Verweise hinzu, wie im folgenden Beispiel dargestellt:
using System; using System.Globalization; using System.ComponentModel.DataAnnotations;
Imports System Imports System.Globalization Imports System.ComponentModel.DataAnnotations
Ändern Sie die Klassendefinition wie folgt:
Legen Sie fest, dass die Klasse nicht vererbbar ist. Fügen Sie das NotInheritable-Schlüsselwort in Visual Basic bzw. das sealed-Schlüsselwort in Visual C# hinzu.
Leiten Sie die Klasse vom ValidationAttribute-Basistyp ab.
Wenden Sie das AttributeUsageAttribute-Attribut auf die Klassendefinition an, um anzugeben, wie das benutzerdefinierte Validierungsattribut verwendet werden soll.
Das folgende Beispiel zeigt eine Klassendefinition. Die AttributeUsageAttribute-Parameter sind so festgelegt, dass das benutzerdefinierte Validierungsattribut nur einmal auf Eigenschaften oder Felder angewendet werden kann.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] sealed public class CustomAttribute : ValidationAttribute { }
<AttributeUsage(AttributeTargets.[Property] Or _ AttributeTargets.Field, AllowMultiple := False)> _ Public NotInheritable Class CustomAttribute Inherits ValidationAttribute .... End Class
Überschreiben Sie die IsValid-Methode, und fügen Sie Logik hinzu, um die Validierung auszuführen. Geben Sie true zurück, wenn die benutzerdefinierte Validierung erfolgreich ist, oder false, wenn sie fehlschlägt. Der zu überprüfende Wert wird als einziger Parameter an die Methode übergeben.
Im folgenden Beispiel wird die überschriebene Methode gezeigt.
public override bool IsValid(object value) { bool result = true; // Add validation logic here. return result; }
Public Overrides Function IsValid( _ ByVal value As Object) As Boolean ' Add validation logic here. Return result End Function
Überschreiben Sie optional die FormatErrorMessage-Methode, um benutzerdefinierte Formatierungen auf die Fehlermeldungen anzuwenden.
Das folgende Beispiel veranschaulicht, wie Sie anhand des Namens des in der Validierung fehlgeschlagenen Datenfelds eine benutzerdefinierte Fehlermeldung erstellen. Der ErrorMessageString-Wert wird als Parameter übergeben, wenn das benutzerdefinierte Attribut auf das Datenfeld angewendet wird.
public override string FormatErrorMessage(string name) { return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name); }
Public Overrides Function FormatErrorMessage( _ ByVal name As String) As String Return [String].Format(CultureInfo.CurrentCulture, _ ErrorMessageString, name) End Function
Speichern und schließen Sie die Klassenattributdatei.
Anwenden eines benutzerdefinierten Validierungsattributs
Um die Validierung für ein Datenfeld anzupassen, müssen Sie eine partielle Klasse, die das Datenmodell erweitert, implementieren. Auf diese Weise können Sie das benutzerdefinierte Attribut auf das Datenfeld anwenden.
So erstellen Sie eine partielle Klasse für die Validierung
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner App_Code, und klicken Sie dann auf Neues Element hinzufügen.
Klicken Sie unter Von Visual Studio installierte Vorlagen auf Klasse.
Geben Sie im Feld Name den Namen der Datenbanktabelle ein, für die Sie eine Validierung hinzufügen möchten.
Der Klassenname muss dem Entitätsklassennamen, der die Tabelle repräsentiert, entsprechen. Wenn Sie zum Beispiel eine Validierung für die Tabelle Customers hinzufügen möchten, müssen Sie der Datei in Visual C# den Namen Customer.cs bzw. in Visual Basic den Namen Customer.vb und der Klasse den Namen Customer zuweisen.
Fügen Sie das Partial-Schlüsselwort in Visual Basic bzw. das partial-Schlüsselwort in Visual C# zur Klassendefinition hinzu, um eine partielle Klasse zu erstellen.
Wenn Sie die Klasse in Visual C# erstellen, löschen Sie den Standardkonstruktor.
Im folgenden Beispiel wird die aktualisierte Klassendeklaration veranschaulicht:
public partial class Customer { }
Partial Public Class Customer End Class
Fügen Sie den Namespaces System.Web.DynamicData und System.ComponentModel.DataAnnotations mithilfe des Imports-Schlüsselworts in Visual Basic oder des using-Schlüsselworts in Visual C# Verweise hinzu, wie im folgenden Beispiel dargestellt:
using System.Web.DynamicData; using System.ComponentModel.DataAnnotations;
Imports System.Web.DynamicData Imports System.ComponentModel.DataAnnotations
Erstellen Sie in derselben Datei eine zweite Klasse, die als zugehörige Metadatenklasse fungiert. Sie können der Klasse jeden Namen zuweisen, solange es sich um einen gültigen Klassennamen handelt, der noch nicht verwendet wird.
Im folgenden Beispiel wird eine Metadatenklassendeklaration veranschaulicht:
public class CustomerMetadata { }
Public Class CustomerMetadata End Class
Die zugehörige Metadatenklasse stellt ein Objekt bereit, dem Sie Validierungsattribute zuweisen können.
Wenden Sie das MetadataTypeAttribute-Attribut auf die partielle Klassendefinition an. Verwenden Sie als Parameter für das Attribut den Namen der zugehörigen Metadatenklasse, die Sie im vorherigen Schritt erstellt haben.
Im folgenden Beispiel wird die Definition der partiellen Klasse mit hinzugefügtem Attribut gezeigt.
[MetadataType(typeof(CustomerMetadata))] public partial class Customer { }
<MetadataType(GetType(CustomerMetadata))> _ Partial Public Class Customer End Class
Sie können nun das benutzerdefinierte Validierungsattribut auf ein Datenfeld anwenden.
So wenden Sie ein benutzerdefiniertes Validierungsattribut auf ein Datenfeld an
Erstellen Sie in der Metadatenklasse eine Eigenschaft oder ein Feld mit einem Namen, der dem zu validierenden Datenfeld entspricht.
Wenden Sie das zuvor erstellte benutzerdefinierte Validierungsattribut auf das Datenfeld an, das Sie validieren möchten.
Das folgende Beispiel veranschaulicht, wie Sie das benutzerdefinierte Validierungsattribut auf das Datenfeld Phone anwenden.
public partial class CustomerMetadata { [CustomAttribute(parm1, ErrorMessage = "{0} field validation failed.")] public object Phone; }
Public Class CustomerMetadata <PhoneMask(parm1, _ ErrorMessage:="{0} field validation failed.")> _ Public Phone As Object End Class
Speichern und schließen Sie die Klassendatei.
Beispiel
Im folgenden Beispiel wird ein benutzerdefiniertes Attribut mit dem Namen PhoneMaskAttribute erstellt und auf das Datenfeld Phone der Tabelle Customer in der AdventureWorksLT-Datenbank angewendet. In dem Beispiel wird eine LINQ to SQL-Klasse für das Datenmodell verwendet.
Das Attribut weist Dynamic Data an, das Datenfeld Phone anhand einer Maske zu validieren, die ein spezifisches Format für Telefonnummern festlegt. Wenn die vom Benutzer eingegebene Telefonnummer nicht mit der Maske übereinstimmt, löst der Attributcode einen benutzerdefinierten Fehler aus.
Imports Microsoft.VisualBasic
Imports System
Imports System.Globalization
Imports System.ComponentModel.DataAnnotations
<AttributeUsage(AttributeTargets.[Property] Or AttributeTargets.Field, AllowMultiple:=False)> _
Public NotInheritable Class PhoneMaskAttribute
Inherits ValidationAttribute
' Internal field to hold the mask value.
ReadOnly _mask As String
Public ReadOnly Property Mask() As String
Get
Return _mask
End Get
End Property
Public Sub New(ByVal mask As String)
_mask = mask
End Sub
Public Overrides Function IsValid( _
ByVal value As Object) As Boolean
Dim phoneNumber As String = DirectCast(value, String)
Dim result As Boolean = True
If Me.Mask <> Nothing Then
result = MatchesMask(Me.Mask, phoneNumber)
End If
Return result
End Function
' Checks if the entered phone number matches the mask.
Public Shared Function MatchesMask(ByVal mask As String, _
ByVal phoneNumber As String) As Boolean
If mask.Length <> phoneNumber.Trim().Length Then
' Length mismatch.
Return False
End If
Dim i As Integer = 0
While i < mask.Length
If mask(i) = "d"c _
AndAlso Char.IsDigit(phoneNumber(i)) = False Then
' Digit expected at this position.
Return False
End If
If mask(i) = "-"c AndAlso phoneNumber(i) <> "-"c Then
' Spacing character expected at this position.
Return False
End If
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End While
Return True
End Function
Public Overrides Function FormatErrorMessage( _
ByVal name As String) As String
Return [String].Format(CultureInfo.CurrentCulture, _
ErrorMessageString, name, Me.Mask)
End Function
End Class
using System;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class PhoneMaskAttribute : ValidationAttribute
{
// Internal field to hold the mask value.
readonly string _mask;
public string Mask
{
get { return _mask; }
}
public PhoneMaskAttribute(string mask)
{
_mask = mask;
}
public override bool IsValid(object value)
{
var phoneNumber = (String)value;
bool result = true;
if (this.Mask != null)
{
result = MatchesMask(this.Mask, phoneNumber);
}
return result;
}
// Checks if the entered phone number matches the mask.
internal bool MatchesMask(string mask, string phoneNumber)
{
if (mask.Length != phoneNumber.Trim().Length)
{
// Length mismatch.
return false;
}
for (int i = 0; i < mask.Length; i++)
{
if (mask[i] == 'd' && char.IsDigit(phoneNumber[i]) == false)
{
// Digit expected at this position.
return false;
}
if (mask[i] == '-' && phoneNumber[i] != '-')
{
// Spacing character expected at this position.
return false;
}
}
return true;
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture,
ErrorMessageString, name, this.Mask);
}
}
Imports Microsoft.VisualBasic
Imports System.Web.DynamicData
Imports System.ComponentModel.DataAnnotations
<MetadataType(GetType(CustomerMetadata))> _
Partial Public Class Customer
End Class
Public Class CustomerMetadata
<PhoneMask("999-999-9999", _
ErrorMessage:="{0} field value does not match the mask {1}.")> _
Public Phone As Object
End Class
using System.Web.DynamicData;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CustomerMetadata))]
public partial class Customer
{
}
public class CustomerMetadata
{
[PhoneMask("999-999-9999",
ErrorMessage = "{0} value does not match the mask {1}.")]
public object Phone;
}
<%@ Page Language="VB"
AutoEventWireup="true" CodeFile="CustomAttributeValidation.aspx.vb"
Inherits="CustomAttributeValidation" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
<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"
AutoLoadForeignKeys="true" />
<form id="form1" >
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
/>
<asp:GridView ID="GridView1"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="FirstName" />
<asp:DynamicField DataField="LastName" />
<asp:DynamicField DataField="Phone" />
</Columns>
</asp:GridView>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource"
TableName="Customers" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="CustomAttributeValidation.aspx.cs"
Inherits="CustomAttributeValidation" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
<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"
AutoLoadForeignKeys="true" />
<form id="form1" >
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
/>
<asp:GridView ID="GridView1"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="FirstName" />
<asp:DynamicField DataField="LastName" />
<asp:DynamicField DataField="Phone" />
</Columns>
</asp:GridView>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource"
TableName="Customers" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
Imports System
Imports System.Collections
Imports System.Configuration
Imports System.Web.DynamicData
Partial Public Class CustomAttributeValidation
Inherits System.Web.UI.Page
Protected _table As MetaTable
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
' Register control with the data manager.
DynamicDataManager1.RegisterControl(GridView1)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Get the table entity.
_table = GridDataSource.GetTable()
' Assign title dynamically.
Title = String.Concat( _
"Customize <i>Phone</i> Data Field Validation", _
"Using a Custom Attribute")
End Sub
End Class
using System;
using System.Collections;
using System.Configuration;
using System.Web.DynamicData;
public partial class CustomAttributeValidation : System.Web.UI.Page
{
protected MetaTable _table;
protected void Page_Init(object sender, EventArgs e)
{
// Register control with the data manager.
DynamicDataManager1.RegisterControl(GridView1);
}
protected void Page_Load(object sender, EventArgs e)
{
// Get the table entity.
_table = GridDataSource.GetTable();
// Assign title dynamically.
Title = string.Concat("Customize <i>Phone</i> Data Field Validation",
"Using a Custom Attribute");
}
}
Kompilieren des Codes
Zum Kompilieren des Beispielcodes benötigen Sie Folgendes:
Microsoft Visual Studio 2008 Service Pack 1 oder Visual Web Developer 2008 Express Edition Service Pack 1
Die AdventureWorksLT-Beispieldatenbank. Informationen über das Herunterladen und Installieren der SQL Server-Beispieldatenbank finden Sie auf der CodePlex-Website unter Microsoft SQL Server Product Samples: Database. Vergewissern Sie sich, dass Sie die richtige Version der Beispieldatenbank für die von Ihnen verwendete SQL Server-Version (Microsoft SQL Server 2005 oder Microsoft SQL Server 2008) installieren.
Eine Dynamic Data-basierte Website. So können Sie einen Datenkontext für die Datenbank erstellen und die Klasse erstellen, die das anzupassende Datenfeld und die zu überschreibenden Methoden enthält. Weitere Informationen hierzu finden Sie unter Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding.
Siehe auch
Konzepte
Übersicht über ASP.NET Dynamic Data-Feldvorlagen
Übersicht über das ASP.NET Dynamic Data-Modell
Übersicht über ASP.NET Dynamic Data
Referenz
Partielle Klassen und Methoden (C#-Programmierhandbuch)
Änderungsprotokoll
Date |
Versionsgeschichte |
Grund |
---|---|---|
Juli 2008 |
Thema hinzugefügt. |
SP1-Featureänderung. |