Exercise 1: Adding Custom Range Validation Using Validation Attributes

In this exercise, you will learn how to create a custom validation by using MVC3 ValidationAttribute class at server side. For that purpose, you will include a range validation in the Store Manager example to validate that the price of an album belongs to a certain range.

Task 1 – Adding a validation attribute class

In this task, you will add a validation attribute class at server side. Each attribute to be validated should have a new class inherited from ValidationAttribute.

  1. Open the begin solution MvcMusicStore.sln at Source\Ex01-Server Side Custom Validation\Begin
  2. Create a new folder Validations at project root, which will include all the custom rules.
  3. Add a new C#(Visual Basic) class into the Validations folder and rename it to PriceValidationAttribute.[cs|vb].
  4. Open PriceValidationAttribute.[cs|vb] and add a reference to the System.ComponentModel.DataAnnotations namespace:

    C#

    using System;
    FakePre-447fed3c96b44068a083f301518f7a94-264ca49cd2164e8b8c24b3f73ead9905FakePre-3ef2401ef63f49e88eab5cbcb8691947-f66891b855fc46b5bca93b9e71a5b2causing System.ComponentModel.DataAnnotations;

    Visual Basic

    Imports System
    FakePre-46839c3b12684abf9c57966baa9daea1-a48a368783584ef283facc9adfbfa0f5FakePre-63c8ac65b5ce41108102e87cedd24a23-b0fb2fe86fde4a8fbe6515ab38577d6fImports System.ComponentModel.DataAnnotations

  5. Inherit the PriceValidationAttribute class from ValidationAttribute. Additionally, you have to add the AttributeUsage attribute specification, which in this case can be set to fields and properties:

    C#

    using System;
    FakePre-b7efea30a2864ccbbeeb82b23eda3068-88f3009356394a8cb1ab67d20ed70cb5FakePre-167a7382f234444bbbda8722f75451a5-78952e94569c4c9aa13bfb5e0385249eFakePre-4ef85c3717a948e282907878a77b0d11-90dd7fadfd0b4b2a9360dc290ec12ab5FakePre-316c196783824c77a4fe7277554cb31d-3de39ba499d841a4bf15710501af85d1[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]FakePre-9ec335e1c2874010b7b954a100b45170-9e51438833a14cc789573f316fbdf2f9FakePre-fbf38cd2c43b45f7aa8a3fd6b9908152-751d1395786940b8af9498f8b4e5f26eFakePre-c0e35210b00842fab1acec609ac83252-05c477e53d4a483d80d45d1288dd5a07

    Visual Basic

    Imports System
    FakePre-26934cd979634823b85aeb900d249431-55bf0dfdae2c499792ece334cfcdd00dFakePre-35347532c4ee4b56949b35295e7bdfff-f5fcc15a10674d67bc0c166a0a93bd21FakePre-4d16b53a0ff742f7a8018192f88089d7-34973d3f2c9249bea171dbb94ddef388FakePre-3d10e2a0eb774d51a9d0700c53dfed6a-8145c158ce5e460aadbf559878d26341<AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple := false, Inherited := true)>FakePre-d634e3011c67472aad0ade0acd7e53b1-c63bbcf262494bea87c9e15ed585db8bFakePre-d144ab7099314d4da41aaa4625b28817-ac70b5ed5f1f4793b6e7295e56c43310FakePre-929234ac5dbc4e30ad73231f10a31c2a-692fcf6acc654c91ab002b9659f0d9bb

    Note:
    AttributeUsage determines how custom attribute class’s attributes can be applied.

    -C#-

    [System.AttributeUsage(System.AttributeTargets.All,

    AllowMultiple = false, Inherited = true)]

    -Visual Basic-

    <System.AttributeUsage(System.AttributeTargets.All,

    AllowMultiple = false, Inherited = true)>

    AttributeTargets: This parameter specifies all the application elements on which it is valid to apply an attribute. It is possible to use System.AttributeTargets.All, or to specify each member (for example, Class, Property, Method or Field).

    AllowMultiple: If it is set to true, then the attribute can be applied more than once in the target 

    Inherit: If it is set to false, then the attribute is not inherited by derived attribute classes.

    You could read more about AttributeUsage in msdn.

  6. Define the thresholds for the album price range. To do this, add the following code to the generated class:

    (Code Snippet – ASP.NET MVC 3 Custom Validation – Ex1 Custom Range Validation Thresholds - CSharp)

    C#

    using System;
    FakePre-31790c1bd1a7499b8066ce5067b37a8e-5fb2c462ba6c4fef86c87df7663dd66dFakePre-799ae750cccf4cb59bb3ec7a11bd42cd-4c302275179f470caa98453621705efeFakePre-451fb078b1f04f92b3c671a230320c34-3aeb4446ca1446d5b0bd78656b181a51FakePre-35eb212fd43641899244824bfbde1b97-bd0f2d7e6ab5429691d6c3fcfdaf7ed2FakePre-2cb4a92d350b4e1e971d072345c0ecd1-e9c70b8194b14b2ca1731775e9759f1fFakePre-98a0842e843d4100ad804dc9e174664c-bcfc8acffacd4c9393bcab81bbba7e95FakePre-281335a8c80e4c5eae2a945cf9fb885f-7234633c5fc342ca878bf21808b3eb60FakePre-25e8f20ad90c48b7a91b4a44d8fca22a-35121107d4e44f07b43196b00b197153FakePre-1aeea78dfeb5401bbee18edfde6a450f-ab3410393f80408dbc137d5364c7f1c2FakePre-a14221cffa7043fdbf098599f2f62a8e-878018ee31d74941b714ee2fb9e64cc8 private decimal minPrice = 0.01M; private decimal maxPrice = 100.00M;FakePre-6c794ef8122348798643eb82f67b9865-df3620ae6a7e46ffaffe36cee4e00437FakePre-e32316aa3a184361b1c4171f079d9bed-05bfe3797f5344da9bcc18da10b5681c

    (Code Snippet – ASP.NET MVC 3 Custom Validation – Ex1 Custom Range Validation Thresholds - VB)

    Visual Basic

    Imports System
    FakePre-8acacaa82d7a44869ec36970ddf70f80-950cd30264a54dd89e40bd454c57ffcfFakePre-bc711b01aa2a41eb9879545edee5a606-57d8be2bf8464350ae6a2accb81fdb4aFakePre-8b1e9f25f0054f16b4e8c8924f01eeba-be50d8f87a334b9a991df5925e70cc13FakePre-51cc2e4139d0478bbbf31a50db6d1ebb-4902984029fb4ceb9d44bac07bf264a8FakePre-a849ba3a085f4cb88b19397e88c5e5ee-f780524d7d9b41cdb9d83885c3d47febFakePre-0b066d5ca5444a28a8c6a703635eec80-5d647fcfbb9a4194b6f049842b9b54e3FakePre-bd541c8a76a440febff299306cee1118-373f452cfb574803b8e4023c1716ec73FakePre-1e0d96137a4348fd9a74e26271578954-84909bb9ce3c40abbded20726588345eFakePre-80ffef2ee01c4b09ab1c0c1d86b968b3-b4190e6c8cd14305807966e360500fb3FakePre-b224d554ebd14d0386197f39244bf7f5-e8b3d01342ff47448518dfc435838992FakePre-d16eb37b23074264ae5d3f807bd7172e-c235f84ac76248d7948b29e9fd125d80 Private minPrice As Decimal = 0.01D Private maxPrice As Decimal = 100DFakePre-e1dff0949902479aac4c1e5f96eb0b1d-89e0e375e22845609c0f3db311dd1571FakePre-65ac7b4db3144c0b93eb619803ba7160-4600f2700481491a802cfc428296feecFakePre-3e8f71d599fd41ddb88505dfd50883a5-92114666315f420db8d9f0c3c28c0f90

    Note:
    The values of minPrice and maxPrice are initialized here, but they could be retrieved from a database query or a Web Service call, making the application more maintainable.

  7. Implement a class initializer and the method IsValid from the base class. This step is required for custom validation at server side:

    (Code Snippet – ASP.NET MVC 3 Custom Validation – Ex1 Custom Range Validation IsValid- CSharp)

    C#

    using System;
    FakePre-264ac02d1d73432ca73055a5b8e65b56-a156192512754ca288eb3e9ad9f0c20aFakePre-7f868b02b76b4dd798627e6b5fdeca97-10e30c934c0d419b92ddb4e71583c350FakePre-a0739bce8a1346379616a2e824316f00-7e9ec588831f4a0aaf5ec21200cde8f1FakePre-6c78fb73e4654707add93e0eb30a01d5-3aaf2a02fdbf4b638a3c850bd201c224FakePre-80f6b2b313174a42b3168936075cec05-46b373b469064ccab9764cc68458e412FakePre-f260b74c71044e35bdebc33dd60f01a8-64652230fd7c4f73afa6c6221e64fb97FakePre-5f88e0bbdddf463a95c875924fe9a369-46b0dd99cfed458491e41a6fa3e23abfFakePre-0195c23cfc274b6aa7fe548d2228ed18-11d5746c87b44e0881f644b346c2edffFakePre-681c68ddb58543c899893f53413f3860-9dfefcd3154a4c0cb4a35fb530bc29ecFakePre-960edbeda08d46ff9b89cf36fc178cee-e9ec2b9952d2487d9610a42dee99e2c6FakePre-01254aa228104ae9ac5581dde25f1b03-880a670987e84166a47bba939df93144 public PriceValidationAttribute(): base("The price is not in a valid range") { } public override bool IsValid(object value) { decimal price = (decimal)value; if (price < this.minPrice || price > this.maxPrice) return false; return true; }FakePre-f302dc7d9b494e17b19c9cb9fccc81dc-eb1550acffc047fdaa4118c939b894ffFakePre-d4d3a82b67be4a5b824647b979ce13b2-041fd86ba5284c48b0ae23bc027a7b9d

    (Code Snippet – ASP.NET MVC 3 Custom Validation – Ex1 Custom Range Validation IsValid- VB)

    Visual Basic

    Imports System
    FakePre-aab212311b714aefb97c1611b3fbef10-2068b295d5ff4105b37b58493f0eeb25FakePre-62228fe13c234a9daf738396363493bf-2749e065682041ac993e342d6c0711d6FakePre-c99957792d0c46dda7fd25be9af93f31-b065f8f1453b46a882dc6d047cf600e2FakePre-b07126ccb09e4a689f71864d3e7d89c0-dc741811270b4cd6bab4eb677595eca9FakePre-a64992c7c5af45afa99f664a157df11c-1045cc384f1b46daa30840105c7b1950FakePre-e4cf307e95de4cb8b7f59d367332eb03-4f02ea3ec4bb45738c05ec74a2161d27FakePre-23a82fac73a14cd8b1526e100e45dfdb-9dad9ba03e424cf3b351045aab53c248FakePre-e2b7feb3178f4eee8d401e8ff15e68eb-64fce1a412d94f7fb72671d21364a485FakePre-08d3c5c9227f46ef886a3048a345c5d9-5d61d2f80b704794b338deed8b8e865cFakePre-a4c595efbe2f465d8a9e822150278f72-e96f5955bae643b7ab5346be9621c1b1FakePre-90d5005eb17e42d7a2bb8d38e210e542-e0e9db473f534f789ad7621e7ab3ea37FakePre-8a3fb078c7f943548f22a11206330b96-fb4b22710b1642b0aa40159bdf41fdae Public Sub New() MyBase.New("The price is not in a valid range") End Sub Public Overloads Overrides Function IsValid(ByVal value As Object) As Boolean Dim price = CDec(value) If price < Me.minPrice OrElse price > Me.maxPrice Then Return False End If Return TrueFakePre-3dcceaca21804c83acffe487001ac474-aa3abce1348c4d9f9faa5de2769cc4acFakePre-27e203f82d1f4ceaaa3b9da884485dce-05450c2f093948789ae3998c92ff9d6a

