How to: Validate Model Data Using DataAnnotations Attributes

This topic illustrates how to use attributes from the System.ComponentModel.DataAnnotations namespace to specify validation for individual fields in the data model. These attributes define common validation patterns, such as range checking and required fields. The System.ComponentModel.DataAnnotations attributes cause MVC to provide both client and server validation checks with no additional coding required by you.

The System.ComponentModel.DataAnnotations attributes can be used with the Entity Data Model (EDM), LINQ to SQL, and other data models. You can also create custom validation attributes. For more information, see How to: Customize Data Field Validation in the Data Model Using Custom Attributes.

A Visual Studio project with source code is available to accompany this topic: Download.

The following illustration shows error messages that are automatically displayed in a browser when client-side validation fails.

Messages displayed in the browser in response to validation errors

Validation Errors

To add validation using DataAnnotations attributes

  1. Add a class to your project to contain the partial class definitions. For more information, see How to: Customize Data Field Validation in the Data Model.

  2. Add a namespace declaration to the partial class that matches the namespace of the data model that you are using.

    Note

    An incorrect namespace used in a partial class results in a naked partial class, which is a partial class that is not associated with any other class. A naked partial class is typical reason that DataAnnotations attributes are not recognized by the data model. To avoid this problem, you can copy the namespace from the data model code to make sure that you have the correct namespace.

  3. Name the partial class to match the class declaration that represents the table in the data model and paste it into the new class file.

    Note

    It is important that the class names match exactly. The easiest way to make sure that the name of the partial class matches is to copy it.

    The following example shows a partial class for the Product table from the AdventureWorksLT_2008 sample database. In this example, the database is represented by the MvcDA namespace.

    using System.ComponentModel.DataAnnotations;  
    namespace MvcDA {
        [MetadataType(typeof(ProductMD))]
        public partial class Product {
            public class ProductMD {
                [StringLength(50),Required]
                public object Name { get; set; }
                [StringLength(15)]
                public object Color { get; set; }
                [Range(0, 9999)]
                public object Weight { get; set; }
              //  public object NoSuchProperty { get; set; }
            }
        }
    }
    
    Imports System.ComponentModel.DataAnnotations
    
    <MetadataType(GetType(ProductMD))> _
    Partial Public Class Product
    End Class
    
    Public Class ProductMD
        Private _Name As Object
        <StringLength(60)> _
        <Required()> _
        Public Property Name() As Object
            Get
                Return _Name
            End Get
            Set(ByVal value As Object)
                _Name = value
            End Set
        End Property
    
        Private _Color As Object
        <StringLength(60)> _
        Public Property Color() As Object
            Get
                Return _Color
            End Get
            Set(ByVal value As Object)
                _Color = value
            End Set
        End Property
    
        Private _Weight As Object
        <Required(), StringLength(50)> _
        Public Property Weight() As Object
            Get
                Return _Weight
            End Get
            Set(ByVal value As Object)
                _Weight = value
            End Set
        End Property
    
        'Private _NoSuchProperty As Object
        '<Required(), StringLength(30)> _
        'Public Property NoSuchProperty() As Object
        '    Get
        '        Return _NoSuchProperty
        '    End Get
        '    Set(ByVal value As Object)
        '        _NoSuchProperty = value
        '    End Set
        'End Property
    
    End Class
    

    Note

    The property named NoSuchProperty is included in the class and is commented out. You can use this property to test the partial class, as explained later in this topic.

  4. Create an associated class (sometimes referred to as a buddy class) that contains the properties of the partial class that represent the table.

    The associated class can have any name; a convention is to append "MD" or "MetaData" to the table class name. The associated class must be used with EDM or LINQ-to-SQL models because CLR types cannot mark existing properties with new attributes. If you are working with CLR objects directly, sometimes referred to as Plain Old CLR Object (POCO) types, you can apply the attributes directly to the model.

  5. Associate the new class with the table class by using the MetadataTypeAttribute attribute.

    In the previous example, the new class is associated with the table class in the following lines:

    [MetadataType(typeof(ProductMD))]
    
    <MetadataType(GetType(ProductMD))> _
    
  6. Apply System.ComponentModel.DataAnnotations attributes to the properties. You can apply any number of attributes to each property.

Testing the Partial Class

If the data annotations you applied are not recognized, you should verify that the partial class is recognized in the project. The following procedure suggests one way to test the class.

To test the partial class

  1. Add a property to the partial class whose name does not match a property in the corresponding data model.

    For example, uncomment the NoSuchProperty property that is shown in the example in the previous procedure.

  2. Run the project and enter data to be validated.

    If the partial class is recognized, when validation occurs, an InvalidOperationException exception is thrown with a message similar to the following:

    The associated metadata type for type 'MvcDA.Product' contains the following unknown properties or fields: NoSuchProperty. Please make sure that the names of these members match the names of the properties on the main type.

    If the partial class is naked, no exception is thrown. In that case, examine the partial-class name to make sure it matches the corresponding class name in the data model and the correct namespace has been used.

  3. Remove the property in the partial class that you added for testing.

Adding Client-Side Validation

After adding server-side validation, you can add client-side validation by including the necessary JavaScript validation files and enabling client-side validation.

To add client side validation

  • Add references to the JavaScript validation files to the view that contains the elements that you want to validate. (A common practice is to include them in the Site.master file so they apply to every view.)

    The following example shows how to reference the JavaScript files that are required in order to include client-side validation. (In this example, the references are made to the debug versions of the libraries.) The example also shows how to call the EnableClientValidation method in order to enable client-side validation. A common way to enable client validation is to add the following code to the Site.master file. However, you can also add it to the view page that is implementing client-side validation. If you include the following code in the master page, every view has client-side validation automatically enabled.

    <head runat="server">
      <script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script>
      <script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
      <script src="<%= Url.Content("~/Scripts/MicrosoftMvcValidation.debug.js") %>" type="text/javascript"></script>
      <% Html.EnableClientValidation();%>
    </head> 
    
    <head runat="server">
      <script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script>
      <script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
      <script src="<%= Url.Content("~/Scripts/MicrosoftMvcValidation.debug.js") %>" type="text/javascript"></script>
      <% Html.EnableClientValidation()%>
    </head>
    

Compiling the Code

To compile the example code, you need the following:

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

  • The AdventureWorksLT_2008 sample database. For information about how to download and install the SQL Server sample database, see Microsoft SQL Server Product Samples: Database on the CodePlex site. Make sure that you install the correct version of the sample database for the version of SQL Server that you are running (Microsoft SQL Server 2005 or Microsoft SQL Server 2008).

  • An MVC application that has an EDM that was created from the AdventureWorksLT_2008 sample database. For more information, see the tutorial Creating Model Classes with the Entity Framework on the ASP.NET Web site.

See Also

Tasks

Walkthrough: Using Templated Helpers to Display Data in ASP.NET MVC

Other Resources

How to: Customize Data Field Validation in the Data Model Using Custom Attributes