<?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 : MVC</title><link>http://blogs.msdn.com/davidebb/archive/tags/MVC/default.aspx</link><description>Tags: MVC</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Passing anonymous objects to MVC views and accessing them using dynamic</title><link>http://blogs.msdn.com/davidebb/archive/2009/12/18/passing-anonymous-objects-to-mvc-views-and-accessing-them-using-dynamic.aspx</link><pubDate>Sat, 19 Dec 2009 00:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9938997</guid><dc:creator>davidebb</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9938997.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9938997</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9938997</wfw:comment><description>&lt;P&gt;First, I’ll start with a little disclaimer: this post is not about whether using dynamic is better/worse than static typing.&amp;nbsp; Instead, it’s about making it more convenient to use dynamic &lt;STRONG&gt;if you choose to go that route&lt;/STRONG&gt;.&amp;nbsp; Clearly, some people dislike dynamic, as you can see in the comments in that &lt;A href="http://haacked.com/archive/2009/08/26/method-missing-csharp-4.aspx" mce_href="http://haacked.com/archive/2009/08/26/method-missing-csharp-4.aspx"&gt;post from Phil Haack&lt;/A&gt;, and for the most part, all the key arguments for/against have been made.&lt;/P&gt;
&lt;P&gt;So anyway, let’s proceed… Recently, a few people have experimented with extending their view pages from ViewPage&amp;lt;dynamic&amp;gt;.&amp;nbsp; The idea is to then be able to access model data using the more convenient dynamic syntax.&amp;nbsp; e.g. check out &lt;A href="http://stackoverflow.com/questions/1178984/dynamic-typed-viewpage" mce_href="http://stackoverflow.com/questions/1178984/dynamic-typed-viewpage"&gt;this thread&lt;/A&gt; on StackOverflow, as well as Phil’s post I mention above.&lt;/P&gt;
&lt;P&gt;One limitation that people are hitting is that you can’t easily pass an anonymous object as your model, because anonymous types are internal.&lt;/P&gt;
&lt;H3&gt;What we’re trying to write&lt;/H3&gt;
&lt;P&gt;e.g. Let’s say we’re trying to write this code in the controller:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;public class HomeController : Controller {
    public ActionResult Index() {
        return View(
            new {
                Message = "Welcome to ASP.NET MVC!",
                Date = DateTime.Now
            });
    }
}&lt;/PRE&gt;
&lt;P&gt;Note that we’re passing an anonymous object as the model.&amp;nbsp; The main reason to do this is to avoid the need to create an explicit ViewModel type.&amp;nbsp; Obviously, that’s controversial, but it should be viewed more as a simpler alternative to writing&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;ViewData["Message"] = "Welcome to ASP.NET MVC!";
ViewData["Date"] = DateTime.Now;
return View();&lt;/PRE&gt;
&lt;P&gt;And then you’d change your view to have Inherits="System.Web.Mvc.ViewPage&amp;lt;dynamic&amp;gt;", which ideally would let you write something like this:&lt;/P&gt;&lt;PRE class="brush: xml;"&gt;&amp;lt;asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"&amp;gt;
    &amp;lt;h2&amp;gt;&amp;lt;%: Model.Message %&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;
        The date is &amp;lt;%: Model.Date %&amp;gt;
    &amp;lt;/p&amp;gt;
