Partager via


Comment : personnaliser la validation des champs de données dans le modèle de données à l'aide d'attributs personnalisés

Mise à jour : Juillet 2008

Dynamic Data ASP.NET vous permet de personnaliser et d'étendre la validation des champs de données au niveau de la couche données. Cette rubrique vous indique comment ajouter la validation des champs de données dans le modèle de données en procédant comme suit :

  • Création d'un attribut de validation personnalisé. Cet attribut vous permet de créer des métadonnées personnalisées que vous utilisez dans le modèle de données pour la validation.

  • Application de l'attribut de validation personnalisé. Après avoir créé l'attribut personnalisé, vous l'appliquez aux champs de données que vous souhaitez valider.

Exécutez un exemple en ligne de cette fonctionnalité.

Création d'un attribut de validation personnalisé

Un attribut de validation personnalisé vous permet de créer des métadonnées que vous pouvez utiliser dans le modèle de données pour valider des champs de données. Vous devez dériver l'attribut personnalisé de la classe de base ValidationAttribute.

Pour créer un attribut de validation personnalisé

  1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le dossier App_Code, puis cliquez sur Ajouter un nouvel élément.

  2. Sous Ajouter un nouvel élément, cliquez sur Classe.

    Dans la zone Nom, entrez le nom de la classe d'attributs de validation personnalisés. Vous pouvez utiliser tout nom qui n'est pas déjà utilisé. Par exemple, vous pouvez entrer le nom CustomAttribute.vb en Visual C# ou CustomAttribute.vb en Visual Basic pour créer une classe d'attributs personnalisés nommée CustomAttribute.

  3. Ajoutez des références aux espaces de noms System, System.Web.Globalization et System.ComponentModel.DataAnnotations à l'aide du mot clé Imports dans Visual Basic ou du mot clé using dans Visual C#, comme le montre l'exemple suivant :

    using System;
    using System.Globalization;
    using System.ComponentModel.DataAnnotations;
    
    Imports System
    Imports System.Globalization
    Imports System.ComponentModel.DataAnnotations
    
  4. Apportez les modifications suivantes à la définition de classe :

    • Faites en sorte que cette classe ne puisse être héritée. Ajoutez le mot clé NotInheritable dans Visual Basic ou le mot clé sealed dans Visual C#.

    • Dérivez la classe du type de base ValidationAttribute.

    • Appliquez l'attribut AttributeUsageAttribute à la définition de classe pour déclarer comment votre attribut de validation personnalisé doit être utilisé.

    L'exemple suivant illustre une définition de classe. Les paramètres AttributeUsageAttribute sont définis de manière à ce que l'attribut de validation personnalisé puisse être appliqué aux propriétés ou aux champs une seule fois.

    [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. Substituez la méthode IsValid et ajoutez une logique pour effectuer la validation. Retournez la valeur true si la validation personnalisée est réussie, ou false si elle échoue. La valeur à valider est passée à la méthode en tant que paramètre unique.

    L'exemple suivant illustre la méthode substituée.

    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. Facultativement, substituez la méthode FormatErrorMessage pour effectuer une mise en forme de message d'erreur personnalisé.

    L'exemple suivant indique comment utiliser le nom du champ de données dont la validation a échoué pour générer un message d'erreur personnalisé. La valeur ErrorMessageString est passée en tant que paramètre lorsque l'attribut personnalisé est appliqué au champ de données.

    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. Enregistrez et fermez le fichier d'attribut de classe.

Application d'un attribut de validation personnalisé

Pour personnaliser la validation pour un champ de données, vous devez implémenter une classe partielle qui étend le modèle de données. Cela vous permet d'appliquer l'attribut personnalisé au champ de données.

Pour créer une classe partielle pour la validation

  1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le dossier App_Code, puis cliquez sur Ajouter un nouvel élément.

  2. Sous Modèles Visual Studio installés, cliquez sur Classe.

    Dans la zone Nom, entrez le nom de la table de base de données pour laquelle vous souhaitez ajouter la validation.

    Le nom de classe doit correspondre au nom de classe d'entité qui représente la table. Par exemple, si vous souhaitez ajouter la validation à la table Customers, vous devez nommer le fichier Customer.cs en Visual C# ou Customer.vb en Visual Basic, puis nommer la classe Customer.

  3. Ajoutez le mot clé Partial dans Visual Basic ou le mot clé partial dans Visual C# à la définition de classe pour en faire une classe partielle. 

  4. Si vous créez la classe dans Visual C#, supprimez le constructeur par défaut.

    L'exemple suivant montre la déclaration de classe mise à jour.

    public partial class Customer {
    
    }
    
    Partial Public Class Customer
    
    End Class
    
  5. Ajoutez des références aux espaces de noms System.Web.DynamicData et System.ComponentModel.DataAnnotations à l'aide du mot clé Imports dans Visual Basic ou du mot clé using dans Visual C#, comme le montre l'exemple suivant :

    using System.Web.DynamicData;
    using System.ComponentModel.DataAnnotations;
    
    Imports System.Web.DynamicData
    Imports System.ComponentModel.DataAnnotations
    
  6. Dans le même fichier, créez une deuxième classe qui servira de classe de métadonnées associée. Vous pouvez lui donner n'importe quel nom du moment que celui-ci est valide et qu'il n'est pas déjà utilisé.

    L'exemple suivant montre une déclaration de classe de métadonnée.

    public class CustomerMetadata
    {
    
    }
    
    Public Class CustomerMetadata 
    
    End Class
    

    La classe de métadonnées associée fournit un objet auquel vous pouvez appliquer des attributs de validation.

  7. Appliquez l'attribut MetadataTypeAttribute à la définition de classe partielle. Pour le paramètre de l'attribut, utilisez le nom de la classe de métadonnées associée que vous avez créée à l'étape précédente.

    L'exemple suivant présente la définition de classe partielle avec l'attribut ajouté.

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

Vous pouvez maintenant appliquer l'attribut de validation personnalisé à un champ de données.

Pour appliquer un attribut de validation personnalisé à un champ de données

  1. Dans la classe de métadonnées, créez une propriété ou un champ dont le nom correspond au champ de données à valider.

  2. Appliquez l'attribut de validation personnalisé que vous avez créé précédemment au champ de données que vous souhaitez valider.

    L'exemple suivant indique comment appliquer l'attribut de validation personnalisé au champ de données Phone.

    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. Enregistrez et fermez le fichier de classe.

Exemple

L'exemple suivant indique comment créer et appliquer un attribut personnalisé nommé PhoneMaskAttribute au champ de données Phone de la table Customer dans la base de données AdventureWorksLT. L'exemple utilise une classe LINQ to SQL pour le modèle de données.

L'attribut donne l'ordre à Dynamic Data de valider le champ de données Phone en fonction d'un masque qui représente un format de numéro de téléphone spécifique. Si le numéro de téléphone entré par l'utilisateur ne correspond pas au masque, le code de l'attribut émet une erreur personnalisée.

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");

    }
}

