T4MVC 2.4.04 update: MVC 2 support, new settings, cleanup, fixes

To get the latest build of T4MVC:

Go to T4MVC page on CodePlex

Though I haven’t blogged for a while about T4MVC, I’ve been making a few minor updates and only sent notification via Twitter.  Now, I have a few things that are worth discussing in a little more detail.  Note that you can see the complete list of changes from version to version in the readme.txt file that comes with it.  BTW, I used to have all this revision information directly in the .tt file, but it was getting a little long so I moved it to the readme.

The changes described below were added between version 2.4.00 and 2.4.04.

MVC 2 Preview 2 support

The most interesting things to many people is that I just made a fix to allow T4MVC to work on MVC 2 Preview 2 apps.  The reason is was not working is that the MVC team changed a number of their API’s to return MvcHtmlString instead of strings.

One challenge here is that I did not want to maintain two separate versions of T4MVC, just to account for this small difference.  Instead, I ended up adding logic in T4MVC which detects which version of ASP.NET MVC your app is using, and adapts what it generates accordingly.  The result is that the overall T4MVC experience is the same as before: you drop it into any MVC app and it should just work!

Detecting the version of MVC in use through the less-then-perfect VS DTE object model was a bit of a challenge in itself.  In case you’re curious, here is the logic I ended up with:

 var vsProject = (VSLangProj.VSProject)Project.Object;

foreach (VSLangProj.Reference r in vsProject.References) {
    if (r.Name.Equals("System.Web.Mvc", StringComparison.OrdinalIgnoreCase)) {
        return r.MajorVersion;
    }
}

The fact that I had to cast Project.Object to a VSProject was far from intuitive.  But anyway, I digress, this post is not about the VS DTE model :)

So, back to MVC 2, please note that this new T4MVC does not add support for any of the new features.  It simply allows it to run without blowing up, but still only supports features that existed in MVC 1.  In particular, the one big obvious feature that would be worth supporting is Areas (Phil’s blog).  This is something I’d definitely like to add support for when I get some cycles (unless someone else does it first! :)).

Generate cleaner code that doesn’t make various tools complain

This came as various separate changes based of issues that several people mentioned.  Copying items from the revision list:

  • Put all the generated code in a T4MVC #region. This is useful to tell tools like ReSharper to ignore it.
  • Added <auto-generated /> comment to disable StyleCop in generated file
  • Added pragma to prevent compiler from complaining about missing Xml comments
  • Renamed generated classes to be CLS compliant

Generally, T4MVC is trying to be a good citizen with the various tools people are running.

New knobs in T4MVC.settings.t4

You can look at T4MVC.settings.t4 to see the list of things that are customizable.  In short, and again copying from the history list, the new knobs are:

  • Added a setting to turn off the behavior that always keeps the template dirty
  • Added a setting to set the namespace that Links get generated in
  • Added ProcessVirtualPath method to T4MVC.settings.t4 so user can write custom logic to modify client URL's

Cleanup

I made various cleanup to the template’s logic.  In particular, I greatly simplified the logic that locates the VS project that contains the T4 template, by using the FindProjectItem() method:

 // Find the .tt file's ProjectItem
ProjectItem projectItem = dte.Solution.FindProjectItem(Host.TemplateFile);

Before, I was doing all kind of crazy things, mostly because I didn’t know about this method.  I’m learning the VS DTE model as I go along, as I had never used it before :)