Twitter About Home

MvcScaffolding: Overriding the T4 Templates

This blog post is part of a series about the MvcScaffolding NuGet package:

Published Apr 6, 2011
  1. [Introduction: Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package][1]
  2. [Standard usage: Typical use cases and options][2]
  3. [One-to-Many Relationships][3]
  4. [Scaffolding Actions and Unit Tests][4]
  5. This post: Overriding the T4 templates
  6. [Creating custom scaffolders][5]
  7. [Scaffolding custom collections of files][6]

Previous posts in this series have shown how you can use MvcScaffolding’s built-in features to handle a range of CRUD scenarios, as well as quickly generate actions, view models, views, and unit test stubs using the included templates. But what if you want to do something different?

In this post and over the next two, I’ll show you how you can:

  • Change the code that the built-in scaffolders generate by overriding the T4 templates they use
  • Scaffold completely different types of things by creating your own new, custom scaffolders with arbitrary PowerShell logic
  • **Combine multiple built-in and custom scaffolders **to generate whole structures of code files that implement useful functionality

Overriding the T4 Templates

Note: This post assumes you’ve already installed the MvcScaffolding package. If not, see the earlier posts in this series for an introduction.

The simplest form of customisation is overriding the T4 templates. For example, if you want to change what data access code is generated, you can supply your own templates that produce code based on NHibernate, or Mongo, or whatever, instead of Entity Framework which is the default.

To get started, you first need to know which existing T4 template you want to override. You can find this out either by:

  • Looking in \packages\\tools to see the structure of scaffolders and templates
  • Or, by running the scaffolder whose output you want to change and passing the –Verbose flag so it tells you which templates it’s using
  • Or, just by looking at the following table to see the built-in ones:
</table> Next, run the special “CustomTemplate” scaffolder to create a template override. The syntax is: “Scaffold CustomTemplate scaffoldername templatename”. For example, if you want to override the repository template, the scaffolder name is “repository”, and so is the template name, so you run: {: .media .image } [SNAGHTML2d9deaf9_thumb[1]][7] This adds a new CustomScaffolders folder into your project which contains the template override: {: .media .image } [image_thumb[2]][8] Now all you have to do is edit that file, Repository.cs.t4, using T4 syntax to define the code you want to generate. You can use T4’s <#= … #> blocks to evaluate parameter values supplied by the scaffolder to insert things like the repository name, the model type, the model primary key property name, and so on. The file’s initial contents acts as an example you can modify. For example, if you wanted repositories implemented as static in-memory collections, instead of being backed by a SQL database, you could set up the first few lines of the class template as follows:
/// <summary>
/// A dummy in-memory repository for <#= modelName #> entities. Its data will be reset each time you restart the application.
/// </summary>
public class <#= modelName #>Repository : I<#= modelName #>Repository
    private readonly static Dictionary<<#= primaryKeyProperty.Type.AsString #>, <#= modelName #>> InMemoryCollection = new Dictionary<<#= primaryKeyProperty.Type.AsString #>, <#= modelName #>>();
    public IQueryable<<#= modelName #>> All
        get { return InMemoryCollection.Values.AsQueryable(); }
… and of course edit the rest of the template to read/write data in InMemoryCollection too. ### Using Your Custom Template You don’t have to do anything special to use the custom template. Just the fact that it’s there in your project means it will override the default one. So, next time you run “**Scaffold Repository SomeEntity**” (or scaffold a controller using the **–Repository** switch), it will use your template. Of course, this means it’s easy to share: just commit your **/CodeTemplate** folder into source control, and then your template becomes a standard for everyone working on your project. ### A runnable example For reference, see the downloadable example project that includes a complete “in-memory collection repository” template. Try it out by generating a controller with repository for the provided StockItem model:
Scaffold Controller StockItem -Repository
Then, you can compile and run the application, navigate to the URL /StockItems, and add/edit/delete items in the in-memory collection. If you’d like to do something a little more interesting, how about adapting the repository template further, to generate code that reads/writes data using NHibernate or Mongo or some other data store? [1]: [2]: [3]: [4]: [5]: [6]: [7]: [8]:
Scaffolder name Template name What it’s used for
DbContext DbContext Empty data context class
DbContext DbContextEntityMember Entity set property used for each model type added to the data context class (e.g., DbSet properties) </td> </tr>
Repository Repository Repository interface and default concrete implementation
Action Action Action method (Note: only used when generating standalone actions. Not used by controller scaffolder)
Action ActionPost As above, for actions that handle POST requests
Action ViewModel View model used by scaffolded actions
ActionUnitTest TestClass Empty unit test class
ActionUnitTest TestMethod Unit test method stub
View Create, _CreateOrEdit, Delete, Details, Edit, Empty, Index MVC view for the corresponding view type
(Note: CreateOrEdit has no leading underscore if you’re generating ASPX views, because that’s a Razor convention)
Controller ControllerWithContext Complete MVC controller with inline data access code
Controller ControllerWithRepository Complete MVC controller that uses repositories for data access

Scaffolding Actions and Unit Tests with MvcScaffolding

This blog post is part of a series about the MvcScaffolding NuGet package:

Published Mar 28, 2011