T4MVC Documentation page(转)
转自:http://mvccontrib.codeplex.com/wikipage?title=T4MVC_doc&referringTitle=T4MVC
1. Introduction
T4MVC is a T4 template for ASP.NET MVC apps that creates strongly typed helpers that eliminate the use of literal strings when referring the controllers, actions and views. It helps make your MVC code much more maintainable, and gives you intellisense where you normally would not have any. It was started by David Ebbo as a little blog post thing, and has since gained many new features based on great community feedback.T4MVC runs in both Visual Studio 2008 SP1 and Visual Studio 2010, and supports both ASP.NET MVC 1.0 and 2.0.
To use it, simply download the zip file, and copy both T4MVC.tt and T4MVC.tt.settings.t4 to the root of your MVC application. You should instantly see a number of files get created in Visual Studio under T4MVC.tt.
The code in those generated files enable a whole range of scenarios, all relating to replacing unwanted literal strings with a strongly typed alternative. The documentation below gives a complete list of those scenarios.
2. Scenarios
Instead of a formal documentation, we'll just demonstrate by example the various scenarios where T4MVC helps improve your code. The examples are shown in a before/after format to outline the change that is made.Note: a lot of the examples given below are based on the Nerd Dinner sample MVC application.
2.1 Using View Name constants
Any time you would use a literal string to refer to a view, T4MVC gives you a strongly typed alternative. e.g. suppose you have this code in a view:
<% Html.RenderPartial("DinnerForm"); %>
<% Html.RenderPartial(MVC.Dinners.Views.DinnerForm); %>
When you need to use a view name inside a controller, things get even easier. e.g. you can replace:
return View("InvalidOwner");
return View(Views.InvalidOwner);
Note how you can omit the MVC.Dinners prefix, since this is implied by the fact that the code lives in the Dinners controller.
2.2 Referring to controller actions
Many MVC APIs follow a pattern where you need to pass three pieces of information in order to refer to a controller action:
- the controller name (often implied when dealing with the current controller)
- the action method name
- the parameters to be passed to the action method
All of this is typically done by passing literal strings for #1 and #2, and an anonymous object for #3, e.g.
<%= Html.ActionLink("Delete Dinner", "Delete", "Dinners", new { id = Model.DinnerID }, null)%>
With T4MVC, you would instead write:
<%= Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID))%>
One other great benefit of this approach is that you get full intellisense while you type this line. In fact, you even get full refactoring support if you use a tool like resharper which supports aspx refactoring!
Adding additional route parameters
In some situation, you may need to add extra values to the route that don’t exist in the action method. You can do it as follows:Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID) .AddRouteValue("foo", 17))
You can add multiple values this way using a fluent approach, e.g.
Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID) .AddRouteValue("foo", 17) .AddRouteValue("bar", "abc"))
As an alternative for adding multiple values, you can write:
Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID) .AddRouteValues(new { foo = 17, bar = "abc"}))
Note that in some cases, you may want to omit the action method parameters from the route, possibly because they are meant to come from form data and not from the URL. For those cases, you can always use the parameter-less override that T4MVC generates (that part is not new), e.g.
Html.ActionLink("Delete Dinner", MVC.Dinners.Delete() .AddRouteValues(new { foo = 17, bar = "abc"}))
Now suppose you want to add all the current query string values to the route values produced by T4MVC. You can use the AddRouteValues() overload that takes a NameValueCollection. e.g.
RedirectToAction(MVC.Home.MyAction().AddRouteValues(Request.QueryString));
This adds to the existing set of AddRouteValue/AddRouteValues fluent APIs to make it easier to deal with all kind different situations.
The nice thing about this fluent approach is that it doesn’t require adding overloads to all the T4MVC helpers (e.g. Html.ActionLink is this case) to take in the extra route values. Instead, it automatically applies to any method that uses the T4MVC pattern.
The general pattern of making a pseudo-call to a controller action is used is many places in T4MVC:
2.2.1 Html.ActionLink
Ok, we just covered that one above.2.2.2 Url.Action
<%= Url.Action("Delete", "Dinners", new { id = Model.DinnerID })%>
<%= Url.Action(MVC.Dinners.Delete(Model.DinnerID))%>
2.2.3 Ajax.ActionLink
<%= Ajax.ActionLink( "RSVP for this event", "Register", "RSVP", new { id=Model.DinnerID }, new AjaxOptions { UpdateTargetId="rsvpmsg", OnSuccess="AnimateRSVPMessage" }) %>
<%= Ajax.ActionLink( "RSVP for this event", MVC.RSVP.Register(Model.DinnerID), new AjaxOptions { UpdateTargetId="rsvpmsg", OnSuccess="AnimateRSVPMessage" }) %>
2.2.4 RedirectToAction (in controller code)
return RedirectToAction("Details", new { id = dinner.DinnerID });
return RedirectToAction(MVC.Dinners.Details(dinner.DinnerID));
2.2.5 routes.MapRoute (typically in global.asax)
routes.MapRoute( "UpcomingDinners", "Dinners/Page/{page}", new { controller = "Dinners", action = "Index" } );
routes.MapRoute( "UpcomingDinners", "Dinners/Page/{page}", MVC.Dinners.Index(null) );
2.2.6 Html.BeginForm
Essentially, it’s the same support as ActionLink() but for the BeginForm() method. 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.Here is how you might use this:
using (Html.BeginForm(MVC.Account.LogOn(), FormMethod.Post)) { ... }
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.
2.2.7 Html.RenderAction and Html.Action (only in MVC 2 or newer)
These are new to MVC 2. See Phil Haack's post about them for details.<%= Html.Action("Menu", new { options = new MenuOptions { Width=400, Height=500} })%>
<%= Html.Action(MVC.Home.Menu(new MenuOptions { Width=400, Height=500})); %>
2.3. Strongly typed links to script files and static resources
T4MVC generates static helpers for your content files and script files. So instead of writing:
<img src="/Content/nerd.jpg" />
<img src="<%= Links.Content.nerd_jpg %>" />
<script src="/Scripts/Map.js" type="text/javascript"></script>
<script src="<%= Links.Scripts.Map_js %>" type="text/javascript"></script>
Another benefit is that you get a more versatile reference. When you write src="/Content/nerd.jpg", your app will only work when it’s deployed at the root of the site. But when you use the helper, it executes some server side logic that makes sure your reference is correct wherever your site is rooted. It does this by calling VirtualPathUtility.ToAbsolute("~/Content/nerd.jpg").
One unfortunate thing is that for some reason, VS doesn’t support intellisense in the view for parameter values. As a workaround, you can type it outside of the tag to get intellisense and then copy it there.
Important note: if you see strange links getting generated in your <head> tag, you just need to remove the runat="server" from it.
Support for Minified Javascript files
Minified javascript files are alternate version of the files that makes them as small as possible, but using various strategies like removing white space. e.g. in an MVC application’s Scripts folder, you’ll typically see both jquery-1.3.2.js and jquery-1.3.2.min.js. 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.T4MVC makes it automatic to use one vs. the other depending on the context. e.g. suppose you have:
<script src="<%= Links.Scripts.jquery_1_2_6_js %>" type="text/javascript"></script>
// Logic to determine if the app is running in production or dev environment public static bool IsProduction() { return (HttpContext.Current != null && !HttpContext.Current.IsDebuggingEnabled); }
But you can easily change this logic if you have a different way of determining ‘production’.
2.4 Using T4MVC with MVC 2 "Areas"
One of MVC 2's major new features is the support for breaking up a large application into "Areas". This works by following a structure that looks like:
- Root folder
- Areas
- NerdDinner
- Models
- Views
- Controllers
- Wiki
- Models
- Views
- Controllers
- NerdDinner
- Areas
T4MVC automatically works with your areas and makes them available in its object model. Here is an example:
<%= Html.ActionLink("Delete Dinner", MVC.NerdDinner.Dinners.Delete(Model.DinnerID))%>
Optionally, if you set IncludeAreasToken to true in the settings file, the naming scheme becomes:
<%= Html.ActionLink("Delete Dinner", MVC.Areas.NerdDinner.Dinners.Delete(Model.DinnerID))%>
3. Tweaking the behavior of T4MVC
When you download T4MVC, you not only get the main T4MVC.tt template, but you also get a file named T4MVC.tt.settings.t4. This file contains various knobs that you can use to tweak the code generated by T4MVC. This section describes the various switches:Set AlwaysKeepTemplateDirty to false to turn on the always-dirty behavior
// If true, the template marks itself as unsaved as part of its execution. // This way it will be saved and update itself next time the project is built. // Basically, it keeps marking itself as unsaved to make the next build work. // Note: this is certainly hacky, but is the best I could come up with so far. bool AlwaysKeepTemplateDirty = true;
Set SplitIntoMultipleFiles to false to generate a single file with everything
// If true,the template output will be split into multiple files. bool SplitIntoMultipleFiles = true;
Use HelpersPrefix to change the MVC prefix of the genrated classes
// The prefix used for things like MVC.Dinners.Name and MVC.Dinners.Delete(Model.DinnerID) const string HelpersPrefix = "MVC";
Use ControllersFolder and ViewsRootFolder to rename the Controllers and Views folders
// 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";
Use LinksNamespace the generated links' namespace
// The namespace that the links are generated in (e.g. "Links", as in Links.Content.nerd_jpg) const string LinksNamespace = "Links";
Use StaticFilesFolders to tweak the list of folders from which links are generated
// Folders containing static files for which links are generated (e.g. Links.Scripts.Map_js) readonly string[] StaticFilesFolders = new string[] { "Scripts", "Content", };
4. Related resources
David Ebbo has written a series of blog posts on T4MVCScott Hanselman also blogged about it here
Last edited Aug 14 2011 at 4:09 PM by davidebbo, version 5