T4 templates have been a pretty popular topic lately. If you have no idea what they are, don’t feel bad, I didn’t either only a couple weeks ago! In a nutshell, it’s a simple template processor that’s built into VS and allows for all kind of cool code generation scenario. For a bunch of information about them, check out the following two blogs:
The basic idea is that you can drop a hello.tt file into a project, and it will generate a hello.cs (or hello.anything) file via its template. The template syntax of .tt files is very similar to ASP.NET’s <% … %> blocks, except that they use <# … #> instead.
For a cool example of what you can do with T4, check out this post from Danny Simmons, which shares out a .tt which generates all the Entity Framework classes automatically from an edmx file. What’s really nice is that you can easily customize the template to generate exactly the code that you want, instead of being locked into what the designer normally generates.
One weakness we currently have with Dynamic Data is that we don’t have a great way to get started with a custom page. Suppose you start out with a web app in full scaffold mode, and find the need to customize the Details page for Products. The ‘standard’ procedure to do this is:
While this generally works, it has one big weakness: you need to start your customization from a ‘generic’ file which knows nothing about your specific table. e.g. you start out with a <asp:DetailsView> control that uses AutoGenerateRows to generate all the fields. So if you want to do any kind of real UI customization, you’ll likely have to do a bunch of repetitive steps, e.g.
In a few hours, I was able to put together a quick T4 template that replaces most of those repetitive steps. The steps using this template become simply:
While this is cool, there is one thing that is a bit strange about it: you’re left with a .tt file you don’t want in your project:
And since details.tt file generates details.aspx file, you can’t really change the aspx until you delete the .tt file. Unfortunately, VS makes this more difficult than you would think because the two files are linked to each other. The best steps I found to delete it are:
I know, that’s painful!! Ideally, what we really want to do is use the .tt do to a one time transform, but never actually have it be part of the project. At this point, I’m not yet sure how to do this, but I’m hopeful that there is a way. Suggestions are welcome! :)
In order to perform its task, the template needs to figure out what all the entity type’s fields are for the custom page. Doing this is a bit non-trivial, and what I do here is not as clean as it could be, as this is just a quick prototype. Here is a brief description of what it does:
If you look at the t4 files, you’ll see all this logic at the end. That part is certainly quick and dirty, and could use some rewriting. But what comes before it is a pretty clean template that’s easy to tweak to your needs. e.g.
<table class="detailstable"> <# foreach (var prop in data.Properties) { #> <tr> <th> <#= prop.Name #> </th> <td> <asp:DynamicControl DataField="<#= prop.Name #>" runat="server" /> </td> </tr> <# } #> </table>
As you can see, it looks very much like inline code in an aspx file, except that instead of executing at runtime on the web server, it executes in Visual Studio to generate a file that becomes part of the project.
So I’m only talking about Details.tt/Details.aspx. What about the other Dynamic Data views: List, Edit, Insert? Well, those would all work in pretty much the same way, and I simply haven’t had a chance to get to them. For now, I just wanted to get this first T4 file out as a proof of concept that shows the kind of things that can be done. Contributions are welcome! :)
Clearly, a lot of what I describe here is pretty raw, and it’s only a very early prototype. But I think it should be enough to convey the potential power of design time file generation via T4 templates. Later, I’d like to get better integration with VS. e.g instead of dropping the .tt file in the project and later having to delete it, it’d be nice to get a custom action by right clicking on the CustomPages folder, that would let you generate the aspx file. It would still use T4 under the cover, but you wouldn’t have to see it unless you want to.
Hopefully, I’ll be writing more about this in the future if there is interest.