Procedura: personalizzare la convalida dei campi dati nel modello dati mediante gli attributi personalizzati
Aggiornamento: Luglio 2008
ASP.NET Dynamic Data consente di personalizzare ed estendere la convalida dei campi dati al livello dati. In questo argomento viene illustrato come aggiungere la convalida dei campi dati nel modello dati attenendosi alla seguente procedura:
Creazione di un attributo di convalida personalizzato. Questo attributo consente di creare metadati personalizzati da utilizzare nel modello dati per la convalida.
Applicazione dell'attributo di convalida personalizzato. Una volta creato, l'attributo personalizzato viene applicato ai campi dati che si desidera convalidare.
Eseguire un esempio in linea di questa funzionalità.
Creazione di un attributo di convalida personalizzato.
Un attributo di convalida personalizzato consente di creare metadati che possono essere utilizzati nel modello dati per convalidare i campi dati. È necessario derivare l'attributo personalizzato dalla classe base ValidationAttribute.
Per creare un attributo di convalida personalizzato
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella App_Code, quindi scegliere Aggiungi nuovo elemento.
In Aggiungi nuovo elemento, fare clic su Classe.
Nella casella Nome immettere il nome della classe dell'attributo di convalida personalizzato. È possibile utilizzare qualsiasi nome, purché non sia già utilizzato. Ad esempio, è possibile immettere il nome CustomAttribute.vb in Visual C# o CustomAttribute.vb in Visual Basic per creare una classe dell'attributo personalizzato denominata CustomAttribute.
Aggiungere riferimenti agli spazi dei nomi System, System.Web.Globalization e System.ComponentModel.DataAnnotations utilizzando la parola chiave Imports in Visual Basic o la parola chiave using in Visual C#, come illustrato nell'esempio seguente:
using System; using System.Globalization; using System.ComponentModel.DataAnnotations;
Imports System Imports System.Globalization Imports System.ComponentModel.DataAnnotations
Apportare le seguenti modifiche alla definizione della classe.
Impostare la classe in modo che non sia ereditabile. Aggiungere la parola chiave NotInheritable in Visual Basic o la parola chiave sealed in Visual C#.
Derivare la classe dal tipo di base ValidationAttribute.
Applicare l'attributo AttributeUsageAttribute alla definizione di classe per dichiarare come deve essere utilizzato l'attributo di convalida personalizzato.
Nell'esempio seguente viene illustrata una definizione di classe. I parametri AttributeUsageAttribute vengono impostati in modo che l'attributo di convalida personalizzato possa essere applicato a proprietà o a campi solo una volta.
[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
Eseguire l'override del metodo IsValid e aggiungere la logica per eseguire la convalida. Restituire true se la convalida personalizzata viene eseguita correttamente, o false se non riesce. Il valore da convalidare viene passato al metodo come unico parametro,
Nell'esempio riportato di seguito viene illustrato il metodo sottoposto a override.
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
Se lo si desidera, eseguire l'override del metodo FormatErrorMessage per eseguire una formattazione personalizzata dei messaggi di errore.
Nell'esempio riportato di seguito viene illustrato come utilizzare il nome del campo dati la cui convalida non è riuscita per compilare un messaggio di errore personalizzato. Il valore ErrorMessageString viene passato come parametro quando l'attributo personalizzato è applicato al campo dati.
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
Salvare e chiudere il file di attributi di classe.
Applicazione di un attributo di convalida personalizzato.
Per personalizzare la convalida per un campo dati, è necessario implementare una classe parziale che estenda il modello dati. Ciò consente di applicare l'attributo personalizzato al campo dati.
Per creare una classe parziale per la convalida
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella App_Code, quindi scegliere Aggiungi nuovo elemento.
In Modelli Visual Studio installati fare clic su Class.
Nella casella Nome immettere il nome della tabella di database per cui si desidera aggiungere la convalida.
Il nome della classe deve corrispondere al nome della classe di entità che rappresenta la tabella. Ad esempio, se si desidera aggiungere la convalida per la tabella Customers, è necessario assegnare al file il nome Customer.cs in Visual C# o Customer.vb in Visual Basic e assegnare alla classe il nome Customer.
Aggiungere la parola chiave Partial in Visual Basic o la parola chiave partial in Visual C# alla definizione della classe per renderla una classe parziale.
Se si crea la classe in Visual C#, eliminare il costruttore predefinito.
Nell'esempio riportato di seguito viene illustrata la dichiarazione di classe aggiornata.
public partial class Customer { }
Partial Public Class Customer End Class
Aggiungere riferimenti agli spazi dei nomi System.Web.DynamicData e System.ComponentModel.DataAnnotations utilizzando la parola chiave Imports in Visual Basic o la parola chiave using in Visual C#, come illustrato nell'esempio seguente:
using System.Web.DynamicData; using System.ComponentModel.DataAnnotations;
Imports System.Web.DynamicData Imports System.ComponentModel.DataAnnotations
Nello stesso file creare una seconda classe che fungerà da classe di metadati associata. È possibile utilizzare qualsiasi nome per la classe, purché sia valido e non già utilizzato.
Nell'esempio riportato di seguito viene illustrata la dichiarazione di una classe di metadati.
public class CustomerMetadata { }
Public Class CustomerMetadata End Class
La classe di metadati associata fornisce un oggetto a cui è possibile applicare attributi di convalida.
Applicare l'attributo MetadataTypeAttribute alla definizione della classe parziale. Per il parametro dell'attributo, utilizzare il nome della classe di metadati associata creata nel passaggio precedente.
Nell'esempio riportato di seguito viene illustrata la definizione della classe parziale a cui è stato aggiunto l'attributo.
[MetadataType(typeof(CustomerMetadata))] public partial class Customer { }
<MetadataType(GetType(CustomerMetadata))> _ Partial Public Class Customer End Class
È ora possibile applicare l'attributo di convalida personalizzato a un campo dati.
Per applicare un attributo di convalida personalizzato a un campo dati
Nella classe di metadati creare una proprietà o un campo il cui nome corrisponda al campo dati da convalidare.
Applicare l'attributo di convalida personalizzato creato precedentemente al campo dati che si desidera convalidare.
Nell'esempio seguente viene illustrato come applicare l'attributo di convalida personalizzato al campo dati Telefono.
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
Salvare e chiudere il file di classe.
Esempio
Nell'esempio seguente viene illustrato come creare e applicare un attributo personalizzato denominato PhoneMaskAttribute al campo dati Telefono della tabella Customer contenuta nel database AdventureWorksLT. Nell'esempio viene utilizzata una classe LINQ-to-SQL per il modello dati.
L'attributo indica a Dynamic Data di convalidare il campo dati Telefono rispetto a una maschera che rappresenta un formato specifico del numero di telefono. Se il numero di telefono immesso dall'utente non corrisponde alla maschera, il codice dell'attributo pubblica un errore personalizzato.
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");
}
}
Compilazione del codice
Per compilare il codice di esempio, è necessario quanto segue:
Microsoft Visual Studio 2008 Service Pack 1 o Visual Web Developer 2008 Express Edition Service Pack 1.
Database di esempio AdventureWorksLT. Per informazioni su come scaricare e installare il database di esempio di SQL Server, vedere Microsoft SQL Server Product Samples: Database (informazioni in lingua inglese) nel sito Web CodePlex. Assicurarsi di installare la versione del database di esempio appropriata per la versione di SQL Server in esecuzione (Microsoft SQL Server 2005 o Microsoft SQL Server 2008).
Sito Web basato su dati dinamici che consente di creare un contesto dati per il database nonché la classe che contiene il campo dati da personalizzare e i metodi di cui eseguire l'override. Per ulteriori informazioni, vedere la classe Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding.
Vedere anche
Concetti
Cenni preliminari sui modelli di campo di ASP.NET Dynamic Data
Cenni preliminari sul modello di ASP.NET Dynamic Data
Cenni preliminari su ASP.NET Dynamic Data
Riferimenti
Classi e metodi parziali (Guida per programmatori C#)
Cronologia delle modifiche
Date |
History |
Motivo |
---|---|---|
Luglio 2008 |
Argomento aggiunto. |
Modifica di funzionalità in SP1. |