The Weekly Source Code 43 - ASP.NET MVC and T4 and NerdDinner
UPDATE: David's put the T4 template with some nice updates on CodePlex - It's the last download here.
I really advocate folks reading as much source as they can because you become a better writer by reading as much as writing. That's the whole point of the Weekly Source Code - reading code to be a better developer.
Reading code in Open Source projects is a good way to learn, especially if the project has been around a while and been successful, or if you already respect the team of people working on it. Less reliably, you can find snippets of code by searching and sharing code.
David Ebbo is scary clever. You know someone is smart when they come up with something you don't think you yourself could come up with on your own, but you still kick yourself for not thinking of it in the first place.
David's been experimenting with ways to make ASP.NET MVC better, specifically in the area of strongly-typed helpers. He's trying to get rid of strings, magic or otherwise.
He started with a BuildProvider (not a lot of folks know about BuildProviders...it's a powerful secret.) David didn't like these kinds of links in ASP.NET MVC:
<%= Html.ActionLink("Home", "Index", "Home")%>
So his BuildProvider would get added to the web.config:
<buildProviders>
<add extension=".actions" type="MvcActionLinkHelper.MvcActionLinkBuildProvider" />
</buildProviders>
And it would give you better methods like this, by poking around in your project and dynamically generating helper methods for you:
<%= Html.ActionLinkToHomeIndex("Home")%>
Then, just days later, David got the T4 religion (I've argued we are doing a poor job of promoting this, so I'm telling everyone I know) and you should too. David explored the pros and cons of CodeDom vs. T4 for CodeGen then recreated his ASP.NET MVC Helpers using T4.
He's enabling not only better ActionLinks, but also Action Url Helpers, Constants for View Names, and a very clever thing, helpers for View Models, courtesy of David Fowler.
I thought this was particular cool, because it's a really visceral example of what you can do with Code Generation when you start exploring what you know at compile time with what you wish you knew at Design Time. It also reminds us that it's more than just Compile/Test/Run - your projects become more "meta" when you've got Inspect/CodeGen/Compile/Test/Run.
For example, if you have a ViewModel that say, has a string, rather than:
<label for="Name">Name:</label>
<%= Html.TextBox("Name", Model.Name) %>
<%= Html.ValidationMessage("Name", "*") %>
Why not this instead:
<%= ViewModel.Name.Label() %>
<%= ViewModel.Name.TextBox() %>
<%= ViewModel.Name.Validation() %>
This ViewModel stuff is in the earlier CodeDom templates, but not (yet?) the T4 templates. I hope we see it again, don't you? What do you think, Dear Reader, of this approach vs. the "Opinionated Input Builder" approach?
Just recently David put out his "new and improved" MVC T4 template, which is the one you should check out. I'm gently pushing him to put it on CodePlex somewhere and bake this goodness in. (Go tell him and Phil!)
He was doing some stuff at runtime, but has since moved to a pure design-time approach.
David Ebbo's ASP.NET MVC T4 Template applied to Nerd Dinner
David took the NerdDinner app as his base, and installed his T4 template. Just drop it in, and magic gets generated. How does it work, though?
Before he was using reflection but since this is a Design Time Code Generation process he had to delve into the *gasp* COM-based VS File Code Model API. However, this does really show off the power and flexibility of T4 itself. Kudos to David for looking COM in the face and not blinking!
Go download his template (direct ZIP here) and open it up.
T4 files can be scary to view in a text editor as they are constantly switching between <% code blocks %> and the code that's being generated. I use Notepad2 to view them, using the (interestingly enough) XML Document option that gives me rudimentary syntax highlighting.
If you're serious about T4, go get the Visual T4 Community Edition from Clarius for half-way syntax highlighting, or pay for the Professional Edition. They'll register themselves with Visual Studio and give you a better experience than just all-black text.
The first line in David's T4 template that made me chuckle was the the first line that's executed:
<# PrepareDataToRender(this); #>
As they say, it's funny because it's true. This is typical of code generation templates of all kinds. It's the "DoIt()" method that takes the left-hand's code (the COM crap) and prepares it for the right-hand (the template itself).
In order for David to make his template tidy and enable this nice clean level of abstraction:
<# foreach (var controller in Controllers.Where(c=>c.IsPartialClass)) { #>
namespace <#= controller.Namespace #> {
public partial class <#= controller.ClassName #> {
protected RedirectToRouteResult RedirectToAction(ControllerActionCallInfo callInfo) {
return RedirectToAction(callInfo.Action, callInfo.Controller, callInfo.RouteValues);
}
...snip...
...he has to prepare an object model, and that's what PrepareDataToRender does. It's funny also because it's buried at the end, as it should be. It's really a pleasure to read and does a LOT considering it's only a 415 line template.
He has a number of cute gems like this one-line helper function that combines a little COM a little LINQ and a little magic to a list of methods to his template using the Visual Studio API. I laughed at the "functionFunction" enum. "Do you like her? or do you like her like her?"
// Return all the CodeFunction2 in the CodeElements collection
public static IEnumerable<CodeFunction2> GetMethods(CodeClass2 codeClass) {
// Only look at regular method (e.g. ignore things like contructors)
return codeClass.Members.OfType<CodeFunction2>()
.Where(f => f.FunctionKind == vsCMFunction.vsCMFunctionFunction);
}
David is clearly deep into this exploration right now, and is asking your opinion about the design. I would encourage you to flood him with feedback, or leave it hear and I'll tell him. ;)
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.



About Newsletter