<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angle Bracket Percent : ASP.NET</title><link>http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx</link><description>Tags: ASP.NET</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>T4MVC 2.6: MVC 2 Areas support</title><link>http://blogs.msdn.com/davidebb/archive/2009/11/29/t4mvc-2-6-mvc-2-areas-support.aspx</link><pubDate>Mon, 30 Nov 2009 06:51:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9930050</guid><dc:creator>davidebb</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9930050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9930050</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9930050</wfw:comment><description>&lt;p&gt;To get the latest build of T4MVC:&lt;/p&gt;  &lt;h1 align="center"&gt;&lt;a href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to T4MVC page on CodePlex&lt;/a&gt;&lt;/h1&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;One of MVC 2's major new features is the support for breaking up a large application into &amp;quot;Areas&amp;quot;. This works by following a structure that looks like:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Root folder      &lt;ul&gt;       &lt;li&gt;Models &lt;/li&gt;        &lt;li&gt;Views &lt;/li&gt;        &lt;li&gt;Controllers &lt;/li&gt;        &lt;li&gt;Areas          &lt;ul&gt;           &lt;li&gt;NerdDinner              &lt;ul&gt;               &lt;li&gt;Models &lt;/li&gt;                &lt;li&gt;Views &lt;/li&gt;                &lt;li&gt;Controllers &lt;/li&gt;             &lt;/ul&gt;           &lt;/li&gt;            &lt;li&gt;Blog              &lt;ul&gt;               &lt;li&gt;Models &lt;/li&gt;                &lt;li&gt;Views &lt;/li&gt;                &lt;li&gt;Controllers &lt;/li&gt;             &lt;/ul&gt;           &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So basically you still have your top level Models/Views/Controllers folders, and in addition to that you can have an arbitrary number of “Areas”, each having their own set of Models/Views/Controllers folders.&lt;/p&gt;  &lt;p&gt;Starting with MVC 2.6, T4MVC lets you use areas in much the same way it lets you access top level items.&amp;#160; e.g. you can now write:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;&amp;lt;%= Html.ActionLink(&amp;quot;Delete Dinner&amp;quot;, MVC.NerdDinner.Dinners.Delete(Model.DinnerID))%&amp;gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Note how we referred to the controller as MVC.&lt;b&gt;NerdDinner&lt;/b&gt;.Dinners.&lt;/p&gt;

&lt;p&gt;Optionally, if you set IncludeAreasToken to true in the settings file, this becomes:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;&amp;lt;%= Html.ActionLink(&amp;quot;Delete Dinner&amp;quot;, MVC.Areas.NerdDinner.Dinners.Delete(Model.DinnerID))%&amp;gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Lots of headaches to find a good naming pattern for Areas in T4MVC&lt;/h2&gt;

&lt;p&gt;Surprisingly, one of the things that caused the most headaches in getting this working was finding a well working naming pattern.&lt;/p&gt;

&lt;p&gt;Here are the patterns that were on the table:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MVC.NerdDinner.Dinners &lt;/li&gt;

  &lt;li&gt;MVC.NerdDinnerArea.Dinners &lt;/li&gt;

  &lt;li&gt;MVC.Areas.NerdDinner.Dinners &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;#1 is the simplest and most concise, but breaks if you have a top level controller that has the same name as the area.&lt;/p&gt;

&lt;p&gt;#2 appends ‘Area’ to the area name to solve the conflict we caused by #1.&amp;#160; But while it solves the conflict, you end up with a slightly quirky naming scheme.&lt;/p&gt;

&lt;p&gt;#3 uses an extra Areas token before the area name to avoid the conflict.&amp;#160; The drawback here is that you end up with one more token, meaning one more thing to type through in intellisense.&lt;/p&gt;

&lt;p&gt;I then &lt;a href="http://twitter.com/davidebbo/status/6119050408"&gt;polled twitter&lt;/a&gt; to see whether people preferred #2 or #3, and most went with the cleaner and more wordy #3.&lt;/p&gt;

&lt;p&gt;Then &lt;a href="http://twitter.com/nikhilk"&gt;Nikhil&lt;/a&gt; suggested using a hybrid of #1 and #2, where we only append ‘Area’ to the area name if we detect a conflict with a top level controller name.&amp;#160; Let’s call this #4!&lt;/p&gt;

&lt;p&gt;So I ended up supporting both #3 and #4, based on the IncludeAreasToken switch in the settings file.&lt;/p&gt;

&lt;p&gt;But frankly, I’m considering getting rid of #3.&amp;#160; In the twitter poll, people didn’t like #2 mostly because it’s weird to have that extra ‘Area’ suffix.&amp;#160; But with the hybrid #4 solution, this funky name only occurs exceptionally, making it much less of an issue.&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;

