Monday 1 December 2014

Using DataAnnotations with Entity Framework 4 Entities for a More Dynamic MVC Model


entity_framework
I’ve been working with MVC3 and Razor lately.  It’s been absolutely great.  I’ve not used MVC to build a production app until now, and it’s been killer fast building things out quickly.  Previously, I’ve just used regular old objects like are in the starter projects to play around with my applications as the “M” in my MVC.  With these, you can use the System.ComponentModel.DataAnnotations to decorate your classes with validation, labels, datatypes, field types and more that are used in MVC views to dynamically create your UI.  Now, though, I’m building a pretty big application that I’ll be putting out for a longer term, and will use SQL Server for the back-end with Entity Framework 4.0 entities as my model. The problem with this is that entity models are dynamically generated, and don’t contain annotations of their own.
Here’s an example of the DataAnnotations in a typical model:
public class LogOnModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}
Since entities are regenerated often (meaning annotating the entities directly will result in your changes being wiped out pretty quickly), but are the preferred way of working with databases, what’s the best way to go about annotating the entities so they work seamlessly in the MVC framework?
I recently asked this question on StackOverflow, and Austin Lamb of the Microsoft Silverlight team was kind enough to let me know how this is done in the Silverlight world, which ended up working seamlessly with MVC.  See, when you generate entities, they are created as partial classes.  This means that you can extend them by creating another partial class for each of the entity classes.  This gets us around the problem of the regenerating entities wiping out any DataAnnotations, since partial classes we create manually aren’t regenerated by the T4 template that creates the entities.  Now, can we just annotate the fields straight up in the partial class we manually create?  Well, not directly.  The trick here, as Austin points out, is to use a MetadataType class that holds the DataAnnotations.  This MetadataType class, that corresponds to a single entity class, is applied to the partial class you manually created, which then links everything up.  I know it’s hard to visualize by my typing this out in a paragraph, so I’ll give you code he gave me.  Below is the partial class and MetadataType class that you need to create under the assumption you want to add DataAnnotations to the Person class’ FirstName field:
[MetadataType(typeof(PersonMetadata))]
public partial class Person {
  // Note this class has nothing in it.  It's just here to add the class-level attribute.
}

public class PersonMetadata {
  // Name the field the same as EF named the property - "FirstName" for example.
  // Also, the type needs to match.  Basically just redeclare it.
  // Note that this is a field.  I think it can be a property too, but fields definitely should work.

   [Required]
   [Display(Name = "First Name")]
   public string FirstName;
}
Once you have this set up, the DataAnnotations will show through even if you use an Entity Framework model as the model for your MVC application.  Pretty slick, eh?  If you want to read the whole article then go here.  Don’t forget to upvote Adam’s post as it’s helped me a ton, and if this post has helped you, it’s only because of him.  Enjoy!

No comments:

Post a Comment

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...