Compilation du code

Pour compiler cet exemple de code, vous avez besoin des éléments suivants :

  • Microsoft Visual Studio 2008 Service Pack 1 ou Visual Web Developer 2008 Express Service Pack 1. 

  • L'exemple de base de données AdventureWorksLT. Pour plus d'informations sur le téléchargement et l'installation de l'exemple de base de données SQL Server, consultez Exemples de produits Microsoft SQL Server : Base de données (en anglais) sur le site CodePlex. Prenez soin d'installer la version appropriée de l'exemple de base de données pour la version de SQL Server que vous exécutez (Microsoft SQL Server 2005 ou Microsoft SQL Server 2008).

  • Un site Web dynamique piloté par des données. Cela vous permet de créer un contexte de données pour la base de données et de créer la classe qui contient le champ de données à personnaliser et les méthodes à substituer. Pour plus d'informations, consultez Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding.

Voir aussi

Concepts

Vue d'ensemble des modèles de champs Dynamic Data ASP.NET

Vue d'ensemble des modèles de données Dynamic Data ASP.NET

Vue d'ensemble de Dynamic Data ASP.NET

Référence

ValidationAttribute

DynamicValidator

Classes et méthodes partielles (Guide de programmation C#)

Historique des modifications

Date

Historique

Raison

Juillet 2008

Ajout d'une rubrique.

Modifications de fonctionnalités dans le SP1.