&lt;p&gt;To end this post, I’d like to thank Nathan Roe for helping out putting together this change!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9930050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>T4MVC now has a real home and a dedicated forum!</title><link>http://blogs.msdn.com/davidebb/archive/2009/11/25/t4mvc-now-has-a-real-home-and-a-dedicated-forum.aspx</link><pubDate>Wed, 25 Nov 2009 08:09:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9928433</guid><dc:creator>davidebb</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9928433.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9928433</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9928433</wfw:comment><description>&lt;p&gt;Up until now, most things related to T4MVC were happening through my &lt;a href="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx"&gt;various blog posts&lt;/a&gt; about it.&amp;#160; And while that was sort of working ok for a while, it was also less than ideal for a couple reasons.&lt;/p&gt;  &lt;p&gt;First, there was no single place to go to in order to get information about it.&amp;#160; You’d basically have to go through the various posts that describe the various features as they were added.&amp;#160; And as the number of posts grew, so did the pain involved in doing that.&lt;/p&gt;  &lt;p&gt;The second issue is that there was no good place to discuss it, ask questions and report issues.&amp;#160; So all of those things were mostly just happening organically as comments in my various posts, which really doesn’t work so well.&amp;#160; Blog Post comments don’t support threading, and things ended up being spread all over the place.&lt;/p&gt;  &lt;p&gt;To simplify this mess, I created two things:&lt;/p&gt;  &lt;h2&gt;New T4MVC Home Page: &lt;a title="http://aspnet.codeplex.com/wikipage?title=T4MVC" href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;http://aspnet.codeplex.com/wikipage?title=T4MVC&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;This page contains everything you may want to know about T4MVC: where to get it, the complete documentation, and links to other relevant places.&amp;#160; And obviously, the idea is to keep this page up to date as new features are added. &lt;/p&gt;  &lt;h2&gt;New discussion forum: &lt;a title="http://forums.asp.net/1215.aspx" href="http://forums.asp.net/1215.aspx"&gt;http://forums.asp.net/1215.aspx&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;This is a standard ASP.NET forum, much like the one used for MVC and other ASP.NET topics.&amp;#160; If you have any questions or comments about T4MVC, this is the place to go!&lt;/p&gt;  &lt;p&gt;Hopefully, this will help make things a little less random :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9928433" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>T4MVC 2.5.01: added support for Html.RenderAction and Html.Action</title><link>http://blogs.msdn.com/davidebb/archive/2009/11/20/t4mvc-2-5-01-added-support-for-html-renderaction-and-html-action.aspx</link><pubDate>Sat, 21 Nov 2009 02:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9926602</guid><dc:creator>davidebb</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9926602.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9926602</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9926602</wfw:comment><description>&lt;P&gt;To get the latest build of T4MVC:&lt;/P&gt;
&lt;H1 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC page on CodePlex&lt;/A&gt;&lt;/H1&gt;
&lt;P&gt;MVC 2 Beta introduces two nice helpers called Html.RenderAction and Html.Action.&amp;nbsp; Phil Haack &lt;A href="http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx" mce_href="http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx"&gt;described them in detail on his blog&lt;/A&gt;, so you may want to read through that before reading this post.&lt;/P&gt;
&lt;P&gt;Basically, they’re two additional methods that follow the standard MVC pattern of passing the controller name and action name as literal strings, and the action parameters as anonymous objects.&amp;nbsp; e.g. Copying from Phil’s example, if you have an Action like this:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;public ActionResult Menu(MenuOptions options) {
    return PartialView(options);
}&lt;/PRE&gt;
&lt;P&gt;You can write this in your View:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;%= Html.Action("Menu", new { options = new MenuOptions { Width=400, Height=500} })%&amp;gt;&lt;/PRE&gt;
&lt;P&gt;Note how the action name is hard coded, and the MenuOptions parameter is passed as an anonymous object.&amp;nbsp; With T4MVC, you can instead write:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;%= Html.Action(MVC.Home.Menu(new MenuOptions { Width=400, Height=500})); %&amp;gt;&lt;/PRE&gt;
&lt;P&gt;Giving you full intellisense and type checking for the controller name, action name and parameters.&lt;/P&gt;
&lt;P&gt;Another advantage is that normally, if you use an ActionName attribute, you’ll need to pass that name instead of the action method name.&amp;nbsp; Again from Phil’s blog:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;[ActionName("CoolMenu")]
public ActionResult Menu(MenuOptions options) {
    return PartialView(options);
}&lt;/PRE&gt;
&lt;P&gt;And you then have to pass “CoolMenu” instead of “Menu” when you make the call, which is pretty easy to get in trouble with.&amp;nbsp; But with T4MVC, the fact that you use a non-default Action Name is abstracted out, so you make the exact same Html.RenderAction(MVC.Home.Menu(...)) call.&lt;/P&gt;
&lt;P&gt;Of course, all of this is nothing new if you’re used to using T4MVC.&amp;nbsp; It’s just the same pattern as we have everywhere else, applied to those couple new methods.&amp;nbsp; Maybe I’m just rehashing the same old benefits of strong typing and avoiding literal strings :)&lt;/P&gt;
&lt;P&gt;On a separate note: I fixed a small bug that happened when you used a custom ActionResult without an explicit ctor.&amp;nbsp; See comments in &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/11/16/t4mvc-2-5-00-update-multiple-output-files-and-minified-javascript-support.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/11/16/t4mvc-2-5-00-update-multiple-output-files-and-minified-javascript-support.aspx"&gt;previous post&lt;/A&gt; for details on the issue.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9926602" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>T4MVC 2.5.00 update: multiple output files and minified javascript support</title><link>http://blogs.msdn.com/davidebb/archive/2009/11/16/t4mvc-2-5-00-update-multiple-output-files-and-minified-javascript-support.aspx</link><pubDate>Tue, 17 Nov 2009 02:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9923340</guid><dc:creator>davidebb</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9923340.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9923340</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9923340</wfw:comment><description>&lt;P&gt;To get the latest build of T4MVC:&lt;/P&gt;
&lt;H1 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC page on CodePlex&lt;/A&gt;&lt;/H1&gt;
&lt;P&gt;T4MVC build 2.5.00 brings a couple of fun new features that I’ll describe in this post.&amp;nbsp; I can’t take too much credit for them as they came from users who suggested them to me, and helped out getting the code going.&lt;/P&gt;
&lt;H2&gt;Support for multiple output files&lt;/H2&gt;
&lt;P&gt;Up until now, T4MVC.tt has always generated a single file, which is the T4MVC.cs that you see get nested under it in VS.&amp;nbsp; And normally, this is the way T4 templates work: they just generate one file.&amp;nbsp; But last week I got an email from &lt;A href="http://blogs.msdn.com/stuartleeks/" mce_href="http://blogs.msdn.com/stuartleeks/"&gt;Stuart Leeks&lt;/A&gt; who pointed me to a new &lt;A href="http://damieng.com/blog/2009/11/06/multiple-outputs-from-t4-made-easy-revisited" mce_href="http://damieng.com/blog/2009/11/06/multiple-outputs-from-t4-made-easy-revisited"&gt;blog post from Damien Guard&lt;/A&gt; that describes a nice way to get around this limitation.&amp;nbsp; All of Damien’s logic is very nicely encapsulated in a class, making it pretty easy to add to an existing T4 template without having to make significant changes.&lt;/P&gt;
&lt;P&gt;I was going to look into getting that in T4MVC, but Stuart went ahead and did it, so I didn’t have much to do myself.&amp;nbsp; Thanks to Stuart and Damien on this one!&lt;/P&gt;
&lt;P&gt;But first I suppose we should discuss why generating multiple files is a good thing.&amp;nbsp; Quite simply, it keeps things more organized, and makes things cleaner when working with source control.&amp;nbsp; Since T4MVC can generate a fair bit of code, it is a good candidate to use this.&amp;nbsp; Specifically, T4MVC can now generate a different output file for each controller, making things more manageable.&amp;nbsp; Note that it still generated the ‘primary’ T4MVC.cs file, which contains all the top level things that don’t belong to any specific controller.&lt;/P&gt;
&lt;P&gt;This behavior is on by default, but can be disabled in T4MVC.settings.t4:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;// If true,the template output will be split into multiple files.
bool SplitIntoMultipleFiles = true;&lt;/PRE&gt;
&lt;P&gt;I debated whether to make it the default, but in the end opted for it, as I didn’t see any serious drawbacks.&amp;nbsp; But I guess if you never plan to look at or deal with the generated files in any way, it doesn’t buy you a whole lot and you may choose to turn it off.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff0000&gt;&lt;STRONG&gt;Warning if you’re using VS2010 Beta 2:&lt;/STRONG&gt;&lt;/FONT&gt; Damien’s code uses the ITextTemplatingEngineHost interface, which got moved to a new Microsoft.VisualStudio.TextTemplating.Interfaces namespace in 2010 Beta 2.&amp;nbsp; So on 2010 Beta 2, you’ll need to add one extra import line to T4MVC.tt (the second line below):&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;#@ import namespace="Microsoft.VisualStudio.TextTemplating" #&amp;gt;
&amp;lt;#@ import namespace="Microsoft.VisualStudio.TextTemplating.Interfaces" #&amp;gt;&lt;/PRE&gt;
&lt;H2&gt;Support for Minified Javascript files&lt;/H2&gt;
&lt;P&gt;This one came from &lt;A href="http://twitter.com/matteightyate" mce_href="http://twitter.com/matteightyate"&gt;Matt Wicks&lt;/A&gt;.&amp;nbsp; Minified javascript files are alternate version of the files that makes them as small as possible, but using various strategies like removing white space.&amp;nbsp; e.g. in an MVC application’s Scripts folder, you’ll typically see both jquery-1.3.2.js and jquery-1.3.2.&lt;STRONG&gt;min&lt;/STRONG&gt;.js.&amp;nbsp; Usually, you want to use the minified version at deployment time (to make your site load faster), but the regular version at development time, so you can more easily debug into it.&lt;/P&gt;
&lt;P&gt;The new T4MVC support makes it automatic to use one vs. the other depending on the context.&amp;nbsp; T4MVC has been supporting script files for a while, letting you write:&lt;/P&gt;&lt;PRE class="brush: xml;"&gt;&amp;lt;script src="&amp;lt;%= Links.Scripts.jquery_1_2_6_js %&amp;gt;" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;/PRE&gt;
&lt;P&gt;With this new feature, you don’t need to change anything to this line, but the token jquery_1_2_6_js will automatically point to either jquery-1.3.2.js or jquery-1.3.2.min.js depending on whether you’re running in production.&amp;nbsp; How does it know whether you’re in production?&amp;nbsp; It calls a method defined in T4MVC.settings.t4 which makes the decision.&amp;nbsp; By default, it looks at whether debugging is enabled:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;    // Logic to determine if the app is running in production or dev environment
    public static bool IsProduction() { 
        return (HttpContext.Current != null &amp;amp;&amp;amp; !HttpContext.Current.IsDebuggingEnabled); 
    }&lt;/PRE&gt;But you can easily change this logic if you have a different way of determining ‘production’. &lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9923340" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>Peter Blum’s new blog and his cool new data source controls</title><link>http://blogs.msdn.com/davidebb/archive/2009/11/12/peter-blum-s-new-blog-and-his-cool-new-data-source-controls.aspx</link><pubDate>Fri, 13 Nov 2009 01:19:54 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9921686</guid><dc:creator>davidebb</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9921686.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9921686</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9921686</wfw:comment><description>&lt;p&gt;Peter Blum has been well known is the ASP.NET world for many years for writing a whole suite of powerful controls, which you can read all about on &lt;a href="http://www.peterblum.com/Home.aspx"&gt;his site&lt;/a&gt;.&amp;#160; One thing that was missing on Peter’s resume is that he never had a blog.&amp;#160; Well he started one earlier this month, and is making up for the lost time in a big way, with already 11 posts!&amp;#160; And we’re not talking about small posts that just point to other people’s stuff (unlike this post I suppose!), but real with useful meaty content.&amp;#160; Make sure you check out his blog at &lt;a title="http://weblogs.asp.net/peterblum/" href="http://weblogs.asp.net/peterblum/"&gt;http://weblogs.asp.net/peterblum/&lt;/a&gt;.&amp;#160; I hope he keeps the good stuff coming!&lt;/p&gt;  &lt;p&gt;In particular, Peter has been working hard on some interesting data source controls that work with Visual Studio 2010.&amp;#160; He’s calling them the ‘Versatile DataSources’, and is making it all &lt;a href="http://versatiledatasources.codeplex.com/"&gt;available for free on CodePlex&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The following posts on his blog describe the data source controls:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;First, an &lt;a href="http://weblogs.asp.net/peterblum/archive/2009/11/03/introducing-versatile-datasources.aspx"&gt;Intro Post&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Then a &lt;a href="http://weblogs.asp.net/peterblum/archive/2009/11/03/datasources-dynamic-data-and-soc.aspx"&gt;follow up post&lt;/a&gt; with more details and many code samples&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The simplest way to try out his controls is to &lt;a href="http://versatiledatasources.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35313#DownloadId=90624"&gt;download them from CodePlex&lt;/a&gt;.&amp;#160; The package contains a rich set of samples that you can directly run and play with.&amp;#160; You’ll need VS2010 Beta 2 to run this, so if you don’t already have it, get it from &lt;a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I haven’t fully tried everything yet, but the one I played with the most is his POCODataSource, which is quite interesting.&amp;#160; The core idea is very simple: you give it a type and it makes it easy to put up a WebForms UI to fill up an instance of that type.&amp;#160; The UI supports full validation using standard model annotations supported by Dynamic Data.&lt;/p&gt;  &lt;p&gt;The beauty is that it’s really quite easy to use.&amp;#160; The data source declaration looks something like this (borrowed from Peter’s samples):&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;   &amp;lt;poco:POCODataSource ID=&amp;quot;POCODataSource1&amp;quot; runat=&amp;quot;server&amp;quot; POCOTypeName=&amp;quot;CEOEmailGenerator&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;For the actual UI, you can use any standard ASP.NET data control like DetailsView, FormView or some similar 3rd party control.&amp;#160; Then when an Update operation happens, you simply access the built instance from the data source using&amp;#160; POCODataSource1.POCOInstance.&amp;#160; At that point, you can do whatever you want with it.&amp;#160; In Peter’s sample, he ends up calling an action method directly on the object, e.g.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;protected void FormView1_ItemUpdated(object sender, FormViewUpdatedEventArgs e) {
   if (Page.IsValid) {
      ((CEOEmailGenerator)POCODataSource1.POCOInstance).Send();
   }
}&lt;/pre&gt;

&lt;p&gt;But I don’t see anything that ties you to this pattern, and you could instead just call some helper method and pass the object if your object doesn’t have an action method itself.&lt;/p&gt;

&lt;p&gt;Anyway, check it out in much more details on Peter’s blog!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9921686" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/Dynamic+Data/default.aspx">Dynamic Data</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/Entity+Framework/default.aspx">Entity Framework</category></item><item><title>Using C# dynamic to call static members</title><link>http://blogs.msdn.com/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx</link><pubDate>Sat, 24 Oct 2009 01:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9912333</guid><dc:creator>davidebb</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9912333.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9912333</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9912333</wfw:comment><description>&lt;p&gt;By now, you’ve probably heard that C# 4.0 is adding support for the &lt;em&gt;dynamic&lt;/em&gt; keyword, which introduces some aspects of dynamic languages to C#.&amp;#160; I had not had a chance to really try it, but recently I was reading &lt;a href="http://weblogs.asp.net/bleroy/archive/2009/09/17/fun-with-c-4-0-s-dynamic.aspx"&gt;Bertrand Le Roy’s post&lt;/a&gt; on the topic, and was sort of looking for a good opportunity to use it.&lt;/p&gt;  &lt;p&gt;Today, I found a scenario which I thought it would work great for, but it turned out not to be supported out of the box!&lt;/p&gt;  &lt;p&gt;The scenario is to call static class members using dynamic.&amp;#160; That probably sounds crazy, so let’s look at an example.&amp;#160; Say you have these two classes:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public class Foo1 {
    public static string TransformString(string s) { return s.ToLower(); }
    public static string MyConstant { get { return &amp;quot;Constant from Foo1&amp;quot;; } }
}

public class Foo2 {
    public static string TransformString(string s) { return s.ToUpper(); }
    public static string MyConstant { get { return &amp;quot;Constant from Foo2&amp;quot;; } }
}&lt;/pre&gt;

&lt;p&gt;Note that they are unrelated classes, but share some members with the same signature.&amp;#160; In a sense, you could say that they two classes share a duct tape signature.&lt;/p&gt;

&lt;p&gt;Now here is the problem we’re trying to solve: &lt;strong&gt;given a System.Type object&lt;/strong&gt; of either class (or any other random class that shares those members), &lt;strong&gt;how can you call those members?&lt;/strong&gt;&amp;#160; Concretely, we’re trying to implement this method:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;static void MakeTestCalls(Type type) {
    // Call TransformString(&amp;quot;Hello World&amp;quot;) on this type

    // Get the MyConstant property on this type
}&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;How can we implement this method? &lt;/strong&gt; Ok, we can do it the old fashion way using reflection, e.g.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;static void MakeTestCalls(Type type) {
    Console.WriteLine(type.GetMethod(&amp;quot;TransformString&amp;quot;).Invoke(null, new object[] { &amp;quot;Hello World&amp;quot; }));
    Console.WriteLine(type.GetProperty(&amp;quot;MyConstant&amp;quot;).GetValue(null, null));
}&lt;/pre&gt;

