MVC 3 Unobtrusive Validation with LINQ to SQL

Recently I've been working on a small project that uses LINQ to SQL as it's data layer (it's a very simple model) and contains two presentation projects - a web form application for the front end and an MVC 3 administration panel.

When playing with the unobtrusive validation engine, you'll find many examples on the 'net telling you to decorate your model with various attributes from the System.ComponentModel.DataAnnotations namespace. Now, I ran in to a bit of an issue with the LINQ to SQL objects - they're generated dynamically. I could add the attributes, but they would be overwritten any time I made a change to my DBML file. So, after a bit of searching I came across the MetaDataTypeAttribute in the same namespace. This attribute allows you to create a completely separate, standard class and define it as a Meta Data container for another class. Neat, hu?

Well, I quickly ran in to my second issue - I could create my separate class, but I still had to tag the LINQ classes with the attribute... which meant that data would also be overwritten.

LINQ classes are partial classes - it didn't dawn on me for a few hours, but I could effectively create another partial class in the DBML's code behind file (right click on the DBML file -> View Code) and decorate THAT class with the attribute - which would never be overwritten by the code generator. Below is what my LINQ code behind looks like. This example also includes a CustomValidationAttribute example, which took me a little bit to figure out:


   1:  using System;
   2:  using System.Text;
   3:  using System.ComponentModel.DataAnnotations;
   4:   
   5:  namespace MyNameSpace {
   6:      [MetadataType(typeof(News_Validation))]
   7:      partial class News {
   8:      }
   9:      [MetadataType(typeof(ExclusionDate_Validation))]
  10:      partial class ExclusionDate {
  11:      }
  12:      public sealed class News_Validation {
  13:          [Required(ErrorMessage = "Post content is required.")]
  14:          public string Content { get; set; }
  15:      }
  16:      public sealed class ExclusionDate_Validation {
  17:          [Required(ErrorMessage = "'Date To Replace' is required."), CustomValidation(typeof(Validator), "ValidateDate")]
  18:          public DateTime DateToReplace { get; set; }
  19:   
  20:          [CustomValidation(typeof(Validator), "ValidateDate")]
  21:          public DateTime ReplacementDate { get; set; }
  22:      }
  23:   
  24:      public static class Validator {
  25:          public static ValidationResult ValidateDate(string inputDate) {
  26:              DateTime thisDate;
  27:              if ((inputDate != null) && inputDate.Trim() != string.Empty) {
  28:                  if (DateTime.TryParse(inputDate, out thisDate)) {
  29:                      return ValidationResult.Success;
  30:                  } else {
  31:                      return new ValidationResult("Not a valid date.");
  32:                  }
  33:              } else {
  34:                  return ValidationResult.Success;
  35:              }
  36:          }
  37:      }
  38:  }

Popular posts from this blog

Handling uploads with MVC4, JQuery, Plupload and CKEditor

SSDT With Visual Studio 2012 and Using Custom Assemblies

Deleting All PlayerPrefs for your Unity3D Project on Windows