End Function

End Class

Task 2 – Creating the Custom Data Annotation

In this task, you will add a new data annotation tag to the Album class that will be automatically linked to the validation method just created:

  1. Open the Album.[cs|vb] file at MvcMusicStore\Models.
  2. Add Validations namespace into the Album class

    C#

    using MvcMusicStore.Validations;

    Visual Basic

    Imports MvcMusicStore.Validations

    Replace current data annotation with the PriceValidation attribute:

    C#

      [Range(0.01, 100.00, ErrorMessage = "Price must be between 0.01 and 100.00")]
    
    [PriceValidation]

    Visual Basic

      <Range(0.01, 100.00, ErrorMessage: = "Price must be between 0.01 and 100.00")>
    
    <PriceValidation()>

    After the replacement, the Album.[cs|vb] file should look like the following:

    C#

    namespace MvcMusicStore.Models { [MetadataType(typeof(AlbumMetaData))] public partial class Album { // Validation rules for the Album class ... [Required(ErrorMessage = "Price is required")] [PriceValidation] public object Price { get; set; } } }

    Visual Basic

    <MetadataType(GetType(Album.AlbumMetaData))> Partial Public Class Album 'Validation rules for the Album class ... <Required(ErrorMessage:="Price is required"), PriceValidation()> Public Property Price As Object End Class

Task 3 – Running the Application

In this task, you will test that the StoreManager Create View template validates the price using custom validation.

  1. Press F5 to run the Application.
  2. The project starts in the Home page. Browse /StoreManager/Create and click Save without filling the form to verify that you get the price range validation message:

    Figure 1

    Validating an album price

Next Step

Exercise 2: Adding validation at client side