&lt;p&gt;That works, but it’s ugly.&amp;#160; These are the very type of things that &lt;em&gt;dynamic&lt;/em&gt; is supposed to improve.&amp;#160; So my first naive attempt was to do this:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;static void MakeTestCalls(Type type) {
    dynamic fooTypeDynamic = type;

    Console.WriteLine(fooTypeDynamic.TransformString(&amp;quot;Hello World&amp;quot;));
    Console.WriteLine(fooTypeDynamic.MyConstant);
}&lt;/pre&gt;

&lt;p&gt;Basically, the theory was that when assigning a System.Type to a dynamic variable, it would let you call static members from it.&amp;#160; I didn’t really expect it to work, but I at least had to try! :)&amp;#160; And sure enough, it didn’t work, blowing up with: “Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.RuntimeType' does not contain a definition for 'TransformString'”.&lt;/p&gt;

&lt;p&gt;So I then posted the question on our internal C# list, and got a reply from C# guru &lt;a href="http://blogs.msdn.com/ericlippert/"&gt;Eric Lippert&lt;/a&gt;, basically saying that it was a potentially interesting idea but was just not supported in C# 4.0.&amp;#160; Fair enough, this is only the beginning of C# dynamic, and it doesn’t do everything.&lt;/p&gt;

&lt;p&gt;But I then went back to &lt;a href="http://weblogs.asp.net/bleroy/archive/2009/09/17/fun-with-c-4-0-s-dynamic.aspx"&gt;Bertrand’s post&lt;/a&gt; where he gives a great sample of how you can teach &lt;em&gt;dymamic&lt;/em&gt; new tricks by implementing a custom DynamicObject.&amp;#160; And it turned out to be relative simple.&amp;#160; Here is the class I ended up with:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class StaticMembersDynamicWrapper : DynamicObject {
    private Type _type;
    public StaticMembersDynamicWrapper(Type type) { _type = type; }

    // Handle static properties
    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        PropertyInfo prop = _type.GetProperty(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);
        if (prop == null) {
            result = null;
            return false;
        }

        result = prop.GetValue(null, null);
        return true;
    }

    // Handle static methods
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
        MethodInfo method = _type.GetMethod(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);
        if (method == null) {
            result = null;
            return false;
        }

        result = method.Invoke(null, args);
        return true;
    }
}&lt;/pre&gt;

&lt;p&gt;The idea is pretty simple: when the runtime needs to call something, it basically asks you to do it.&amp;#160; It passes you the method (or property) name and the parameters, and you take it from there. And in this case, of course, we’re using reflection.&lt;/p&gt;

&lt;p&gt;Once we have that, the real fun starts as we’re now able to call our static members using &lt;em&gt;dynamic&lt;/em&gt;!&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;static void MakeTestCalls(Type type) {
    dynamic typeDynamic = new StaticMembersDynamicWrapper(type);

    // Call TransformString(&amp;quot;Hello World&amp;quot;) on this type
    Console.WriteLine(typeDynamic.TransformString(&amp;quot;Hello World&amp;quot;));

    // Get the MyConstant property on this type
    Console.WriteLine(typeDynamic.MyConstant);
}&lt;/pre&gt;

&lt;p&gt;Note how we wrap the type into our custom DynamicObject is order to have the dynamic invocations go through us.&lt;/p&gt;

&lt;p&gt;Now you might say that the scenario above where you have two classes with identical static members doesn’t seem like something that would actually occur commonly in real apps.&amp;#160; But once you start bringing in generics, it can actually be more common.&amp;#160; e.g. suppose you have something like:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class Table&amp;lt;T&amp;gt; {
    public static IEnumerable&amp;lt;T&amp;gt; Records { get { [return records from database table T] } }
}&lt;/pre&gt;

&lt;p&gt;The idea is that the class is an abstraction for a database table.&amp;#160; So Table&amp;lt;Product&amp;gt;.Records returns an IEnumerable&amp;lt;Products&amp;gt;, and Table&amp;lt;Category&amp;gt;.Records returns an IEnumerable&amp;lt;Category&amp;gt;.&amp;#160; Now suppose you’re writing some table agnostic code that can work with the data from any table.&amp;#160; You have a System.Type for &lt;em&gt;some &lt;/em&gt;Table&amp;lt;T&amp;gt;, and you need to get its Records property.&amp;#160; &lt;strong&gt;Even though it seems like it’s the same Records property coming for a base class, the reality is that it’s a completely different property for each T&lt;/strong&gt;, and C# provides no simple way of making the call.&amp;#160; But with the technique above, you get to access the property with a much simpler syntax than with reflection.&lt;/p&gt;

&lt;p&gt;The zipped sample is attached to this post.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9912333" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9912333.ashx" length="3844" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/Dynamic/default.aspx">Dynamic</category></item><item><title>T4MVC 2.4.04 update: MVC 2 support, new settings, cleanup, fixes</title><link>http://blogs.msdn.com/davidebb/archive/2009/10/15/t4mvc-2-4-04-update-mvc-2-support-new-settings-cleanup-fixes.aspx</link><pubDate>Thu, 15 Oct 2009 20:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9907823</guid><dc:creator>davidebb</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9907823.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9907823</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9907823</wfw:comment><description>&lt;P&gt;To get the latest build of T4MVC:&lt;/P&gt;
&lt;H1 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC page on CodePlex&lt;/A&gt;&lt;/H1&gt;
&lt;P&gt;Though I haven’t blogged for a while about T4MVC, I’ve been making a few minor updates and only sent notification via Twitter.&amp;nbsp; Now, I have a few things that are worth discussing in a little more detail.&amp;nbsp; Note that you can see the complete list of changes from version to version in the readme.txt file that comes with it.&amp;nbsp; 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.&lt;/P&gt;
&lt;P&gt;The changes described below were added between version 2.4.00 and 2.4.04.&lt;/P&gt;
&lt;H2&gt;MVC 2 Preview 2 support&lt;/H2&gt;
&lt;P&gt;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.&amp;nbsp; The reason is was not working is that the MVC team changed a number of their API’s to return MvcHtmlString instead of strings.&lt;/P&gt;
&lt;P&gt;One challenge here is that I did not want to maintain two separate versions of T4MVC, just to account for this small difference.&amp;nbsp; 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.&amp;nbsp; 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!&lt;/P&gt;
&lt;P&gt;Detecting the version of MVC in use through the less-then-perfect VS DTE object model was a bit of a challenge in itself.&amp;nbsp; In case you’re curious, here is the logic I ended up with:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;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;
    }
}&lt;/PRE&gt;
&lt;P&gt;The fact that I had to cast Project.Object to a VSProject was far from intuitive.&amp;nbsp; But anyway, I digress, this post is not about the VS DTE model :)&lt;/P&gt;
&lt;P&gt;So, back to MVC 2, please note that &lt;STRONG&gt;this new T4MVC does not add support for any of the new features&lt;/STRONG&gt;.&amp;nbsp; It simply allows it to run without blowing up, but still only supports features that existed in MVC 1.&amp;nbsp; In particular, the one big obvious feature that would be worth supporting is Areas (&lt;A href="http://haacked.com/archive/2009/07/31/single-project-areas.aspx" mce_href="http://haacked.com/archive/2009/07/31/single-project-areas.aspx"&gt;Phil’s blog&lt;/A&gt;).&amp;nbsp; This is something I’d definitely like to add support for when I get some cycles (unless someone else does it first! :)).&lt;/P&gt;
&lt;H2&gt;Generate cleaner code that doesn’t make various tools complain&lt;/H2&gt;
&lt;P&gt;This came as various separate changes based of issues that several people mentioned.&amp;nbsp; Copying items from the revision list:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Put all the generated code in a T4MVC #region. This is useful to tell tools like ReSharper to ignore it.&lt;/LI&gt;
&lt;LI&gt;Added &amp;lt;auto-generated /&amp;gt; comment to disable StyleCop in generated file&lt;/LI&gt;
&lt;LI&gt;Added pragma to prevent compiler from complaining about missing Xml comments&lt;/LI&gt;
&lt;LI&gt;Renamed generated classes to be CLS compliant&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Generally, T4MVC is trying to be a good citizen with the various tools people are running.&lt;/P&gt;
&lt;H2&gt;New knobs in T4MVC.settings.t4&lt;/H2&gt;
&lt;P&gt;You can look at T4MVC.settings.t4 to see the list of things that are customizable.&amp;nbsp; In short, and again copying from the history list, the new knobs are:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Added a setting to turn off the behavior that always keeps the template dirty&lt;/LI&gt;
&lt;LI&gt;Added a setting to set the namespace that Links get generated in&lt;/LI&gt;
&lt;LI&gt;Added ProcessVirtualPath method to T4MVC.settings.t4 so user can write custom logic to modify client URL's&lt;/LI&gt;&lt;/UL&gt;
&lt;H2&gt;Cleanup&lt;/H2&gt;
&lt;P&gt;I made various cleanup to the template’s logic.&amp;nbsp; In particular, I greatly simplified the logic that locates the VS project that contains the T4 template, by using the FindProjectItem() method:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;// Find the .tt file's ProjectItem
ProjectItem projectItem = dte.Solution.FindProjectItem(Host.TemplateFile);&lt;/PRE&gt;Before, I was doing all kind of crazy things, mostly because I didn’t know about this method.&amp;nbsp; I’m learning the VS DTE model as I go along, as I had never used it before :) &lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9907823" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>T4MVC 2.4 updates: settings file, sub view folders, ActionName support and more</title><link>http://blogs.msdn.com/davidebb/archive/2009/07/28/t4mvc-2-4-updates-settings-file-sub-view-folders-actionname-support-and-more.aspx</link><pubDate>Tue, 28 Jul 2009 23:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9851503</guid><dc:creator>davidebb</dc:creator><slash:comments>34</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9851503.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9851503</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9851503</wfw:comment><description>&lt;P&gt;To get the latest build of T4MVC:&lt;/P&gt;
&lt;H2 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC page on CodePlex&lt;/A&gt;&lt;/H2&gt;
&lt;P&gt;This post is a continuation of various previous posts on the T4MVC template for ASP.NET MVC:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx"&gt;A new and improved ASP.NET MVC T4 template&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;The MVC T4 template is now up on CodePlex&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/30/t4mvc-2-2-update-routing-forms-di-container-fixes.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/30/t4mvc-2-2-update-routing-forms-di-container-fixes.aspx"&gt;T4MVC 2.2 update: Routing, Forms, DI container, fixes&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I last blogged about version 2.2, and there have been a number of changes since that (you can get the full history at the top of the T4MVC.tt file).&amp;nbsp; This post describes some of those changes.&lt;/P&gt;
&lt;H2&gt;T4MVC now uses a separate settings file&lt;/H2&gt;
&lt;P&gt;Previously, if you wanted to customize T4MVC, you’d have to change T4MVC.tt directly.&amp;nbsp; This is fine until you want to grab the next build, and have to hand merge the changes.&lt;/P&gt;
&lt;P&gt;Instead, it is now using a separate settings file called T4MVC.settings.t4.&amp;nbsp; The idea is that you can tweak some behavior by changing this file, without changing the main file.&amp;nbsp; &lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Make sure that you copy both files when you grab 2.4 or later!&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Note&lt;/STRONG&gt;: it uses a .t4 extension instead of .tt, because we don’t want VS to process it directly.&amp;nbsp; Instead, it’s included by the main .tt file.&amp;nbsp; What’s nice is that the .t4 extension is also recognized by &lt;A href="http://www.visualt4.com/" mce_href="http://www.visualt4.com/"&gt;Clarius’ Visual T4&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Currently, it doesn’t support all that many settings, but it’s only a first step.&amp;nbsp; The idea is that as more customization scenarios come up, new things will appear there.&amp;nbsp; Of course, you may need some small hand merging of the settings files when you update to newer versions, but that’s a lot less painful than merging the main .tt file.&lt;/P&gt;
&lt;P&gt;Here is what it contains in 2.4.00:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;// The prefix used for things like MVC.Dinners.Name and MVC.Dinners.Delete(Model.DinnerID)
const string HelpersPrefix = "MVC";

