Condividi tramite


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

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella App_Code, quindi scegliere Aggiungi nuovo elemento.

  2. 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.

  3. 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
    
  4. 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
    
  5. 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
    
  6. 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
    
  7. 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

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella App_Code, quindi scegliere Aggiungi nuovo elemento.

  2. 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.

  3. 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. 

  4. 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
    
  5. 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
    
  6. 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.

  7. 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

  1. Nella classe di metadati creare una proprietà o un campo il cui nome corrisponda al campo dati da convalidare.

  2. 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
    
  3. 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

ValidationAttribute

DynamicValidator

Classi e metodi parziali (Guida per programmatori C#)

Cronologia delle modifiche

Date

History

Motivo

Luglio 2008

Argomento aggiunto.

Modifica di funzionalità in SP1.