Still musing around T4 Templates – Part 3

 

As I have promised, here goes the third part of the series dealing with T4 Templates in Entity Framework. In the previous parts (Part1 and Part 2) we have focused rather on T4 Templates’ basics elaboration without Entity Framework involvement. This time let’s talk about a more useful scenario. Due to the reason in the past I wrote a few articles concerning ASP.NET MVC, the example in this article uses MVC as well whereas the application’s model is based on Entity Framework.

Validation is extremely important while receiving user input. The basic security principle tells us, that the server should never trust the client. So validation is imperative on Server. This however needs an additional roundtrip to the server. Therefore before server validations take place, client validation could prevent invalid data input and therefore it could largely improve users’ experience whereas server-side validation remains the server’s particular security stronghold defense line. At the end of the day ASP.NET MVC Annotation Attributes work both for Server- and Client-side (JScript) validations.

Here is a simple ASP.NET MVC Example (all examples download links are at the end of this article) which yet doesn’t use Entity Framework. The Application uses POCO (Plain Old CLR Objects) classes and therefore it is extremely simple to decorate such classes with any extension attributes inclusively of those for validation purposes (Code 1).

public class User
{
  [Required(ErrorMessage = "First Name is a required field!")]
  [StringLength(20, ErrorMessage="First Name’s length must be between 2 and 20", MinimumLength=2)]
  [RegularExpression(@"^[a-zA-Z”-‘\s]{1,22}$", ErrorMessage = "Some characters are not allowed.")]
  public string FirstName { get; set; }
        
  [Required(ErrorMessage = "Last Name is a required field!")]
  [StringLength(20, ErrorMessage = "First Name’s length must be between 2 and 20", MinimumLength=2)]
  [RegularExpression(@"^[a-zA-Z”-‘\s]{1,22}$", ErrorMessage = "Some characters are not allowed.")]
 
  public string LastName { get; set; }
        
  [Required(ErrorMessage = "Status is a required field!")]
  public MembershipStatus Status { get; set; }
        
  public int Id { get; set; }
  public Uri UserId { get; set; } 
  public DateTime LastModified { get; set; }
}
Code 1

Some properties of the User class are annotated even with multiple validation Attributes. This could popup more meaningful and user-friendly messages as Picture 1 shows.

 

Picture 1

So I assume there is no discussion about the fact, that Data Annotation Validators are useful. The only problem starts while trying to create a model based on Entity Framework. If you start from an existing Database, the conceptual model’s classes are generated automatically and thus there is no way to decorate the by default created classes with such validation Attributes. Whatever you add to those classes, the next time they are replaced with their original versions.

The very first step toward a solution is to download and install the ADO.NET C# (or VB.NET) POCO Entity Generator. This could replace the hidden internal code-generation algorithm with a T4 Template based. Furthermore getting POCO is still half of the truth. While using the installed POCO Entity Generator we could get a perfectly valid conceptual model, which are however rewritten and regenerated each time like the previously mentioned Entity Framework default code generation strategy did. So where exactly are the benefits?

The benefits are, that we could simply either 1) decouple the conceptual model from the T4 Template or 2) tweak that T4 Template in order to get Attributed classes. While completely decoupling the POCOs from the automatic code generation makes any persistent code change possible, future model updates will be however decoupled as well and manual code adjustment of the conceptual model is requested after the model was updated.

It looks therefore more convenient to edit the T4 Template which will maintain automatic code-generation features intact and furthermore all future model updates will be reflected in the conceptual model output as well. So let me show you an example extending/editing the T4 Template which will generate Attributed properties.

Let’s start with an ASP.NET MVC Application which is based on the mode depicted in Picture 2. There is a User entity and en Employee entity which is inherited from User. Employees an Users have membership states like premium, silver, gold an soon. Furthermore Users could have Orders as well.

Picture 2

Right mouse button on that model, click on “Add Code Generation Item…” and select ADO.NET POCO Entity Generator (Picture 3) and name it let say TweakedModel.tt (Picture 4). After the code generator ran, the entities of the model are represented with appropriate POCO classes. Our task is now to take the TweakedModel.tt and tweak/alter it in the way it will emit an Attributed User class similar to the one in Code 1.

Picture 3

Picture 4

So please open TweakedModel.tt Template in the editor while assuming you have already installed the tangible T4 Editor mentioned in the previous parts. As you could note, most of the lines are within T4 Code Sections, which means they will run at code-generation time. Taking it from the top please locate the line calling the “WriteHeader” method. This is the location where all the “using” Namespaces will be generated. Due to the reason, our attempt is focused on Validations Attributes living in the System.ComponentModel.DataAnnotations Namespace, let’s add an additional string Parameter to this method like Picture 5 depicts. This will add one more using System.ComponentModel.DataAnnotations Statement to each .cs file output. So this part is common for all entities generated. The editor’s intellisense will greatly assist you in this effort as inserting a colon after the first parameter, the bold hint will display “string[] extraUsing”, meaning here we could put a collection/list of additional strings with the appropriate namespaces.