// The folder under the project that contains the controllers
const string ControllersFolder = "Controllers";

// The folder under the project that contains the views
const string ViewsRootFolder = "Views";

// Folders containing static files for which links are generated (e.g. Links.Scripts.Map_js)
readonly string[] StaticFilesFolders = new string[] {
    "Scripts",
    "Content",
};&lt;/PRE&gt;
&lt;H2&gt;Support for views in sub folders&lt;/H2&gt;
&lt;P&gt;I have had a few users mention that they sometimes don’t put their views directly under Views\CtrlName, but instead put them in a subfolder.&amp;nbsp; e.g. you might have Views\Dinners\Sub\Details.aspx.&lt;/P&gt;
&lt;P&gt;Previously, T4MVC was ignoring those.&amp;nbsp; Now, it finds them and makes them available using a matching hierarchy.&lt;/P&gt;
&lt;P&gt;So when you have Views\Dinners\Sub\Details.aspx, you can refer to it as&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;MVC.Dinners.Views.Sub.Details&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;or if you’re within the Dinners controller, you can just write:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Views.Sub.Details&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And this will evaluate to "Sub/Details".&lt;/P&gt;
&lt;H2&gt;Support for [ActionName] attribute&lt;/H2&gt;
&lt;P&gt;Suppose you have an action method that looks like:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;public virtual ActionResult Details(int id) {&lt;/PRE&gt;
&lt;P&gt;By default, the action name is just the method name: “Details”.&amp;nbsp; That is, this is what normally shows up in your URLs, e.g. /Dinners/&lt;STRONG&gt;Details&lt;/STRONG&gt;/2.&lt;/P&gt;
&lt;P&gt;But sometimes, you want your action name to be different from the method name, and that’s when you would use the MVC &lt;A href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionnameattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionnameattribute.aspx"&gt;ActionName attribute&lt;/A&gt;.&amp;nbsp; e.g.&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;[ActionName("NewActionName")]
public virtual ActionResult Details(int id) {&lt;/PRE&gt;
&lt;P&gt;And now your URLs start looking like /Dinners/&lt;STRONG&gt;NewActionName&lt;/STRONG&gt;/2.&lt;/P&gt;
&lt;P&gt;Except that previously, T4MVC was ignoring this attribute, causing it to still generate the old URL!&amp;nbsp; Now, it correctly locates and honors the attribute.&lt;/P&gt;
&lt;P&gt;The beauty is that T4MVC completely shields your code from those changes.&amp;nbsp; Without it, you’d have written:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;%= Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID }) %&amp;gt;&lt;/PRE&gt;
&lt;P&gt;And you would have had to change “Details'” to “NewActionName”.&amp;nbsp; But with T4MVC, you just write:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;%= Html.ActionLink(dinner.Title, MVC.Dinners.Details(dinner.DinnerID)) %&amp;gt;&lt;/PRE&gt;
&lt;P&gt;And it keeps on doing the right thing no matter what the ActionName is set to!&lt;/P&gt;
&lt;H2&gt;New parameter-less overload for all actions&lt;/H2&gt;
&lt;P&gt;Previously, T4MVC was only offering pseudo-action calls that had the exact same signature as the real action method.&amp;nbsp; This usually works well, but in some POST scenarios, the parameters comes from the form and not the URL.&lt;/P&gt;
&lt;P&gt;To solve this, T4MVC now always generates a parameter-less overloads.&amp;nbsp; e.g. suppose your action looks like:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;[AcceptVerbs(HttpVerbs.Post), Authorize]
public virtual ActionResult Edit(int id, FormCollection collection) {&lt;/PRE&gt;
&lt;P&gt;Where both the id and the FormCollection are things that you don’t want to pass explicitly, you can write:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;&amp;lt;% using (Html.BeginForm(MVC.Dinners.Edit())) { %&amp;gt;&lt;/PRE&gt;
&lt;P&gt;So you still get the benefit of not hard coding the controller and action names (what T4MVC is all about), even though you’re not using the signature that matches your real action.&lt;/P&gt;
&lt;H2&gt;Support for placing T4MVC.tt below the root of the app&lt;/H2&gt;
&lt;P&gt;Previously, T4MVC.tt had to be at the root of the MVC web application.&amp;nbsp; Some users mentioned that they preferred to have it in some other folder, like ‘Templates’.&amp;nbsp; So I made a change so it can be anywhere under the project root.&lt;/P&gt;
&lt;H2&gt;Bug fixes&lt;/H2&gt;
&lt;P&gt;There are also a number of bug fixes that are not interesting enough to discuss individually.&amp;nbsp; Please see the history at the top of T4MVC.tt for details.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9851503" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>Using an Associated Metadata Class outside Dynamic Data</title><link>http://blogs.msdn.com/davidebb/archive/2009/07/24/using-an-associated-metadata-class-outside-dynamic-data.aspx</link><pubDate>Sat, 25 Jul 2009 04:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9848007</guid><dc:creator>davidebb</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9848007.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9848007</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9848007</wfw:comment><description>&lt;P&gt;A while back, I &lt;A href="http://blogs.msdn.com/davidebb/archive/2008/06/16/dynamic-data-and-the-associated-metadata-class.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2008/06/16/dynamic-data-and-the-associated-metadata-class.aspx"&gt;blogged&lt;/A&gt; about how ASP.NET Dynamic Data apps can uses an Associated Metadata class (aka a ‘buddy’ class) to add metadata attributed to properties defined in a generated class.&amp;nbsp; It’s a mostly ugly thing that was made necessary by limitations of the C# and VB.NET languages: they don’t let you add attributes to properties defined in another partial class.&lt;/P&gt;
&lt;P&gt;What I didn’t mention there is that this ‘buddy’ class mechanism is actually not specific to Dynamic Data apps, and can in fact be used anywhere.&amp;nbsp; Since I’ve recently heard of several cases of users trying to do something similar, I’ll describe how it’s done.&amp;nbsp; If you’re familiar with TypeDescriptionProviders (which have been around since ancient times), this will look very trivial.&lt;/P&gt;
&lt;P&gt;I will illustrate this in a very simple console app to keep all other distractions out of the picture (the full sample is attached to the post).&amp;nbsp; So the general scenario is that we have a generated class somewhere, e.g.&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;// Assume that this is generated code that should never be hand modified.
// Hence metadata attributes can't be added directly here

public partial class Product {
    public string Name { get; set; }

    public int UnitsInStock { get; set; }
}&lt;/PRE&gt;
&lt;P&gt;Instead, the buddy provider let’s you write:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;[MetadataType(typeof(Product_Metadata))]
public partial class Product {
}

class Product_Metadata {
    [DisplayName("The Units In Stock")]
    public object UnitsInStock { get; set; }
}&lt;/PRE&gt;
&lt;P&gt;This works in Dynamic Data, but if we’re in some other context, no one will find our Product_Metadata ‘buddy’.&amp;nbsp; In our to hook it up ourselves, we just need to make one call!&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;TypeDescriptor.AddProvider(
    new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Product)),
    typeof(Product));&lt;/PRE&gt;
&lt;P&gt;Pretty trivial stuff: we instantiate a TypeDescriptionProvider (with a somewhat scary name, I’ll give you that) and we register it by calling TypeDescriptor.AddProvider.&lt;/P&gt;
&lt;P&gt;Once we do that, the attributes on the ‘buddy’ class magically show up as if they were defined on the real class:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;// Get the property descriptor for UnitsInStock
PropertyDescriptor propDesc = TypeDescriptor.GetProperties(
    typeof(Product)).Find("UnitsInStock", true);

// Get the display name attribute, which is not actually on the property,
// but on its counterpart in the 'buddy' class
var displayName = propDesc.Attributes.OfType&amp;lt;DisplayNameAttribute&amp;gt;().First();&lt;/PRE&gt;
&lt;P&gt;And that’s pretty much it.&amp;nbsp; One important thing to notice here is that &lt;STRONG&gt;we are not using the standard reflection API&lt;/STRONG&gt; (which would look like typeof(Product).GetCustomAttributes()), but we are instead using the TypeDescriptor API from the System.ComponentModel model namespace.&lt;/P&gt;
&lt;P&gt;So to summarize, you can easily use this ‘buddy’ class mechanism anytime you deal with generated code that you need to annotate with attributes.&amp;nbsp; And even though it’s not pretty to have to use that extra class, it’s comes very handy when there is no alternative.&amp;nbsp; Maybe the day will come when C# will support doing this more cleanly, but in the meantime that’ll have to do!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9848007" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9848007.ashx" length="7616" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/Dynamic+Data/default.aspx">Dynamic Data</category></item><item><title>Two ways to use T4 templates: support code vs. one-time generation</title><link>http://blogs.msdn.com/davidebb/archive/2009/07/17/two-ways-to-use-t4-templates-support-code-vs-one-time-generation.aspx</link><pubDate>Fri, 17 Jul 2009 10:43:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9836857</guid><dc:creator>davidebb</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9836857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9836857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9836857</wfw:comment><description>&lt;p&gt;T4 templates have proven to be useful is a whole range of scenarios, and more and more developers are finding interesting things to do with them.&lt;/p&gt;  &lt;p&gt;For the most part, all those scenarios fall under two very distinct categories: “support code” versus one-time generation.&amp;#160; Unlike my previous post on &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/03/codedom-vs-t4-two-approaches-to-code-generation.aspx"&gt;CodeDom vs. T4&lt;/a&gt;, here we’re not talking about making a choice between two competing technologies, but simply about using T4 in the way that makes sense for a given scenario.&lt;/p&gt;  &lt;p&gt;Let’s start with a brief description of the two usage patterns:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Support code&lt;/strong&gt;: here, a T4 template generates a file that you rarely need to look at, and you should never modify.&amp;#160; Instead, it contains “support code” that you can code against.&amp;#160; A great example of this is my &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;T4MVC template&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;One-time generation&lt;/strong&gt;: here, you are executing a T4 template to generate a file that then becomes part of your project.&amp;#160; This file can then safely be modified.&amp;#160; The T4 template just gave you a starting point.&amp;#160; A great example of this is the Add View dialog in ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;I purposely gave two examples that relate to ASP.NET MVC to make a point that the two scenarios are not exclusive, and can play different parts within the same application.&lt;/p&gt;  &lt;p&gt;The rest of this post will discuss various aspects of the two scenarios in more details.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Using T4 templates to generate “Support Code”&lt;/h2&gt;  &lt;p&gt;This is the scenario that you are most likely to have encountered when you got introduced to T4 templates.&amp;#160; It has a pretty low barrier of entry as it is directly supported by Visual Studio 2008.&amp;#160; The general flow here is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You add a file with a .tt extension to your VS project &lt;/li&gt;    &lt;li&gt;VS knows about those files, so it instantly sets it up to use the ‘TextTemplatingFileGenerator’ custom tool (you can see this in the .tt file’s property grid). &lt;/li&gt;    &lt;li&gt;Whenever you save the .tt file, the template executes, and the generated file becomes a sub-file of the .tt file. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;e.g. suppose your Hello.tt file has:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;&amp;lt;#@ Template Language=&amp;quot;C#v3.5&amp;quot; #&amp;gt;
&amp;lt;#@ Output Extension=&amp;quot;.cs&amp;quot; #&amp;gt;