&amp;lt;/asp:Content&amp;gt;&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Which is simpler than having to dig things out of the view data dictionary through string indexing.&lt;/P&gt;
&lt;H3&gt;But the default dynamic binder won’t let us!&lt;/H3&gt;
&lt;P&gt;Unfortunately, if you try to run this code, it’ll blow up with this error: &lt;FONT color=#ff0000&gt;Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: '&amp;lt;&amp;gt;f__AnonymousType1&amp;lt;string,System.DateTime&amp;gt;.Message' is inaccessible due to its protection level&lt;/FONT&gt; &lt;/P&gt;
&lt;P&gt;The reason for this is that the anonymous type being passed in the controller in internal, so it can only be accessed from within the assembly in which it’s declared.&amp;nbsp; Since views get compiled separately, the dynamic binder complains that it can’t go over that assembly boundary.&lt;/P&gt;
&lt;P&gt;But if you think about it, this restriction from the dynamic binder is actually quite artificial, because if you use private reflection, nothing is stopping you from accessing those internal members (yes, it even work in Medium trust).&amp;nbsp; So the default dynamic binder is going out of its way to enforce C# compilation rules (where you can’t access internal members), instead of letting you do what the CLR &lt;STRONG&gt;runtime&lt;/STRONG&gt; allows.&lt;/P&gt;
&lt;H3&gt;Solution: write our own!&lt;/H3&gt;
&lt;P&gt;I’m not sure why it was designed this way, but the good news is that it’s easy to work around by writing our own custom DynamicObject which binds through private reflection!&amp;nbsp; I’ve written a couple posts that make use of custom DynamicObjects (find them &lt;A href="http://blogs.msdn.com/davidebb/archive/tags/Dynamic/default.aspx" mce_href="http://blogs.msdn.com/davidebb/archive/tags/Dynamic/default.aspx"&gt;here&lt;/A&gt;), and the basic concept is the same: given the name of a property, write whatever code you want to produce its value.&lt;/P&gt;
&lt;P&gt;Here, we’re not only going to write a custom Dynamic Object, but also a custom DynamicViewPage that uses it.&amp;nbsp; And doing all this takes surprisingly little code.&amp;nbsp; Here is the full implementation:&lt;/P&gt;&lt;PRE class="brush: csharp;"&gt;public class DynamicViewPage : ViewPage {
    // Hide the base Model property and replace it with a dynamic one
    public new dynamic Model { get; private set; }

    protected override void SetViewData(ViewDataDictionary viewData) {
        base.SetViewData(viewData);

        // Create a dynamic object that can do private reflection over the model object
        Model = new ReflectionDynamicObject() { RealObject = ViewData.Model };
    }

    class ReflectionDynamicObject : DynamicObject {
        internal object RealObject { get; set; }

        public override bool TryGetMember(GetMemberBinder binder, out object result) {
            // Get the property value
            result = RealObject.GetType().InvokeMember(
                binder.Name,
                BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                RealObject,
                null);

            // Always return true, since InvokeMember would have thrown if something went wrong
            return true;
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;As you can see there is not that much to it: when we need to look up a property value, we use private reflection and that’s the end of it.&lt;/P&gt;
&lt;H3&gt;And now it all works!&lt;/H3&gt;
&lt;P&gt;Once we have this, all that’s left to do is use it as our base class for the view, e.g.&lt;/P&gt;&lt;PRE class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="MvcHelpers.DynamicViewPage" %&amp;gt;&lt;/PRE&gt;
&lt;P&gt;And we’re then able to write exactly what we wanted above in the controller and the view, without hitting any access issues.&lt;/P&gt;
&lt;P&gt;The full VS2010 project is attached to this post.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9938997" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9938997.ashx" length="246204" 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/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/Dynamic/default.aspx">Dynamic</category></item><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>13</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>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>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>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><item><title>A T4 based approach to creating ASP.NET MVC strongly typed helpers</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/04/a-t4-based-approach-to-creating-asp-net-mvc-strongly-typed-helpers.aspx</link><pubDate>Fri, 05 Jun 2009 09:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9700905</guid><dc:creator>davidebb</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9700905.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9700905</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9700905</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"&gt;this newer post&lt;/a&gt; for the latest and greatest MVC T4 template&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Earlier this week, I wrote a post on &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx"&gt;using a BuildProvider to create ActionLink helpers&lt;/a&gt;.&amp;#160; That approach was using CodeDom to generate the code, and there was quite some user interest in it (and &lt;a href="http://haacked.com/archive/2009/06/02/alternative-to-expressions.aspx"&gt;Phil blogged it&lt;/a&gt;, which helped!).&lt;/p&gt;  &lt;p&gt;Then yesterday, I wrote a post on &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/03/codedom-vs-t4-two-approaches-to-code-generation.aspx"&gt;the Pros and Cons of using CodeDom vs T4 templates for source code generation&lt;/a&gt;.&amp;#160; They are drastically different approaches, and while both have their strengths, T4 has definitely been getting more buzz lately.&lt;/p&gt;  &lt;p&gt;The logical follow-up to those two posts is a discussion on using T4 templates to generate MVC strongly typed helpers.&amp;#160; The general idea here is to use the existing ASP.NET extensibility points (BuildProvider and ControlBuilder), but rely on T4 templates to produce code instead of CodeDom.&amp;#160; Hence, I called the helper library AspNetT4Bridge (I’m really good at naming things!).&lt;/p&gt;  &lt;p&gt;As far as I know, this is the first time that T4 templates are executed dynamically inside an ASP.NET application, so let’s view this as an experiment, which has really not been put to the test yet.&amp;#160; But it is certainly an exciting approach, so let’s see where it takes us!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;What scenarios are we enabling&lt;/h2&gt;  &lt;p&gt;Before we get too far into the technical details, let’s look at the various MVC scenarios that this is enabling.&amp;#160; But the great thing to keep in mind is that since T4 templates are so flexible, it is very easy to tweak the generated code or add additional scenarios.&amp;#160; Hence it is best to view those scenarios as examples of the type of things that you can achieve with this model, rather than as a final end result.&lt;/p&gt;  &lt;h3&gt;ActionLink helpers&lt;/h3&gt;  &lt;p&gt;First, we have the same scenario that my &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx"&gt;previous post&lt;/a&gt; covered, except that we’re now using T4 instead of CodeDom.&amp;#160; Instead of writing:&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;&amp;quot;Edit&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Edit&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;{ id = item.ID })&lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;You can write the more strongly typed (here, ‘Test’ is the name of the controller):&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.ActionLinkToTestEdit(&lt;span style="color: #a31515"&gt;&amp;quot;Edit&amp;quot;&lt;/span&gt;, item.ID) &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;And note that you get full intellisense in VS for those helpers!&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/AT4basedapproachtocreatingMVCstronglytyp_C7A4/image_7.png" width="411" height="228" /&gt; &lt;/p&gt;

&lt;h3&gt;Action Url helpers&lt;/h3&gt;

&lt;p&gt;This is similar to the previous section, except it covers the case where you need to generate raw URL’s rather than HTML &amp;lt;a&amp;gt; tags.&amp;#160; Instead of writing:&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;Url.Action(&lt;span style="color: #a31515"&gt;&amp;quot;Edit&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;{ id = item.ID }) &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;You can write:&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;Url.UrlToTestEdit(item.ID) &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h3&gt;Constants for View Names&lt;/h3&gt;

&lt;p&gt;That’s another case where you often end up hard coding view names as literal string, e.g.&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;&amp;quot;LogOnUserControl&amp;quot;&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"&gt;&lt;/a&gt;With the generated helpers, you get to write:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt; Html.RenderPartial(Views.&lt;span style="color: #2b91af"&gt;Shared&lt;/span&gt;.LogOnUserControl); &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;And again, you get full intellisense:&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/AT4basedapproachtocreatingMVCstronglytyp_C7A4/image_899167cb-ef7c-4847-a44a-c7c2313764c0.png" width="349" height="137" /&gt;&lt;/p&gt;

&lt;h3&gt;Rendering helpers for strongly typed views&lt;/h3&gt;

&lt;p&gt;Assume you are using a strongly typed view.&amp;#160; You might write something like this (which is what the View wizard generates by default):&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;label &lt;/span&gt;&lt;span style="color: red"&gt;for&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Name&amp;quot;&amp;gt;&lt;/span&gt;Name:&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;label&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;Html.TextBox(&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, Model.Name) &lt;span style="background: #ffee62"&gt;%&amp;gt;
&lt;/span&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;Html.ValidationMessage(&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;*&amp;quot;&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"&gt;&lt;/a&gt;

&lt;p&gt;With the helpers, you can instead write:&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;ViewModel.Name.Label() &lt;span style="background: #ffee62"&gt;%&amp;gt;
&lt;/span&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;ViewModel.Name.TextBox() &lt;span style="background: #ffee62"&gt;%&amp;gt;
&lt;/span&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;ViewModel.Name.Validation() &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Here ViewModel is some name I came up with (well, &lt;a href="http://twitter.com/davidfowl"&gt;Fowler&lt;/a&gt; did!) as the class that holds the helpers.&amp;#160; There may be better names for it!&lt;/p&gt;

&lt;p&gt;Note that the helpers can be smart about what they offer based on the data type.&amp;#160; e.g. for a boolean field, you typically want a check box instead of a text box, and the helpers account for this:&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/AT4basedapproachtocreatingMVCstronglytyp_C7A4/image_3212c937-5041-4fe3-8e6c-27893e9b0095.png" width="304" height="167" /&gt;&lt;/p&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;h2&gt;What do you need to do to enable this in your MVC app?&lt;/h2&gt;

&lt;p&gt;There are five relatively straightforward steps you need to take to enable this.&lt;/p&gt;

&lt;p&gt;1. Copy AspNetT4Bridge.dll into the bin folder of your app (you’ll get it by building the attached sample).&lt;/p&gt;

&lt;p&gt;2. In the web.config file at the root of your app, register the BuildProvider for .tt files&lt;/p&gt;

&lt;pre class="code"&gt;&lt;p&gt;    &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: blue"&gt;      ...
&lt;/span&gt;&lt;span style="color: blue"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;buildProviders&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;extension&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;.tt&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AspNetT4Bridge.AspNetT4BridgeBuildProvider&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
      &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;buildProviders&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;3. In the web.config in the Views folder (which you didn’t know existed, did you?), change the pageParserFilterType as follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: red"&gt;pageParserFilterType&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AspNetT4Bridge.Mvc.ViewTypeParserFilter&lt;/span&gt;&amp;quot;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;4. Copy the Templates and App_Code folders (each containing a .tt file) from the attached sample app to the root of your app. In VS, blank out the Custom Tool for the .tt files if you see it set to TextTemplatingFileGenerator (see &lt;a href="http://blogs.msdn.com/webdevtools/archive/2009/01/27/overview-of-mvc-tools-features.aspx"&gt;this post&lt;/a&gt; for some details on this).&lt;/p&gt;

&lt;p&gt;5. If you have any strongly typed views (i.e. views the inherit ViewPage&amp;lt;T&amp;gt; and not just ViewPage), you need to change the Inherits attribute from &lt;strong&gt;System.Web&lt;/strong&gt;.Mvc.ViewPage&amp;lt;...&amp;gt; to &lt;strong&gt;AspNetT4Bridge&lt;/strong&gt;.Mvc.ViewPage&amp;lt;...&amp;gt;.&amp;#160; I know that’s a bit ugly, and we can think of ways to clean that up later.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;So what about those T4 templates?&lt;/h2&gt;

&lt;p&gt;This post is supposed to be about using T4 templates, and so far we haven’t said a whole lot about them.&amp;#160; They are certainly the magic piece that makes all this work.&amp;#160; We are actually using two different .tt files, which cover two distinct scenarios:&lt;/p&gt;

&lt;h3&gt;Top level code&lt;/h3&gt;

&lt;p&gt;This applies to generated code that every page is referencing, and is used for the first three scenarios above (Action Links, Urls and View name constants).&amp;#160; The T4 file that does this is App_Code\StrongTypedLinkExtensions.tt.&lt;/p&gt;

&lt;p&gt;As an aside, many people have a misconception that App_Code is just for web &lt;strong&gt;sites&lt;/strong&gt; and not for web &lt;strong&gt;apps&lt;/strong&gt;.&amp;#160; However, while it is rarely used, is is fully available.&amp;#160; It’s built with a reference to the bin assemblies, and all pages are built to a reference to it.&lt;/p&gt;

&lt;p&gt;The way we make App_Code work with T4 templates is that we have a BuildProvider registered for the .tt extension.&amp;#160; This BuildProvider uses its own ITextTemplatingEngineHost in order to process the T4 templates into source code.&amp;#160; It then uses a CodeDom CodeSnippetCompileUnit to wrap this code into something CodeDom understands.&amp;#160; That’s why I called this AspNetT4Bridge, as it really bridges the CodeDom world of ASP.NET with the T4 world.&amp;#160; Fine, you come up with a better name! :)&lt;/p&gt;

&lt;p&gt;Look for this logic in AspNetT4BridgeBuildProvider.cs.&lt;/p&gt;

&lt;h3&gt;Page level code&lt;/h3&gt;

&lt;p&gt;This applies to code that is specific to a given page, and that we just want to inject in there.&amp;#160; This is what’s uses for the view helpers like ViewModel.Name.TextBox() described above.&amp;#160; The T4 file that does this is Templates\MvcHtmlRenderHelpers.tt.&lt;/p&gt;

&lt;p&gt;This works by using a ControlBuilder and its ProcessGeneratedCode method, which I &lt;a href="http://blogs.msdn.com/davidebb/archive/2008/11/19/a-hidden-gem-for-control-builder-writers.aspx"&gt;discussed in a previous post&lt;/a&gt;.&amp;#160; The situation is similar to the App_Code case: we need to come up with some source code, we use T4 to generate it, and we wrap it in a CodeDom construct (in this case it’s a CodeSnippetTypeMember, because the code goes inside the class).&lt;/p&gt;

&lt;p&gt;Look for this logic in T4CodeGenerator.cs.&lt;/p&gt;

&lt;h3&gt;But what the heck is in those T4 templates?&lt;/h3&gt;

&lt;p&gt;So I’ve talked about how they get hooked up and executed, but still haven’t said a word about what’s in them.&amp;#160; Well, I told you where they are, so go ahead and take a look!&amp;#160; e.g. check out App_Code\StrongTypedLinkExtensions.tt.&lt;/p&gt;

&lt;p&gt;There is nothing really hard about how it works, but the mix of genera&lt;strong&gt;tor&lt;/strong&gt; code and genera&lt;strong&gt;ted&lt;/strong&gt; code certainly makes it confusing at first.&amp;#160; Do yourself a favor and install the free &lt;a href="http://www.visualt4.com/downloads.html"&gt;Clarius Community T4 editor&lt;/a&gt;.&amp;#160; It doesn’t do a whole lot, but the fact that it shows the two types of code (genera&lt;strong&gt;tor&lt;/strong&gt; and genera&lt;strong&gt;ted&lt;/strong&gt;) in different color goes a long way to make things clearer.&lt;/p&gt;

&lt;p&gt;The way the Action Links and Url helpers are generated is fairly straightforward:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It gets the list of referenced assemblies from the Host &lt;/li&gt;

  &lt;li&gt;It uses reflection to figure out what types are controllers &lt;/li&gt;

  &lt;li&gt;For each controllers, it finds that Action methods &lt;/li&gt;

  &lt;li&gt;For each Action method, it generates both an ActionLine and a Url helper, custom made for that action method (hence strongly typed). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The View Name Constant helpers are also fairly simple.&amp;#160; They just look at what directories and files are under the Views folder, and generate constants accordingly.&amp;#160; I’ll show this part here as an example:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: gray"&gt;namespace Views {
&lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#
&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt;var viewsDir = HostingEnvironment.VirtualPathProvider.GetDirectory(&amp;quot;~/Views&amp;quot;);
    foreach (VirtualDirectory dir in viewsDir.Directories) {
&lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;
&lt;/span&gt;&lt;span style="color: red"&gt;    &lt;/span&gt;&lt;span style="color: gray"&gt;public static class &lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt; dir.Name &lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: red"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;{
&lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt;      foreach (VirtualFile file in dir.Files) {
            string viewName = Path.GetFileNameWithoutExtension(file.Name);
&lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;
&lt;/span&gt;&lt;span style="color: red"&gt;        &lt;/span&gt;&lt;span style="color: gray"&gt;public const string &lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt; viewName &lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: red"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;= &amp;quot;&lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt; viewName &lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;quot;;
&lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt;      } &lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;
&lt;/span&gt;&lt;span style="color: red"&gt;    &lt;/span&gt;&lt;span style="color: gray"&gt;}
    
&lt;/span&gt;&lt;span style="background: gold"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="background: #f0f8ff; color: #191970"&gt;  } &lt;/span&gt;&lt;span style="background: gold"&gt;#&amp;gt;
&lt;/span&gt;&lt;span style="color: gray"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Go ahead, try changing them!&lt;/h3&gt;

&lt;p&gt;One of the big reason to use T4 over CodeDom for this code generation is to not ‘lock’ the kind of code that get generated into a binary.&amp;#160; Instead, you can very easily tweak it, remove things you don’t care about, and generate entirely new things.&amp;#160; All this really takes is an understanding of &amp;lt;# #&amp;gt; and &amp;lt;#= #&amp;gt; blocks, which is pretty easy when you already know how &amp;lt;% %&amp;gt; and &amp;lt;%= %&amp;gt; blocks work, since they’re pretty much the same thing!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;So here we are, dynamically executing T4 templates at runtime in an ASP.NET app.&amp;#160; One big caveat that I mentioned in my &lt;a href="http://blogs.msdn.com/davidebb/archive/2009/06/03/codedom-vs-t4-two-approaches-to-code-generation.aspx"&gt;previous post&lt;/a&gt; is that you’re not really &lt;em&gt;supposed&lt;/em&gt; to do that!&amp;#160; Copying from there:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;CodeDom is part of the framework, while T4 is not.&amp;#160; That means that if you need to dynamically do this at runtime (as opposed to within VS), then T4 is not really an option.&amp;#160; Technically, it is possible to use it at runtime outside VS, but you either have to run on a machine with VS installed, or you have to copy Microsoft.VisualStudio.TextTemplating.dll into your project (which works, but is not officially supported – hopefully it will be at some point!).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I wrote that it wasn’t an option, and next thing I blog about doing it.&amp;#160; What’s the deal?&amp;#160; Well, there are some things that are changing in VS 2010 that will help.&amp;#160; In particular, they are adding the concept of preprocessing T4 templates, while today you can only fully process them all at once.&amp;#160; With preprocessing, we’ll be able to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Let VS preprocess the T4 templates into some intermediate source code (that itself doesn’t requite the T4 runtime. &lt;/li&gt;

  &lt;li&gt;Run this code at ASP.NET runtime to generate the code we care about and add it to the compilation (e.g. in App_Code as above).&amp;#160; This takes no dependency on the T4 runtime. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another caveat I need to mention is that T4 templates can’t be fully executed in medium trust (because they need to compile code).&amp;#160; However, with the VS 2010 changes, that will no longer be an issue.&lt;/p&gt;

&lt;p&gt;So while in the short term, we are breaking the rules a bit by doing this and there are some tough edges, it demonstrates some very useful concepts that can be fully supported later.&lt;/p&gt;

&lt;p&gt;And if all else fails, I had a lot of fun playing with it all!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9700905" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9700905.ashx" length="44712" 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/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/T4/default.aspx">T4</category></item><item><title>A BuildProvider to simplify your ASP.NET MVC Action Links</title><link>http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx</link><pubDate>Tue, 02 Jun 2009 04:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9683123</guid><dc:creator>davidebb</dc:creator><slash:comments>26</slash:comments><comments>http://blogs.msdn.com/davidebb/comments/9683123.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidebb/commentrss.aspx?PostID=9683123</wfw:commentRss><wfw:comment>http://blogs.msdn.com/davidebb/rsscomments.aspx?PostID=9683123</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"&gt;this newer post&lt;/a&gt; for the latest and greatest MVC T4 template&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;One downside of using Html.ActionLink in your views is that it is late bound.&amp;#160; e.g. say you write something like this:&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;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;)&lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The second parameter is the Action name, and the third is the Controller name.&amp;#160; Note how they are both specified as plain strings.&amp;#160; This means that if you rename either your Controller or Action, you will not catch the issue until you actually run your code and try to click on the link.&lt;/p&gt;

&lt;p&gt;Now let’s take the case where you Action takes parameters, e.g.:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;Test(&lt;span style="color: blue"&gt;int &lt;/span&gt;id, &lt;span style="color: blue"&gt;string &lt;/span&gt;name) {
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View();
}&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;Now your ActionLink calls looks something like this:&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;&amp;quot;Test Link&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;{ id = 17, name = &lt;span style="color: #a31515"&gt;&amp;quot;David&amp;quot; &lt;/span&gt;}, &lt;span style="color: blue"&gt;null&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;So in addition to the Controller and Action names changing, you are vulnerable to the parameter names changing, which again you won’t easily catch until runtime.&lt;/p&gt;

&lt;p&gt;One approach to solving this is to rely on Lambda expressions to achieve strong typing (and hence compile time check).&amp;#160; The MVC Futures project demonstrates this approach.&amp;#160; It certainly has merits, but the syntax&amp;#160; of Lambda expressions in not super natural to most.&lt;/p&gt;

&lt;p&gt;Here, I’m exploring an alternative approach that uses an ASP.NET BuildProvider to generate friendlier strongly typed helpers.&amp;#160; With those helpers,&amp;#160; the two calls below become simply:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;p&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;Html.ActionLinkToHomeIndex(&lt;span style="color: #a31515"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;)&lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;Html.ActionLinkToHomeTest(&lt;span style="color: #a31515"&gt;&amp;quot;Test Link&amp;quot;&lt;/span&gt;, 17, &lt;span style="color: #a31515"&gt;&amp;quot;David&amp;quot;&lt;/span&gt;)&lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Not only is this more concise, but it doesn’t hard code any of the problematic strings discussed above: the Controller and Action names, and the parameter names.&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;

&lt;h3&gt;Steps to enable the ActionLink helpers in your MVC app&lt;/h3&gt;

&lt;p&gt;You can easily integrate these helpers in any ASP.NET MVC app by following three steps:&lt;/p&gt;

&lt;p&gt;1. First, add a reference to MvcActionLinkHelper.dll in your app (build the project&amp;#160; in the zip file attached to this post to get it)&lt;/p&gt;

&lt;p&gt;2. Then, register the build provider in web.config.&amp;#160; Add the following lines in the &amp;lt;compilation&amp;gt; section:&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;buildProviders&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;extension&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;.actions&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;MvcActionLinkHelper.MvcActionLinkBuildProvider&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
      &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;buildProviders&lt;/span&gt;&lt;span style="color: blue"&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;3. The third step is a little funky, but still easy.&amp;#160; You need to create an App_Code folder in your app, and add a file with the .actions extension in it.&amp;#160; It doesn’t matter what’s in the file, or what its full name is.&amp;#160; e.g. add an empty file named App_Code/generate.actions.&amp;#160; This file is used to trigger the BuildProvider.&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;

&lt;h3&gt;How does it all work?&lt;/h3&gt;

&lt;p&gt;I included all the sources in the zip, so feel free to look and debug through it to see how it works.&amp;#160; In a nutshell:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When the first request is made at runtime, ASP.NET needs to build the App_Code assembly &lt;/li&gt;

  &lt;li&gt;It finds our .actions file, which triggers the registered BuildProvider &lt;/li&gt;

  &lt;li&gt;The BuildProvider goes through all the reference assemblies and looks for Controller classes &lt;/li&gt;

  &lt;li&gt;It then generates a static class with extension methods for each action &lt;/li&gt;

  &lt;li&gt;Since every aspx page is built with a reference to the App_Code assembly, all&amp;#160; the views are able to use the generated helpers. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;/h3&gt;

&lt;h3&gt;Where is this going?&lt;/h3&gt;

&lt;p&gt;At this point, this is just a quick proof of concept.&amp;#160; There are certainly other areas of MVC where the same idea can be applied.&amp;#160; e.g. currently it only covers Html.ActionLink, but could equally cover Url.Action(), or HTML form helpers (standard and AJAX).&lt;/p&gt;

&lt;p&gt;Please send feedback whether you find this direction interesting as an alternative to the Lambda expression approach.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9683123" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/davidebb/attachment/9683123.ashx" length="267861" 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/MVC/default.aspx">MVC</category><category domain="http://blogs.msdn.com/davidebb/archive/tags/CodeDom/default.aspx">CodeDom</category></item></channel></rss>