Compartir a través de


Cómo: Personalizar la validación de campos de datos en el modelo de datos mediante atributos personalizados

Actualización: Julio de 2008

Los datos dinámicos de ASP.NET permiten personalizar y extender la validación del campo de datos al nivel de la capa de datos. En este tema se explica cómo agregar la validación de campos de datos del modelo de datos realizando los siguientes pasos:

  • Crear un atributo de validación personalizado. Este atributo permite crear metadatos personalizados que se utilizan en el modelo de datos para la validación.

  • Aplicar el atributo de validación personalizado. Una vez creado el atributo personalizado, lo aplica a los campos de datos que desea validar.

Ejecute un ejemplo en línea de esta característica.

Crear un atributo de validación personalizado

Un atributo de validación personalizado le permite crear metadatos que puede utilizar en el modelo de datos para validar campos de datos. Debe derivar el atributo personalizado de la clase base ValidationAttribute.

Para crear un atributo de validación personalizado

  1. En el Explorador de soluciones, haga clic con el botón secundario en la carpeta App_Code y, a continuación, haga clic en Agregar nuevo elemento.

  2. En Agregar nuevo elemento, haga clic en Clase.

    En el cuadro Nombre, escriba el nombre de la clase de atributo de validación personalizado. Puede utilizar cualquier nombre que aún no se utilice. Por ejemplo, puede escribir el nombre CustomAttribute.vb en Visual C# o CustomAttribute.vb en Visual Basic para crear una clase de atributo personalizado denominada CustomAttribute.

  3. Agregue referencias a los espacios de nombres System, System.Web.Globalization y System.ComponentModel.DataAnnotations utilizando la palabra clave Imports de Visual Basic o la palabra clave using de Visual C#, tal como se muestra en el siguiente ejemplo:

    using System;
    using System.Globalization;
    using System.ComponentModel.DataAnnotations;
    
    Imports System
    Imports System.Globalization
    Imports System.ComponentModel.DataAnnotations
    
  4. Realice los siguientes cambios en la definición de clase:

    • Haga la clase no heredable. Agregue la palabra clave NotInheritable en Visual Basic o la palabra clave sealed en Visual C#.

    • Derive la clase del tipo base ValidationAttribute del tipo base.

    • Aplique el atributo AttributeUsageAttribute a la definición de clase para indicar cómo se debe utilizar su atributo de validación personalizado.

    En el ejemplo siguiente se muestra una definición de clase. Los parámetros AttributeUsageAttribute se establecen para que el atributo de validación personalizado se pueda aplicar a propiedades o campos solo una vez.

    [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. Invalide el método IsValid y agregue lógica para realizar la validación. Devuelve true si la validación personalizada se realiza correctamente, o false si se produce un error. El valor que se va a validar se pasa al método como el único parámetro.

    En el siguiente ejemplo se muestra el método invalidado.

    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. Opcionalmente, invalide el método FormatErrorMessage para realizar el formato del mensaje de error personalizado.

    En el ejemplo siguiente se muestra cómo utilizar el nombre del campo de datos que produjo un error en la validación para generar un mensaje de error personalizado. El valor ErrorMessageString se pasa como un parámetro cuando el atributo personalizado se aplica al campo de datos.

    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. Guarde y cierre el archivo de atributo de clase.

Aplicar un atributo de validación personalizado

Para personalizar la validación de un campo de datos debe implementar una clase parcial que extienda el modelo de datos. Esto permite aplicar el atributo personalizado al campo de datos.

Para crear una clase parcial para la validación

  1. En el Explorador de soluciones, haga clic con el botón secundario en la carpeta App_Code y, a continuación, haga clic en Agregar nuevo elemento.

  2. En Plantillas instaladas de Visual Studio, haga clic en Clase.

    En el cuadro Nombre, escriba el nombre de la tabla de base de datos para la que desea agregar la validación.

    El nombre de clase debe coincidir con el nombre de la clase de entidad que representa la tabla. Por ejemplo, si desea agregar validación a la tabla Customers, debe asignar al archivo el nombre Customer.cs en Visual C# o Customer.vb en Visual Basic y asignar a la clase el nombre Customer.

  3. Agregue la palabra clave Partial de Visual Basic o la palabra clave partial de Visual C# a la definición de clase para convertirla en una clase parcial. 

  4. Si está creando la clase en Visual C#, elimine el constructor predeterminado.

    En el ejemplo siguiente se muestra la declaración de clase actualizada.

    public partial class Customer {
    
    }
    
    Partial Public Class Customer
    
    End Class
    
  5. Agregue referencias a los espacios de nombres System.Web.DynamicData y System.ComponentModel.DataAnnotations utilizando la palabra clave Imports de Visual Basic o la palabra clave using de Visual C#, tal y como se muestra en el siguiente ejemplo:

    using System.Web.DynamicData;
    using System.ComponentModel.DataAnnotations;
    
    Imports System.Web.DynamicData
    Imports System.ComponentModel.DataAnnotations
    
  6. En el mismo archivo, cree una segunda clase que actuará como la clase de metadatos asociada. Puede utilizar cualquier nombre para la clase que sea un nombre de clase válido y aún no se haya utilizado.

    En el ejemplo siguiente se muestra una declaración de clase de metadatos.

    public class CustomerMetadata
    {
    
    }
    
    Public Class CustomerMetadata 
    
    End Class
    

    La clase de metadatos asociada proporciona un objeto al que puede aplicar atributos de validación.

  7. Aplique el atributo MetadataTypeAttribute a la definición de clase parcial. Para el parámetro del atributo, utilice el nombre de la clase de metadatos asociada que creó en el paso anterior.

    En el ejemplo siguiente se muestra la definición de clase parcial con el atributo agregado.

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

Ahora puede aplicar el atributo de validación personalizado a un campo de datos.

Para aplicar un atributo de validación personalizado a un campo de datos

  1. En la clase de metadatos, cree una propiedad o campo cuyo nombre corresponda al campo de datos que desea validar.

  2. Aplique el atributo de validación personalizado que creó anteriormente al campo de datos que desea validar.

    En el ejemplo siguiente se muestra cómo aplicar el atributo de validación personalizado al campo de datos 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. Guarde y cierre el archivo de clase.

Ejemplo

El ejemplo siguiente muestra cómo crear y aplicar un atributo personalizado denominado PhoneMaskAttribute al campo de datos Phone de la tabla Customer de la base de datos AdventureWorksLT. En el ejemplo se utiliza una clase LINQ-to-SQL para el modelo de datos.

El atributo indica a los datos dinámicos que validen el campo de datos Phone respecto a una máscara que representa un formato de número de teléfono concreto. Si el número de teléfono especificado por el usuario no coincide con la máscara, el código de atributo emite un error personalizado.

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

    }
}

Compilar el código

Para compilar el código de ejemplo, necesita:

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

  • La base de datos de ejemplo AdventureWorksLT. Para obtener información sobre la forma de descargar e instalar la base de datos de ejemplo de SQL Server, vea Microsoft SQL Server Product Samples: Database en el sitio CodePlex. Asegúrese de que instala la versión correcta de la base de datos de ejemplo para la versión de SQL Server que esté ejecutando (Microsoft SQL Server 2005 o Microsoft SQL Server 2008).

  • Un sitio web dinámico controlado por datos. De este modo, se puede crear un contexto de datos para la base de datos y crear la clase que contiene el campo de datos que se va a personalizar y los métodos que se van a invalidar. Para obtener más información, vea Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding.

Vea también

Conceptos

Información general sobre las plantillas de campos de datos dinámicos de ASP.NET

Información general sobre el modelo de datos dinámicos de ASP.NET

Información general sobre los datos dinámicos de ASP.NET

Referencia

ValidationAttribute

DynamicValidator

Clases y métodos parciales (Guía de programación de C#)

Historial de cambios

Fecha

Historial

Motivo

Julio de 2008

Se ha agregado un tema.

Cambio de características de SP1.