public static class Hello {
    public static void SayHello() {
&amp;lt;# for (int i=0; i&amp;lt;5; i++) { #&amp;gt;
        System.Console.WriteLine(&amp;quot;Hello &amp;lt;#= i #&amp;gt;&amp;quot;);
&amp;lt;# } #&amp;gt;
    }
}&lt;/pre&gt;

&lt;p&gt;In the solution explorer, you will see:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/TwowaysofusingT4templatesonetimegenerati_14319/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/TwowaysofusingT4templatesonetimegenerati_14319/image_thumb.png" width="131" height="43" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;And Hello.cs will contain:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public static class Hello {
    public static void SayHello() {
        System.Console.WriteLine(&amp;quot;Hello 0&amp;quot;);
        System.Console.WriteLine(&amp;quot;Hello 1&amp;quot;);
        System.Console.WriteLine(&amp;quot;Hello 2&amp;quot;);
        System.Console.WriteLine(&amp;quot;Hello 3&amp;quot;);
        System.Console.WriteLine(&amp;quot;Hello 4&amp;quot;);
    }
}&lt;/pre&gt;

&lt;p&gt;Pretty simplistic stuff as far as code generation goes, but there are some key points that need to be made about it.&lt;/p&gt;

&lt;p&gt;First and foremost, &lt;strong&gt;you should never modify the generated file&lt;/strong&gt;.&amp;#160; You certainly can go in there and make changes, and no one will stop you.&amp;#160; You can even run your project and your hand modified code will execute.&amp;#160; But guess what will happen the next time you open Hello.tt and save it?&amp;#160; It will re-execute and blow away your carefully modified Hello.cs.&amp;#160; So resist the temptation, and don’t mess with the generated file!&lt;/p&gt;

&lt;p&gt;That’s why I named this scenario “Support Code”.&amp;#160; What gets generated is code that is meant to be &lt;strong&gt;used &lt;/strong&gt;by you in the rest of your app.&amp;#160; e.g. in the example above, you could simply call Hello.SayHello() from your console app’s Main.&lt;/p&gt;

&lt;p&gt;Now you can take a look at the &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;T4MVC template&lt;/a&gt;, which has 1000 lines and does pretty complex things to make it easier to write your MVC app.&amp;#160; But in essence, it works the exact same way as this trivial example: it’s a .tt file which generates a .cs file.&amp;#160; You rarely look at the .cs file, and you never modify it, but instead you call into the bits and pieces that it generates from your controllers and views.&amp;#160; It will frequently regenerate as you project changes, and that’s really the whole point: it keeps itself up to date so you don’t code against stale code.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Using T4 files for one-time generation&lt;/h2&gt;

&lt;p&gt;In this scenario, our purpose is to help the user create a new file for their project by pre-generating it with some useful content instead of having them start with some generic empty file.&lt;/p&gt;

&lt;p&gt;As mentioned above, a great example of this is the ASP.NET MVC Add View functionality.&amp;#160; It is described in quite some detail in &lt;a href="http://blogs.msdn.com/webdevtools/archive/2009/01/29/t4-templates-a-quick-start-guide-for-asp-net-mvc-developers.aspx"&gt;this post&lt;/a&gt;, so you may want to check it out.&amp;#160; I’ll use this as an illustration in this section, though of course a similar technique can be applied to other domains.&amp;#160; Here the general flow is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You would like to generate a new View for their app &lt;/li&gt;

  &lt;li&gt;Instead of giving you a generic new view (which a regular item template would do), it asks you a bunch of questions: 
    &lt;ul&gt;
      &lt;li&gt;What kind of view would you like, e.g. List, Details, Edit, … &lt;/li&gt;

      &lt;li&gt;What kind of entity is it for, e.g. Product, Customer, … &lt;/li&gt;

      &lt;li&gt;What master page you want to use, etc… &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;It takes all that knowledge and feeds it into a T4 template (suing a custom T4 host; a bit more on this later), which generates the view and adds it where it belongs in your project &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In both the “Support Code” scenario and here, a T4 file is used to generate another file, but from here on things become totally different.&amp;#160; In this one-time generation scenario, the resulting file becomes a completely normal file that’s part of your project.&amp;#160; As such, &lt;strong&gt;you can freely modify it without fear of it getting overwritten&lt;/strong&gt;, since the T4 template is no longer in the picture.&amp;#160; It was simply used to create the file to get you started.&amp;#160; It was a “one-time” generation.&lt;/p&gt;

&lt;p&gt;One weakness of this model is that you can’t easily rerun the template.&amp;#160; e.g. suppose your Product class gets a new member and you want to update the view to account for it.&amp;#160; If you hadn’t touched to previous generated view, you can certainly delete it and rerun the Add View dialog.&amp;#160; But if you had made any modifications, you’re mostly out of luck, and probably better off updating your view by hand without help from the T4 template.&amp;#160; In spite of this weakness, the model is still very useful to get the user quickly started with their code and guiding them towards the pit of success.&lt;/p&gt;

&lt;p&gt;Note that I didn’t say much about exactly how the T4 template gets executed in this scenario.&amp;#160; Unlike the “Support Code” scenario, VS is not the one doing it.&amp;#160; Instead, you have to do some things that are a bit more involved to make it happen.&amp;#160; I won’t go into details about how to write a custom T4 host here as it is beyond the scope of this post, and is well covered by other posts (in particular, check out &lt;a href="http://www.olegsych.com/"&gt;Oleg Sych’s blog&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;One last thing I’ll mention about this model is that the .tt file is normally not part of your project.&amp;#160; Instead, it lives somewhere else, and only its output becomes part of your project.&amp;#160; Well, technically, the .tt file can be in your project for easy editing, but you then have to remove the ‘TextTemplatingFileGenerator’ custom tool, because you really don’t want it to execute on its own (it would surely fail with the custom host).&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;To reemphasize what I said early on, these are not two scenarios that compete with each other and for which you must “pick a side”.&amp;#160; They are just two completely different ways of making use of T4 files.&amp;#160; Both are being used successfully in various projects, and they can live together happily ever after :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9836857" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category></item><item><title>AspPathGuru: A little T4 love for ASP.NET WebForms</title><link>http://blogs.msdn.com/davidebb/archive/2009/07/12/asppathguru-a-little-t4-love-for-asp-net-webforms.aspx</link><pubDate>Sun, 12 Jul 2009 10:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9829978</guid><dc:creator>davidebb</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9829978.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9829978</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9829978</wfw:comment><description>&lt;P&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06.aspx"&gt;Last month&lt;/A&gt;, I wrote a number of posts on using T4 templates to get strong typing in ASP.NET MVC applications. The result is the T4MVC template &lt;A href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471" mce_href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471"&gt;available on CodePlex&lt;/A&gt;.&amp;nbsp; This template has been pretty popular with many MVC users, and I received a huge amount of feedback on improving it.&amp;nbsp; Most of it has been integrated into the CodePlex version (see the extensive History section in the TT file!).&lt;/P&gt;
&lt;P&gt;While T4MVC is only useful to MVC applications, someone suggested that ASP.NET WebForms applications could also benefit from some strong typing, so I put together a little T4 template that does some of that.&lt;/P&gt;
&lt;P&gt;Unlike T4MVC which tries to cover a whole range of MVC scenarios (relating to Controllers, Actions and Views), this template just does one thing: it generates strongly typed constants that points to the path to all aspx/ascx/master files.&amp;nbsp; Since it only deals with path, I called it AspPathGuru.tt.&lt;/P&gt;
&lt;P&gt;To use it, just drop AspPathGuru.tt (attached to this post) to the root of your Web Application.&lt;/P&gt;
&lt;P&gt;You’ll then be able to change code that looks like:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Control &lt;/SPAN&gt;uc = LoadControl(&lt;SPAN style="COLOR: #a31515"&gt;"~/UserControls/MyUserControl.ascx"&lt;/SPAN&gt;);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;to&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Control &lt;/SPAN&gt;uc = LoadControl(&lt;SPAN style="COLOR: #2b91af"&gt;Paths&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #2b91af"&gt;UserControls&lt;/SPAN&gt;.MyUserControl_ascx);&lt;/PRE&gt;
&lt;P&gt;The benefits are clear:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;You get intellisense while typing the constant, helping you make sure you get it right.&lt;/LI&gt;
&lt;LI&gt;If you ever move, rename or delete the user control, you will get a compile time error instead of a runtime error, hence catching the issue much earlier.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Some limitations you should be aware of:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;It only supports Web Applications, not Web Sites.&amp;nbsp; This is because T4 templates don’t get processed in Web Sites (at least I couldn’t get them to, maybe there is a way).&lt;/LI&gt;
&lt;LI&gt;You need to save the .tt file for the generation to occur.&amp;nbsp; So whenever you add or rename aspx/ascx file that you’d like to point to using the generated constant, you should save it.&amp;nbsp; In T4MVC, I implemented a workaround that causes the template to &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;run whenever you build&lt;/A&gt;, and we could do this for AspPathGuru as well, but I wanted to keep it nice and simple to stat with.&lt;/LI&gt;
&lt;LI&gt;It’s probably obvious, but the generated constants are only usable is places where you can write code, like the LoadControl call above.&amp;nbsp; So don’t try to use it as the ‘src’ in a &amp;lt;%@ Register %&amp;gt; directive; it will not work!&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Anyway, at this point this is just a simple template that covers this one scenario, and is certainly much less ambitious than T4MVC.&amp;nbsp; Generally, I think that there just aren’t as many areas in WebForms that can benefit from code generation compared to MVC, but at least this is one!&lt;/P&gt;
&lt;P&gt;Let me know if you find this useful, or if you can think of other areas where a T4 template could benefit WebForms applications.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9829978" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9829978.ashx" length="1575" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category></item><item><title>T4MVC 2.2 update: Routing, Forms, DI container, fixes</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/30/t4mvc-2-2-update-routing-forms-di-container-fixes.aspx</link><pubDate>Tue, 30 Jun 2009 23:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9810154</guid><dc:creator>davidebb</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9810154.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9810154</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9810154</wfw:comment><description>&lt;P&gt;To get the latest build of T4MVC:&lt;/P&gt;
&lt;H2 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC home&amp;nbsp;page&lt;/A&gt;&lt;/H2&gt;
&lt;P&gt;This post is a continuation of various recent posts, most notably:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx"&gt;A new and improved ASP.NET MVC T4 template&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;The MVC T4 template is now up on CodePlex&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;First, I’d like to thank all those who are using the MVC T4 template and sent me suggestions and bug reports.&amp;nbsp; Most issues have been addressed, and most suggestions have been integrated.&amp;nbsp; I’m up to the 8th CodePlex drop, and it’s only been a week! You can see the history of changes at the top of the .tt file.&lt;/P&gt;
&lt;P&gt;Frankly, when I started playing with this, I just thought it’d be a fun thing to spend the afternoon on.&amp;nbsp; Instead, I have probably spent close to half my time working on it in the last week.&amp;nbsp; And I do have other things to work on! :)&amp;nbsp; But it’s been a lot of fun, so no regrets!&lt;/P&gt;
&lt;P&gt;I’m not going to detail every change since the last blog post, since many are bug fixes that are not particularly exciting (though they help make the thing work!).&amp;nbsp; Instead, I’ll just focus on a few new key areas.&lt;/P&gt;
&lt;H2&gt;Strongly typed support for MapRoute&lt;/H2&gt;
&lt;P&gt;This is similar to the RedirectToAction/ActionLink support, but applied to route creation.&amp;nbsp; The original Nerd Dinner routes look like this:&lt;/P&gt;&lt;PRE class=code&gt;routes.MapRoute(
    &lt;SPAN style="COLOR: #a31515"&gt;"UpcomingDinners"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: #a31515"&gt;"Dinners/Page/{page}"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ controller = &lt;SPAN style="COLOR: #a31515"&gt;"Dinners"&lt;/SPAN&gt;, action = &lt;SPAN style="COLOR: #a31515"&gt;"Index" &lt;/SPAN&gt;}
);

