Exercise 3: Using IValidatableObject Custom Validation

In this exercise, you will learn how to implement a custom server-side validation using ASP.NET4 IValidatableObject Interface. In the previous exercises you worked with validation attributes to perform custom validation of several attributes. Now you will use IValidatableObject to prevent the insertion of repeated albums, performing an extra validation at server side that will run after attribute validation is performed.

Task 1 – Implementing IValidatableObject Validation Method

  1. Open the begin solution MvcMusicStore.sln at Source\Ex03-Custom Validation IValidatableObject\Begin.
  2. Open the Album.[cs|vb] file at \Models and implement IValidatableObject interface:

    C#

    FakePre-81b223c27dd34329bccc05a938d25057-28ec03938b6a4a208507ce7cbe9e62fcFakePre-a842b28dbee44041a1b0bed0ce53c548-e17a8c185fb94c8aac62e94991e51151FakePre-2b55a25a4ddf4295aa53592c452b58cd-ce2d222cfe924d22b65b2f39526eab08FakePre-ff625ba7b3ec4b08bb61b418e97c381c-007d93e6aea4451f8cbbaff9db20a6b4FakePre-e7b120227b7648a29cdc6dc78b3bf500-7872dd5738384c8bb50b07581de6865fFakePre-82acb11c92f44c5c998b02f5b13d03b3-91e2812b2ceb4462bfef3673e86c61e3

    Visual Basic

    … <MetadataType(GetType(Album.AlbumMetaData))> Partial Public Class Album Implements IValidatableObject …

    Note:
    IValidatableObject interface (from System.ComponentModel.DataAnnotation) provides a way to invalidate an object. It has one member, Validate Method, which determines if the object that implements the interface is valid:

    -C#-

    IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

    -Visual Basic-

    Validate(ByVal validationContext As ValidationContext) As IEnumerable(Of ValidationResult)

    You could read more about ValidationContext in msdn.

  3. Implement IValidatableObject Validate method on Album class. The method will check if there is any album with the same title and artist in the database and returns a ValidationResult object.

    (Code Snippet – ASP.NET MVC 3 Adding IValidatableObject validation – Ex3 Validate method - CSharp)

    C#

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { MusicStoreEntities storeDB = new MusicStoreEntities(); if (storeDB.Albums.Any(a => a.Title.Trim().ToUpper() == this.Title.Trim().ToUpper() && a.ArtistId == (int)this.ArtistId)) yield return new ValidationResult("Existing Album", new string[] { "Title" }); }

    (Code Snippet – ASP.NET MVC 3 Adding IValidatableObject validation – Ex3 Validate method - VB)

    Visual Basic

    Public Function Validate(ByVal validationContext As ValidationContext) As IEnumerable(Of ValidationResult) Implements IValidatableObject.Validate Dim storeDB As New MusicStoreEntities Dim result = New List(Of ValidationResult) If storeDB.Albums.Any(Function(a) (a.Title.Trim().ToUpper() = Me.Title.Trim().ToUpper()) AndAlso (a.ArtistId = CInt(Me.ArtistId))) Then result.Add(New ValidationResult("Existing Album", New String() {"Title"})) End If Return result End Function

    Note:
    ValidationResult has a message (“Existing album”) and a target field in which the error is associated (“Title”). You will later note that the error message is displayed next to Title field. 

    As Validate method is implemented into Model classes, you might not feel comfortable with the idea of having logic inside the model. For that reason, the use of partial classes to implement Validate method is recommended. 

Task 2 – Running the Application

In this task, you will try to create a repeated album to test the validation.

  1. Press F5 to run the Application.
  2. The project starts in the Home page. Browse /StoreManager/Create.
  3. Fill the form with the following data: “Greatest Hits” in the Title field and “Lenny Kravitz” for Artist. Then, write any valid data in the other fields.
  4. Press Save to submit the form. You will get the error message Existing Album at the right of the title:

    Figure 3

    Validating the insertion of an existing album

Next Step

Exercise 4: Using Unobtrusive jQuery at client side