This blog post is part of a series about the MvcScaffolding NuGet package:
- Introduction: Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package
- Standard usage: Typical use cases and options
- One-to-Many Relationships
- Scaffolding Actions and Unit Tests
- This post: Overriding the T4 templates
- Creating custom scaffolders
- Scaffolding custom collections of files
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 <yourSolutionDir>\packages\<scaffolderPackage>\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:
| 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<YourModel> properties) |
| 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 |
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:
This adds a new CustomScaffolders folder into your project which contains the template override:
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?
18 Responses to MvcScaffolding: Overriding the T4 Templates
Pingback: The Morning Brew - Chris Alcock » The Morning Brew #829
Thanks for getting these out! I will definitely be giving it a try. somehow, you snuck these out while I had stopped checking every day. i won’t let that mistake happen twice.
Hi Steve,
Regarding scaffolding our views, where can we find documentation on what properties are available to us?
i.e.
What else is there for us?
is there a ?
Bah, Model.ViewDataTypeName exists, what else is there? Where is the documentation?
Not sure what’s up with the commenting here.
Pingback: MvcScaffolding Enhancement - DisplayAttribute Support - Naughton Futilities
Hi Steve,
I think that table is not correct when u say about ActionUnitTest.
Only worked when uses Scaffold CustomTemplate UnitTest TestMethod/TestClass.
Using ActionUnitTest it didnt work.
Thanks for this post! Was Helpfull!
Hugs!
João Attila
Pingback: MvcScaffolding: Standard Usage - Steve Sanderson’s blog - As seen on YouTube™
Steve, great work, I use the scaffolds all the time.
Question, Is there a way to just generate a single view (ie: index) of a controller that uses a repository and dbcontext?
I haven’t found a syntax to generate a single view with a model.
Steve
How can I override T4 template for view ???
Has anyone implemented custom template to create ViewModel with AutoMapper mappings and also to popluate the ViewModel properties etc?
I’ve been thrilled to find this excellent post about custom T4′s for MvcScaffolding and have followed the instructions carefully. I have custom templates for generating AspxViews (Create, CreateOrEdit, Delete, Edit, Index), and Repository which all work great.
However I cannot get the customised ControllerWithRepository template to work. Running -verbose when scaffolding indicates that it found the template but it seems like it ignores it and uses the default! Could this be a minor flaw for this one template? Any ideas?
Here’s the output:
Found template ‘ControllerWithRepository’ at ‘C:\dev\…off_my_projects_root…\CodeTemplates\Scaffolders\MvcScaffolding.Controller\ControllerWithRepository.cs.t4′
Added controller Controllers\ProductsController.cs
Thanks for this. I can’t explain how happy I am with this.
I’m having the same issue as Eamon. The ControllerWithRepository seems to be ignored.
Any ideas?
Thanks,
Chris
jkbjkghjk
Can the t4 templates be opened/edited from Visaul Studio 2010. I keep getting an error “The operation could not be completed”
help!
The view-file created by Scaffold doesn’t have the utf-8 BOM signature?
Steps:
1. I created a custom template Index.cs.t4.
2. Filled some unicode character. e.g: “新建”.
3. Create view: Scaffold Views Users Index -Force -ModelType User.
Then, the characters is unreadable which was in template.But, Some characters are displaying well which are querying from the database.
I must change each file created by Scaffold. Open it, Save as UTF-8.
If I unchecked the option “Auto-detect UTF-8 encoding without signature” at “Visual Studio Tools-> Text Editor->General”. VS couldn’t open the file created by Scaffold
There are certainly a lot of details like this take into consideration. That is an excellent point to create up. I provide thoughts over as general inspiration GuildWars2 Necromancer nevertheless clearly you will find questions such as the one you mention where it is important will be working in honest good faith. I don? t understand if best practices have come about around such things as that, but More than likely that your job is clearly referred to as a reasonable game. Both boys and girls feel the actual impact of only a moment’s satisfaction, for the rest of their own lives.
Hi All, does anyone know how to customize the filename of a view? instead of “Create.cshtml” I’d like something like “WhateverIWant.cshtml”.
Thanks!
I’m with Graeme..
Has anyone implemented custom template to create ViewModel with AutoMapper mappings and also to popluate the ViewModel properties etc?