routes.MapRoute(
    &lt;SPAN style="COLOR: #a31515"&gt;"Default"&lt;/SPAN&gt;,&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"{controller}/{action}/{id}"&lt;/SPAN&gt;,&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ controller = &lt;SPAN style="COLOR: #a31515"&gt;"Home"&lt;/SPAN&gt;, action = &lt;SPAN style="COLOR: #a31515"&gt;"Index"&lt;/SPAN&gt;, id = &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;}&lt;SPAN style="COLOR: green"&gt;
&lt;/SPAN&gt;);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The ‘defaults’ line of each route is what we’re trying to fix.&amp;nbsp; It makes heavy use of anonymous objects and literal strings, which should be avoided whenever possible.&amp;nbsp; If your controller or action name change, you won’t easily catch it.&lt;/P&gt;
&lt;P&gt;Previous version of T4MVC let you change that line to:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ controller=&lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Dinners.Name, action=&lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Dinners.Actions.Index }&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This fixes the issue for the most part, but it’s a bit wordy and doesn’t support refactoring.&amp;nbsp; Now, the latest version of T4MVC lets you change those routes to:&lt;/P&gt;&lt;PRE class=code&gt;routes.MapRoute(
    &lt;SPAN style="COLOR: #a31515"&gt;"UpcomingDinners"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: #a31515"&gt;"Dinners/Page/{page}"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Dinners.Index(&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
);

routes.MapRoute(
    &lt;SPAN style="COLOR: #a31515"&gt;"Default"&lt;/SPAN&gt;,&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"{controller}/{action}/{id}"&lt;/SPAN&gt;,&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Home.Index(),&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ id = &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;}&lt;SPAN style="COLOR: green"&gt;