Picture 5

As we learned in the previous parts, the WriteHeader represents a helper or T4 Class Section which is located toward the end of this template. In my case it is somewhere at line 716 (Picture 6) and if you scroll down to that location it turns out indeed to be a T4 Class Section (distinguished with the + sign).

Picture 6

Next please turn your attention on the comments somewhere at line 34 declaring // Emit Enity Types (Picture 7). This is the location which starts looping over all entities within the model. Note furthermore, that the current entity’s name is in the local variable “entity.Name”. Using this variable all the C# files are generated ( see at line 37 – Picture 7). Do not overlook the statement region.Begin("Primitive Properties"); where the inner looping over the entity’s properties starts (line 44 – Picture 7).

Picture 7

Next let’s locate the place within this tt-Template which will write the properties’ starting declarations. This happens at this T4 Code Template (see line 62 in Picture 8 as well):

<#=PropertyVirtualModifier(Accessibility.ForProperty(edmProperty))#>

Code 2

Hence fore if we would like to insert Validation Attributes decorating the defined entities’ selected properties, here our attempt should proceed determining the affected entity and determining the affected property as well. We already identified the local variable keeping the entity’s name. Look now for the local variable keeping the entities’ properties, which is kept in edmProperty.Name. According Code 1, we have to decorate the User entity’s FirstName and LastName properties. Therefore we could insert these filtering statements directly before the statement in Code 2. The Result is depicted in Picture 8. The lines 55 through 61 (marked red) are inserted into the Template and represent T4 Code Sections. Note also lines 57-60 (marked blue) which are the three Validation Attributes common to both FirstName and LastName properties.

Picture 8

At line 55 the appropriate entity is filtered and on line 56 the appropriate properties are filtered. Note on line 61 the closing statements of the executed T4 Code Section containing the two closing curly brackets. In similar way you could filter more entities and properties. Save the changes and the code will immediately generated (Code 3).

public partial class User
{
        #region Primitive Properties
        public virtual int Id
        {
            get;
            set;
        }
    
        [Required(ErrorMessage = "FirstName is a required field!")]
        [StringLength(20, ErrorMessage="FirstName’s length must be between 2 and 20", MinimumLength=2)]
        [RegularExpression(@"^[a-zA-Z”-‘\s]{1,22}$", ErrorMessage = "Some characters are not allowed.")]
        public virtual string FirstName
        {
            get;
            set;
        }
    
        [Required(ErrorMessage = "LastName is a required field!")]
        [StringLength(20, ErrorMessage="LastName’s length must be between 2 and 20", MinimumLength=2)]
        [RegularExpression(@"^[a-zA-Z”-‘\s]{1,22}$", ErrorMessage = "Some characters are not allowed.")]
        public virtual string LastName
        {
            get;
            set;
        }
        public virtual int MembershipStatusId
        {
            get { return _membershipStatusId; }
            set
            {
                if (_membershipStatusId != value)
                {
                    if (MembershipState != null && MembershipState.Id != value)
                    {
                        MembershipState = null;
                    }
                    _membershipStatusId = value;
                }
            }
        }
        private int _membershipStatusId;
        public virtual Nullable<System.DateTime> LastModified
        {
            get;
            set;
        }
        public virtual Nullable<System.DateTime> BirthDate
        {
            get;
            set;
        }
… // more code is left out // …
}

Code 3

The complete VS2010 example you could download here:

 

http://cid-8d365142bc4869ab.skydrive.live.com/embedicon.aspx/.Documents/RestMvcAppT4Edited.zip

 

How to use the Example (step-by-step guidance)

  1. Download the code
  2. Extract the backup of the UserEmployeeDB database in the folder DB and attach to your local SQL Server instance
  3. Alter the connection strings as appropriate (Example uses “.\sqlexpress”)
  4. The Entity Model is located in the Class Library Project (ClassLibEFClassic)
  5. Start the ASP.NET MVC Application
  6. Click on Employees
  7. After employees are displayed click on any Edit
  8. Delete FirstName content and click on LastName
  9. Add a star at the end of LastName and click into the next TextBox Field (Client side validation takes place)
  10. You have to see something like Picture 9 depicts

 

Picture 9

Advertisements
This entry was posted in Uncategorized - Common. Bookmark the permalink.

2 Responses to Still musing around T4 Templates – Part 3

  1. Jay Pondy says:

    You can attach meta data to EF classes that won’t be overwritten when the template is re-run. Check out: [MetadataType(typeof(UserMetaData))]

    The problem with DataAnnotations is they don’t work with all consumers.

    Good post though!

  2. Stefan R. says:

    Hi Jay, thanks for your hints. This blog seems to be useful in this regard: Using DataAnnotations metadata with Linq2Sql entities at http://blogs.renacimiento.com/eblanco/archive/2010/01/14/using-dataannotations-metadata-with-linq2sql-entities.aspx

    Kind regards, Stefan

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s