&lt;/SPAN&gt;);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Note how we are now pointing at the action by simply making a call to it (though it’s a pseudo-call, and your action method won’t actually be called).&lt;/P&gt;
&lt;P&gt;Also note that in the second route, we’re still using an anonymous object for the ‘id’.&amp;nbsp; This is because even though the route expects an id, the default Action method (HomeController.Index()) doesn’t take one.&amp;nbsp; You could get around this by adding a ‘string id’ param to HomeController.Index() and ignoring it in the method.&amp;nbsp; You could then write MVC.Home.Index(null) in the route and avoid all anonymous objects.&lt;/P&gt;
&lt;H2&gt;BeginForm support&lt;/H2&gt;
&lt;P&gt;This came courtesy of &lt;A href="http://twitter.com/michaelhartau" mce_href="http://twitter.com/michaelhartau"&gt;Michael Hart&lt;/A&gt;.&amp;nbsp; Essentially, it’s the same support as ActionLink() but for the BeginForm() method.&amp;nbsp; But note that because form posts typically pass most of the data via the form and not the URL, BeginForm() is trickier to use correctly than the other methods.&lt;/P&gt;
&lt;P&gt;Here is how you might use this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(Html.BeginForm(&lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Account.LogOn(), &lt;SPAN style="COLOR: #2b91af"&gt;FormMethod&lt;/SPAN&gt;.Post)) { ... }&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Or if the action method takes parameters, you would pass them in the call.&amp;nbsp; However, when you do this you need to make sure that you aren’t also trying to pass those same parameters via the form (e.g. using a text box).&lt;/P&gt;
&lt;P&gt;Generally, the rule of thumb is that this support works well when you’re dealing with forms where the Action method signature exactly matches the form URL.&lt;/P&gt;
&lt;H2&gt;Support for Dependency Injection containers&lt;/H2&gt;
&lt;P&gt;Though this is a bug fix rather than a new feature, I’ll mention it because it affected several people and had me puzzled for a while.&lt;/P&gt;
&lt;P&gt;The root of the problem is that T4MVC generate new constructors for the controllers, and that DI containers use a somewhat arbitrary algorithm to decide what constructor to use.&amp;nbsp; And in those users’ cases, they ended up calling the new constructor generated by T4MVC, messing things up badly.&lt;/P&gt;
&lt;P&gt;The fix was simply to change the generated constructor to be protected, to prevent DI containers from using it.&amp;nbsp; Since T4MVC only uses it when it instantiates the controller derived class, protected works fine.&lt;/P&gt;
&lt;P&gt;Well, I should note that I haven’t actually verified that the fix addresses the issue, but I’m sure those users will tell me if it doesn’t! :)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9810154" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>The MVC T4 template is now up on CodePlex, and it does change your code a bit</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx</link><pubDate>Fri, 26 Jun 2009 17:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9805709</guid><dc:creator>davidebb</dc:creator><slash:comments>53</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9805709.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9805709</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9805709</wfw:comment><description>&lt;P&gt;&lt;STRONG&gt;Short version&lt;/STRONG&gt;: the MVC T4 template (now named T4MVC) is now available on CodePlex, as one of the downloads in the &lt;A href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471" mce_href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471"&gt;ASP.NET MVC v1.0 Source page&lt;/A&gt;.&lt;/P&gt;
&lt;H2 align=center&gt;&lt;A href="http://aspnet.codeplex.com/wikipage?title=T4MVC" mce_href="http://aspnet.codeplex.com/wikipage?title=T4MVC"&gt;Go to&amp;nbsp;T4MVC home page&lt;/A&gt;&lt;/H2&gt;
&lt;H2&gt;Poll verdict: it’s ok for T4MVC to make small changes&lt;/H2&gt;
&lt;P&gt;Yesterday, I posted asking &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/24/mind-if-my-mvc-t4-template-changes-your-code-a-bit.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/24/mind-if-my-mvc-t4-template-changes-your-code-a-bit.aspx"&gt;how people felt about having the template modify their code&lt;/A&gt; in small ways.&amp;nbsp; Thanks to all those who commented!&amp;nbsp; The fact that &lt;A href="http://www.hanselman.com/blog/TheWeeklySourceCode43ASPNETMVCAndT4AndNerdDinner.aspx" mce_href="http://www.hanselman.com/blog/TheWeeklySourceCode43ASPNETMVCAndT4AndNerdDinner.aspx"&gt;Scott Hanselman blogged it&lt;/A&gt; certainly helped get traffic there :)&lt;/P&gt;
&lt;P&gt;The majority of people thought that it was fine as long as&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It’s just those small changes: make classes partial and action methods virtual. Don’t mess with ‘real’ code! &lt;/LI&gt;
&lt;LI&gt;It asks for permission, or at least tells you what it’s doing &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I started looking for a way to pop up a Yes/No dialog, but ended up going with a slightly different approach: T4MVC adds a warning line for every item it modifies.&amp;nbsp; e.g. when you run it, you might see these in the warnings area:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Running transformation: T4MVC.tt changed the class DinnersController to be partial &lt;BR&gt;Running transformation: T4MVC.tt changed the action method DinnersController.Index to be virtual&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Some people were worried about version control.&amp;nbsp; I tried using TFS, and everything worked fine.&amp;nbsp; i.e. when the template modifies files, VS automatically checks them out.&amp;nbsp; We’ll need to see how that works for folks using different systems.&lt;/P&gt;
&lt;H2&gt;What’s new in this version?&lt;/H2&gt;
&lt;P&gt;The template on CodePlex (version 2.0.01 at the top of the file) supports what I described in my &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx"&gt;previous post&lt;/A&gt;, plus some new goodies.&lt;/P&gt;
&lt;H3&gt;Refactoring support for action methods&lt;/H3&gt;
&lt;P&gt;One of the big issues before was the lack of refactoring support.&amp;nbsp; e.g. when you wrote:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;RedirectToAction(&lt;SPAN style="COLOR: #2b91af"&gt;MVC&lt;/SPAN&gt;.Dinners.Details(dinner.DinnerID));&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;This looked like a call to you Details controller action, but it was actually an unrelated method by the same name.&amp;nbsp; Hence, if you renamed your action method and refactored, this call was not modified.&amp;nbsp; It would give a compile error, and had to be hand fixed.&lt;/P&gt;
&lt;P&gt;Now the template takes a drastically different approach:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It extends the controller class &lt;/LI&gt;
&lt;LI&gt;It overrides the action method (hence the need for it to be virtual!) &lt;/LI&gt;
&lt;LI&gt;The override never calls the base (that would be very wrong), but instead returns a special ActionResult which captures the call (controller name, action name, parameter value). &lt;/LI&gt;
&lt;LI&gt;The template emit a new RedirectToAction (or ActionLink, …) overload which understands this special ActionResults, and turns the call data into a ‘regular’ RedirectToAction call. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Pretty tricky stuff, but it works quite well.&amp;nbsp; Some credit to my manager Mike Montwill for coming up with this crazy idea!&lt;/P&gt;
&lt;P&gt;Because the method you call is an override of the real action method, refactoring works perfectly.&amp;nbsp; Also, if you F12 (Go To Definition) on the call, it’ll go straight to your Action method and not some generated code.&lt;/P&gt;
&lt;P&gt;Unfortunately, Visual Studio doesn’t support refactoring in Views, but 3&lt;SUP&gt;rd&lt;/SUP&gt; party tools like Resharper and CodeRush do, so if you use one of those, you’re fully covered.&lt;/P&gt;
&lt;H3&gt;The T4 file automatically runs whenever you build&lt;/H3&gt;
&lt;P&gt;This was the other big painful issue I was up against: every time you made a change to your code that affect the generated code (e.g. new Action, new View, …), you had to manually save the .tt file to cause it to regenerate the new helper code.&lt;/P&gt;
&lt;P&gt;This was a really hard issue, and I must warn you that what I ended up with is more of a workaround than a fix.&amp;nbsp; However, it is pretty effective, so until we find a better solution, it’ll have to do.&lt;/P&gt;
&lt;P&gt;Here is how it works.&amp;nbsp; Warning: reading this has been shown to cause headaches in lab rats:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;As part of its execution, the T4 file finds itself in the VS project system (it had to do that anyway) &lt;/LI&gt;
&lt;LI&gt;It then runs the magic instruction ‘&lt;EM&gt;projectItem.Document.Saved = false;&lt;/EM&gt;’, which causes it to become dirty. &lt;/LI&gt;
&lt;LI&gt;It then proceeds to do its code generation, leaving its file in an unsaved state &lt;/LI&gt;
&lt;LI&gt;Next time you Build your project, VS first saves all the files &lt;/LI&gt;
&lt;LI&gt;This causes the ‘dirty’ T4 template to execute, mark itself as dirty again, and redo its code generation &lt;/LI&gt;
&lt;LI&gt;You get the idea!&amp;nbsp; If you feel like the lab rats, &lt;A href="http://www.tylenol.com/" mce_href="http://www.tylenol.com/"&gt;this may help&lt;/A&gt;. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;One caveat is that you have to initiate the cycle by opening and saving T4MVC.tt once.&amp;nbsp; After you do that, you don’t need to worry about it.&lt;/P&gt;
&lt;H3&gt;Support for strongly typed links to static resources&lt;/H3&gt;
&lt;P&gt;Credit for this idea goes to Jaco Pretorius, who &lt;A href="http://www.jacopretorius.net/2009/06/generating-strongly-typed-content-links.html" mce_href="http://www.jacopretorius.net/2009/06/generating-strongly-typed-content-links.html"&gt;blogged something similar&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;The template generates static helpers for your content files and script files.&amp;nbsp; So instead of writing:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;img &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;src&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/Content/nerd.jpg" /&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;You can now write:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;img &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;src&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;= Links.Content.nerd_jpg &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;" /&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;Likewise, instead of&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;script &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;src&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/Scripts/Map.js" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;type&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="text/javascript"&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;script&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;You can write:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;script &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;src&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;= Links.Scripts.Map_js &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;type&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="text/javascript"&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;script&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;The obvious benefit is that you’ll get a compile error if you ever move or rename your static resource, so you’ll catch it earlier.&lt;/P&gt;
&lt;P&gt;Another benefit is that you get a more versatile reference.&amp;nbsp; When you write &lt;SPAN style="COLOR: red"&gt;src&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/Content/nerd.jpg"&lt;/SPAN&gt;, your app will only work when it’s deployed at the root of the site.&amp;nbsp; But when you use the helper, it executes some server side logic that makes sure your reference is correct wherever your site is rooted.&amp;nbsp; It does this by calling VirtualPathUtility.ToAbsolute("~/Content/nerd.jpg").&lt;/P&gt;
&lt;P&gt;One unfortunate thing is that for some reason, VS doesn’t support intellisense in the view for parameter values.&amp;nbsp; As a workaround, you can type it outside of the tag to get intellisense and then copy it there.&lt;/P&gt;
&lt;H3&gt;More consistent short form to refer to a View from a Controller class&lt;/H3&gt;
&lt;P&gt;Previously, it supported an _ based short form inside the controller:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;View(View_InvalidOwner);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;That was a bit ugly.&amp;nbsp; Now, the short form is:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;View(Views.InvalidOwner);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Here, Views.InvalidOwner is the same as MVC.Dinners.Views.InvalidOwner, but can be shortened because ‘Views’ is a property on the controller.&lt;/P&gt;
&lt;H3&gt;Many bug fixes&lt;/H3&gt;
&lt;P&gt;I also fixed a number of bugs that people reported and that I ran into myself, e.g.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It supports controllers that are in sub-folders of the Controllers folder and not directly in there &lt;/LI&gt;
&lt;LI&gt;It works better with nested solution folder &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I’m sure there are still quite a few little bugs, and we’ll work through them as we encounter them&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9805709" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>Mind if my MVC T4 template changes your code a bit?</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/24/mind-if-my-mvc-t4-template-changes-your-code-a-bit.aspx</link><pubDate>Thu, 25 Jun 2009 09:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9803014</guid><dc:creator>davidebb</dc:creator><slash:comments>40</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9803014.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9803014</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9803014</wfw:comment><description>&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Update&lt;/FONT&gt;&lt;/STRONG&gt;: Please see &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;this post&lt;/A&gt; for what came out of this ‘poll’, and for a pointer to the newest T4 template on CodePlex.&lt;/P&gt;
&lt;P&gt;When working on my &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx"&gt;MVC T4 template&lt;/A&gt;, I was not able to use reflection to discover the Controllers and Actions, because the code that the template generates is itself in the same assembly as the controllers.&amp;nbsp; So that causes a bit of a chicken and egg problem.&lt;/P&gt;
&lt;P&gt;Instead, I had to get out of my element and learn something I was not familiar with: the Visual Studio File Code Model API.&amp;nbsp; It’s very different from using reflection, because instead of working at the assembly level, you work at the source file level.&lt;/P&gt;
&lt;P&gt;You have to first locate the source file you want to look into.&amp;nbsp; You can then ask for the namespaces that it contains, and the classes that they contain, and finally the various members in those classes.&amp;nbsp; To be honest, I find this API quite ugly.&amp;nbsp; It’s a COM interop thing with a horrible object model that looks like it grew organically from version to version rather than having been designed with usability in mind.&amp;nbsp; So all in all, I used it because I had to, but the whole time I was wishing I could use reflection instead.&lt;/P&gt;
&lt;P&gt;But then I made an important realization.&amp;nbsp; Ugly as it is, this object model supports something that would never be possible with reflection: &lt;STRONG&gt;it lets me modify the source code!&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you look at my previous post, I wrote “&lt;EM&gt;But to make things even more useful in the controller, you can let the T4 template generate new members directly into your controller class.&amp;nbsp; To allow this, you just need to make you controller partial&lt;/EM&gt;”.&amp;nbsp; And I have logic in the template that tests this, and does extra generation if it is partial, e.g.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(type.ClassKind == &lt;SPAN style="COLOR: #2b91af"&gt;vsCMClassKind&lt;/SPAN&gt;.vsCMClassKindPartialClass) { ... }&lt;/PRE&gt;
&lt;P&gt;But instead, I have now realized that I can turn this check into an assignment, and change the class to partial if it isn’t already!&lt;/P&gt;&lt;PRE class=code&gt;type.ClassKind = &lt;SPAN style="COLOR: #2b91af"&gt;vsCMClassKind&lt;/SPAN&gt;.vsCMClassKindPartialClass;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Likewise, I have scenarios where I can do cool things if the Controller actions are virtual, and I can just change them to be with a simple line:&lt;/P&gt;&lt;PRE class=code&gt;method.CanOverride = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;To be clear, those statements actually modify the original source file, the one that you wrote.&amp;nbsp; While this is certainly powerful and opens up some new doors, it also raises a big question which is the main purpose of this post:&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Do you mind if the T4 template makes these small changes to your code?&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;We’re only talking about pretty harmless things (making classes partial and methods virtual), but I know developers can get nervous if even small changes magically happen in their source files.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;So please tell me how you feel about this&lt;/STRONG&gt;, e.g. is it more:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;It’s harmless, go for it if it makes the template more useful &lt;/LI&gt;
&lt;LI&gt;Undecided. I don’t really like it, but maybe I’ll put up with it. &lt;/LI&gt;
&lt;LI&gt;No way I’ll use this template if it messes with my files in any way. I may even sue you! &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Tell me where you stand, and please don't sue me.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9803014" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item><item><title>A new and improved ASP.NET MVC T4 template</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/17/a-new-and-improved-asp-net-mvc-t4-template.aspx</link><pubDate>Wed, 17 Jun 2009 18:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9769641</guid><dc:creator>davidebb</dc:creator><slash:comments>40</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9769641.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9769641</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9769641</wfw:comment><description>&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Update&lt;/FONT&gt;&lt;/STRONG&gt;: Please read &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;this post&lt;/A&gt; for the newest and greatest.&lt;/P&gt;
&lt;P&gt;A couple weeks ago, I blogged about &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx"&gt;using a Build provider and CodeDom&lt;/A&gt; to generate strongly typed MVC helpers at runtime.&amp;nbsp; I followed up a few days later with &lt;A href="http://blogs.msdn.com/davidebb/archive/2009/06/04/a-t4-based-approach-to-creating-asp-net-mvc-strongly-typed-helpers.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/2009/06/04/a-t4-based-approach-to-creating-asp-net-mvc-strongly-typed-helpers.aspx"&gt;another version that used T4 templates&lt;/A&gt; instead, making it easier to customize.&lt;/P&gt;
&lt;P&gt;And now I’m back with yet another post on this topic, but this time with a much simpler and improved approach!&amp;nbsp; The big difference is that I’m now doing the generation at design time instead of runtime.&amp;nbsp; As you will see, this has a lot of advantages.&lt;/P&gt;
&lt;H2&gt;Drawbacks of the previous runtime approach&lt;/H2&gt;
&lt;P&gt;Before we go and re-invent the wheel, let’s discuss what the issues with the runtime T4 approach were, and how this is solved by this new approach.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Complex configuration&lt;/STRONG&gt;: to enable the runtime template, you had to add a DLL to your bin, modify two web.config files, and drop two T4 files in different places.&amp;nbsp; Not super hard, but also not completely trivial.&amp;nbsp; By contrast, with this new approach you just drop one .tt file at the root of your app, and that’s basically it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;No partial trust support&lt;/STRONG&gt;: because it was processing T4 files at runtime, it needed full trust to run.&amp;nbsp; Not to mention the fact that using T4 at runtime is not really supported!&amp;nbsp; But now, by doing it at design time, this becomes a non-issue.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Only works for Views&lt;/STRONG&gt;: because only the Views are compiled at runtime, the helpers were only usable there, and the controllers were left out (since they’re built at design time).&amp;nbsp; With this new approach, Controllers get some love too, because the code generated by the template lives in the same assembly as the controllers!&lt;/P&gt;
&lt;H2&gt;Let’s try the new T4 template with the Nerd Dinner app&lt;/H2&gt;
&lt;P&gt;Let’s jump right in and see this new template in action!&amp;nbsp; We’ll be using the Nerd Dinner app as a test app to try it on.&amp;nbsp; So to get started, go to &lt;A title=http://nerddinner.codeplex.com/ href="http://nerddinner.codeplex.com/" mce_href="http://nerddinner.codeplex.com/"&gt;http://nerddinner.codeplex.com/&lt;/A&gt;, download the app and open it in Visual Studio 2008 SP1.&lt;/P&gt;
&lt;P&gt;Then, simply drag the T4 template (the latest one is on &lt;A href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471"&gt;CodePlex&lt;/A&gt;) into the root of the NerdDinner project in VS.&amp;nbsp; And that’s it, you’re ready to go and use the generated helpers!&lt;/P&gt;
&lt;P&gt;Once you’ve dragged the template, you should see this in your solution explorer:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/MvcJedi_127EF/image_d417b977-3d4c-4d3c-88e6-438b7a32582c.png" width=186 height=96 mce_src="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/MvcJedi_127EF/image_d417b977-3d4c-4d3c-88e6-438b7a32582c.png"&gt; &lt;/P&gt;
&lt;P&gt;Note how a .cs file was instantly generated from it.&amp;nbsp; It contains all the cool helpers we’ll be using!&amp;nbsp; Now let’s take a look at what those helpers let us do.&lt;/P&gt;
&lt;H3&gt;Using View Name constants&lt;/H3&gt;
&lt;P&gt;Open the file Views\Dinners\Edit.aspx.&amp;nbsp; It contains:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt; Html.RenderPartial(&lt;SPAN style="COLOR: #a31515"&gt;"DinnerForm"&lt;/SPAN&gt;); &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;This ugly “DinnerForm” literal string needs to go!&amp;nbsp; Instead, you can now write:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt; Html.RenderPartial(MVC.&lt;SPAN style="COLOR: #2b91af"&gt;Dinners&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #2b91af"&gt;Views&lt;/SPAN&gt;.DinnerForm); &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;Though it’s wordier, note that you get full intellisense when typing it. 
&lt;H3&gt;ActionLink helpers&lt;/H3&gt;
&lt;P&gt;Now open Views\Dinners\EditAndDeleteLinks.ascx, where you’ll see:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;= &lt;/SPAN&gt;Html.ActionLink(&lt;SPAN style="COLOR: #a31515"&gt;"Delete Dinner"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Delete"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ id = Model.DinnerID })&lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Here we not only have a hard coded Action Name (“Delete”), but we also have the parameter name ‘id’.&amp;nbsp; Even though it doesn’t look like a literal string, it very much is one in disguise.&amp;nbsp; Don’t let those anonymous objects fool you!&lt;/P&gt;
&lt;P&gt;But with our cool T4 helpers, you can now change it to:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;= &lt;/SPAN&gt;Html.ActionLink(&lt;SPAN style="COLOR: #a31515"&gt;"Delete Dinner"&lt;/SPAN&gt;, MVC.&lt;SPAN style="COLOR: #2b91af"&gt;Dinners&lt;/SPAN&gt;.Delete(Model.DinnerID))&lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;Basically, we got rid of the two unwanted literal strings (“Delete” and “Id”), and replaced them by a very natural looking method call to the controller action.&amp;nbsp; Of course, this is not really calling the controller action, which would be very wrong here.&amp;nbsp; But it’s capturing the essence of method call, and turning it into the right route values.&amp;nbsp; And again, you get full intellisense:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/MvcJedi_127EF/image_46584000-6b2a-437e-97d3-fd756f67577a.png" width=518 height=228 mce_src="http://blogs.msdn.com/blogfiles/davidebb/WindowsLiveWriter/MvcJedi_127EF/image_46584000-6b2a-437e-97d3-fd756f67577a.png"&gt; &lt;/P&gt;
&lt;P&gt;By the way, feel free to press F12 on this Delete() method call, and you’ll see exactly how it is defined in the generated .cs file.&amp;nbsp; The T4 template doesn’t keep any secrets from you!&lt;/P&gt;
&lt;P&gt;Likewise, the same thing works for Ajax.ActionLink.&amp;nbsp; In Views\Dinners\RSVPStatus.ascx, change:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;= &lt;/SPAN&gt;Ajax.ActionLink( &lt;SPAN style="COLOR: #a31515"&gt;"RSVP for this event"&lt;/SPAN&gt;,
                     &lt;SPAN style="COLOR: #a31515"&gt;"Register"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"RSVP"&lt;/SPAN&gt;,
                     &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ id=Model.DinnerID }, 
                     &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AjaxOptions &lt;/SPAN&gt;{ UpdateTargetId=&lt;SPAN style="COLOR: #a31515"&gt;"rsvpmsg"&lt;/SPAN&gt;, OnSuccess=&lt;SPAN style="COLOR: #a31515"&gt;"AnimateRSVPMessage" &lt;/SPAN&gt;}) &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;to just:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: #ffee62"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;= &lt;/SPAN&gt;Ajax.ActionLink( &lt;SPAN style="COLOR: #a31515"&gt;"RSVP for this event"&lt;/SPAN&gt;,
                     MVC.&lt;SPAN style="COLOR: #2b91af"&gt;RSVP&lt;/SPAN&gt;.Register(Model.DinnerID),
                     &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AjaxOptions &lt;/SPAN&gt;{ UpdateTargetId=&lt;SPAN style="COLOR: #a31515"&gt;"rsvpmsg"&lt;/SPAN&gt;, OnSuccess=&lt;SPAN style="COLOR: #a31515"&gt;"AnimateRSVPMessage" &lt;/SPAN&gt;}) &lt;SPAN style="BACKGROUND: #ffee62"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;You can also do the same thing for Url.Action().&lt;/P&gt;
&lt;H3&gt;Even the controller gets a piece of the action&lt;/H3&gt;
&lt;P&gt;As mentioned earlier, Controllers are no longer left out with this approach.&lt;/P&gt;
&lt;P&gt;e.g. in Controllers\DinnersController.cs, you can replace&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;View(&lt;SPAN style="COLOR: #a31515"&gt;"InvalidOwner"&lt;/SPAN&gt;);&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;by&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;View(MVC.&lt;SPAN style="COLOR: #2b91af"&gt;Dinners&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #2b91af"&gt;Views&lt;/SPAN&gt;.InvalidOwner);&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;But to make things even more useful in the controller, you can let the T4 template generate new members directly into your controller class.&amp;nbsp; To allow this, you just need to make you controller partial, e.g.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public &lt;STRONG&gt;partial&lt;/STRONG&gt; class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DinnersController &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;STRONG&gt;Note&lt;/STRONG&gt;: you now need to tell the T4 template to regenerate its code, by simply opening the .tt file and saving it.&amp;nbsp; I know, it would ideally be automatic, but I haven’t found a great way to do this yet.&lt;/P&gt;
&lt;P&gt;After you do this, you can replace the above statement by the more concise:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;View(View_InvalidOwner);&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;You also get to do some cool things like we did in the Views.&amp;nbsp; e.g. you can replace:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;RedirectToAction(&lt;SPAN style="COLOR: #a31515"&gt;"Details"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ id = dinner.DinnerID });&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;by&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;RedirectToAction(MVC.&lt;SPAN style="COLOR: #2b91af"&gt;Dinners&lt;/SPAN&gt;.Details(dinner.DinnerID));&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;How does the T4 template work?&lt;/H2&gt;
&lt;P&gt;The previous runtime-based T4 template was using reflection to learn about your controllers and actions.&amp;nbsp; But now that it runs at design time, it can’t rely on the assembly already being built, because the code it generates is part of that very assembly (yes, a chicken and egg problem of sort).&lt;/P&gt;
&lt;P&gt;So I had to find an alternative.&amp;nbsp; Unfortunately, I was totally out of my element, because my expertise is in the runtime ASP.NET compilation system, while I couldn’t make use of any of it here!&lt;/P&gt;
&lt;P&gt;Luckily, I connected with a few knowledgeable folks who gave me some good pointers.&amp;nbsp; I ended up using the VS File Code Model API.&amp;nbsp; It’s an absolutely horrible API (it’s COM interop based), but I had to make the best of it.&lt;/P&gt;
&lt;P&gt;The hard part is that it doesn’t let you do simple things that are easy using reflection.&amp;nbsp; e.g. you can’t easily find all the controllers in your project assembly.&amp;nbsp; Instead, you have to ask it to give you the code model for a given source file, and in there you can discover the namespaces, types and methods.&lt;/P&gt;
&lt;P&gt;So in order to make this work without having to look at all the files in the projects (which would be quite slow, since it’s a slow API), I made an assumption that the Controller source files would be in the Controllers folder, which is where they normally are.&lt;/P&gt;
&lt;P&gt;As for the view, I had to write logic that enumerates the files in the Views folder to discover the available views.&lt;/P&gt;
&lt;P&gt;All in all, it’s fairly complex and messy code, which hopefully others won’t have to rewrite from scratch.&amp;nbsp; Just open the .tt file to look at it, it’s all in there!&lt;/P&gt;
&lt;P&gt;In addition to looking at the .tt file, I encourage you to look at the generated .cs file, which will show you all the helpers for your particular project.&lt;/P&gt;
&lt;H2&gt;Known issues&lt;/H2&gt;
&lt;H3&gt;T4 file must be saved to regenerate the code&lt;/H3&gt;
&lt;P&gt;This was briefly mentioned above.&amp;nbsp; The T4 generation is done by VS because there is a custom tool associated with it (the tool is called TextTemplatingFileGenerator – you can see it in the properties).&amp;nbsp; But VS only runs the file generator when the .tt file changes.&amp;nbsp; So when you make code changes that would affect the generated code (e.g. add a new Controller), you need to explicitly resave the .tt file to update the generated code.&amp;nbsp; As an alternative, you can right click on the .tt file and choose “Run Custom Tool”, though that’s not much easier.&lt;/P&gt;
&lt;P&gt;Potentially, we could try doing something that reruns the generation as part of a build action or something like that.&amp;nbsp; I just haven’t had time to play around with this.&amp;nbsp; Let me know if you find a good solution to this.&lt;/P&gt;
&lt;H3&gt;No refactoring support&lt;/H3&gt;
&lt;P&gt;This was also the case with the previous template, but it is worth pointing out.&amp;nbsp; Because all the code is generated by the T4 template, that code is not directly connected to the code it relates to.&lt;/P&gt;
&lt;P&gt;e.g. the MVC.Dinners.Delete() generated method results from the DinnersController.Delete() method, but they are not connected in a way that the refactoring engine can deal with.&amp;nbsp; So if you rename DinnersController.Delete() to DinnersController.Delete2(), MVC.Dinners.Delete() won’t be refactored to MVC.Dinners.Delete2().&lt;/P&gt;
&lt;P&gt;Of course, if you resave the .tt file, it will generate a MVC.Dinners.Delete2() method instead of MVC.Dinners.Delete(), but places in your code that call MVC.Dinners.Delete() won’t be renamed to Delete2.&lt;/P&gt;
&lt;P&gt;While certainly a limitation, it is still way superior to what it replaces (literal strings), because it gives you both intellisense and compile time check.&amp;nbsp; But it’s just not able to take that last step that allows refactoring to work.&lt;/P&gt;
&lt;P&gt;It is worth noting that using Lamda expression based helpers instead of T4 generation does solve this refactoring issue, but it comes with a price: less natural syntax, and performance issues.&lt;/P&gt;
&lt;H2&gt;Final words&lt;/H2&gt;
&lt;P&gt;It has been pretty interesting for me to explore those various alternative to solve this MVC strongly typed helper issue.&amp;nbsp; Though I started out feeling good about the runtime approach, I’m now pretty sold on this new design time approach being the way to go.&lt;/P&gt;
&lt;P&gt;I’d be interested in hearing what others think, and about possible future directions where we can take this.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9769641" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidebb/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4MVC/default.aspx">T4MVC</category></item></channel></rss>