February 2011 Blog Posts
David Fowler turned me on to a really cool feature of Razor I hadn’t realized made it into 1.0, Templated Razor Delegates. What’s that? I’ll let the code do the speaking.
@{
Func<dynamic, object> b = @<strong>@item</strong>;
}
<span>This sentence is @b("In Bold").</span>
That could come in handy if you have friends who’ll jump on your case for using the bold tag instead of the strong tag because it’s “not semantic”. Yeah, I’m looking at you Damian
. I mean, don’t both words signify being forceful? I digress.
Note that the delegate that’s generated is a Func<T, HelperResult>. Also, the @item parameter is a special magic parameter. These delegates are only allowed one such parameter, but the template can call into that parameter as many times as it needs.
The example I showed is pretty trivial. I know what you’re thinking. Why not use a helper? Show me an example where this is really useful. Ok, you got it!
Suppose I wrote this really cool HTML helper method for generating any kind of list.
public static class RazorExtensions {
public static HelperResult List<T>(this IEnumerable<T> items,
Func<T, HelperResult> template) {
return new HelperResult(writer => {
foreach (var item in items) {
template(item).WriteTo(writer);
}
});
}
}
This List method accepts a templated Razor delegate, so we can call it like so.
@{
var items = new[] { "one", "two", "three" };
}
<ul>
@items.List(@<li>@item</li>)
</ul>
As I mentioned earlier, notice that the argument to this method, @<li>@item</li> is automatically converted into a Func<dynamic, HelperResult> which is what our method requires.
Now this List method is very reusable. Let’s use it to generate a table of comic books.
@{
var comics = new[] {
new ComicBook {Title = "Groo", Publisher = "Dark Horse Comics"},
new ComicBook {Title = "Spiderman", Publisher = "Marvel"}
};
}
<table>
@comics.List(
@<tr>
<td>@item.Title</td>
<td>@item.Publisher</td>
</tr>)
</table>
This feature was originally implemented to support the WebGrid helper method, but I’m sure you’ll think of other creative ways to take advantage of it.
If you’re interested in how this feature works under the covers, check out this blog post by Andrew Nurse.
Renaming a package ID is a potentially destructive action and one we don’t recommend doing. Why? Well if any other packages depend on your package, you’ve effectively broken them if you change your package ID.
For example, today I wanted to rename a poorly named package, MicrosoftWebMvc, to Mvc2Futures. What I ended up doing is recreating the same package with the new ID and uploading it. That way existing packages that depend on MicrosoftWebMvc aren’t broken.
But now, I have two packages that have the same functionality, but different IDs. Wouldn’t it be nice to eventually remove the old one? I guess I could if I knew that no other package had a dependency on it.
This is where the benefit of having an OData service over the packages in the gallery comes in quite useful. It allows us to construct ad-hoc queries we hadn’t accounted for in our API via an URL. Here’s the URL that shows me a list of all packages that depend on MicrosoftWebMvc.
http://packages.nuget.org/v1/FeedService.svc/Packages?$filter=substringof('MicrosoftWebMvc',%20Dependencies)%20eq%20true&$select=Id,Dependencies
Notice that we’re searching the Dependencies node for the substring “MicrosoftWebMvc” anywhere in it. If my package ID was “web”, this would not be a good query to run, so you might need to tweak it for your use case.
Also, this query only detects direct dependencies. It doesn’t detect transitive dependencies. However, in this case, that’s good enough for my needs.
With this list in hand, I can now approach the MvcContrib folks (who are the only ones that depend on it), and suggest they update their existing packages in place to point to the one with the new ID.
If they do this, am I safe to delete MicrosoftWebMvc?
Not necessarily.
I really need to think twice before I remove the MicrosoftWebMvc package because it’s already been downloaded 939 times. For those users who’ve installed it into their applications, they’ll never get updates for that package.
In this particular case, this is not a problem because we never plan to update the Mvc2Futures package. But for a package that’s more widely used and frequently updated, this would be a bigger concern.
In the meanwhile, what I will do is update MicrosoftWebMvc to be an empty package that depends on the correct package. That’s probably a good plan while I wait for packages that depend on it to update.
Within a Razor view, you have access to a base set of properties (such as Html, Url, Ajax, etc.) each of which provides methods you can use within the view.
For example, in the following view, we use the Html property to access the TextBox method.
@Html.TextBox("SomeProperty")
Html is a property of type HtmlHelper and there are a large number of useful extension methods that hang off this type, such as TextBox.
But where did the Html property come from? It’s a property of System.Web.Mvc.WebViewPage, the default base type for all razor views. If that last phrase doesn’t make sense to you, let me explain.
Unlike many templating engines or interpreted view engines, Razor views are dynamically compiled at runtime into a class and then executed. The class that they’re compiled into derives from WebViewPage. For long time ASP.NET users, this shouldn’t come as a surprise because this is how ASP.NET pages work as well.
Customizing the Base Class
HTML 5 (or is it simply “HTML” now) is a big topic these days. It’d be nice to write a set of HTML 5 specific helpers extension methods, but you’d probably like to avoid adding even more extension methods to the HtmlHelper class because it’s already getting a little crowded in there.

Well perhaps what we need is a new property we can access from within Razor. Well how do we do that?
What we need to do is change the base type for all Razor views to something we control. Fortunately, that’s pretty easy. When you create a new ASP.NET MVC 3 project, you might have noticed that the Views directory contains a Web.config file.
Look inside that file and you’ll notice the following snippet of XML.
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory,
System.Web.Mvc, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
The thing to notice is the <pages> element which has the pageBaseType attribute. The value of that attribute specifies the base page type for all Razor views in your application. But you can change that value by simply replacing that value with your custom class. While it’s not strictly required, it’s pretty easy to simply write a class that derives from WebViewPage.
Let’s look at a simple example of this.
public abstract class CustomWebViewPage : WebViewPage {
public Html5Helper Html5 { get; set; }
public override void InitHelpers() {
base.InitHelpers();
Html5 = new Html5Helper<object>(base.ViewContext, this);
}
}
Note that our custom class derives from WebViewPage, but adds a new Html5 property of type Html5Helper. I’ll show the code for that helper here. In this case, it pretty much follows the pattern that HtmlHelper does. I’ve left out some properties for brevity, but at this point, you can add whatever you want to this class.
public class Html5Helper {
public Html5Helper(ViewContext viewContext,
IViewDataContainer viewDataContainer)
: this(viewContext, viewDataContainer, RouteTable.Routes) {
}
public Html5Helper(ViewContext viewContext,
IViewDataContainer viewDataContainer, RouteCollection routeCollection) {
ViewContext = viewContext;
ViewData = new ViewDataDictionary(viewDataContainer.ViewData);
}
public ViewDataDictionary ViewData {
get;
private set;
}
public ViewContext ViewContext {
get;
private set;
}
}
Let’s write a simple extension method that takes advantage of this new property first, so we can get the benefits of all this work.
public static class Html5Extensions {
public static IHtmlString EmailInput(this Html5Helper html, string name,
string value) {
var tagBuilder = new TagBuilder("input");
tagBuilder.Attributes.Add("type", "email");
tagBuilder.Attributes.Add("value", value);
return new HtmlString(tagBuilder.ToString());
}
}
Now, if we change the pageBaseType to CustomWebViewPage, we can recompile the application and start using the new property within our Razor views.

Nice! We can now start using our new helpers. Note that if you try this and don’t see your new property in Intellisense right away, try closing and re-opening Visual Studio.
What about Strongly Typed Views
What if I have a Razor view that specifies a strongly typed model like so:
@model Product
@{
ViewBag.Title = "Home Page";
}
<p>@Model.Name</p>
The base class we wrote wasn’t a generic class so how’s this going to work? Not to worry. This is the part of Razor that’s pretty cool. We can simply write a generic version of our class and Razor will inject the model type into that class when it compiles the razor code.
In this case, we’ll need a generic version of both our CustomWebViewPage and our Html5Helper classes. I’ll follow a similar pattern implemented by HtmlHelper<T> and WebViewPage<T>.
public abstract class CustomWebViewPage<TModel> : CustomWebViewPage {
public new Html5Helper<TModel> Html5 { get; set; }
public override void InitHelpers() {
base.InitHelpers();
Html5 = new Html5Helper<TModel>(base.ViewContext, this);
}
}
public class Html5Helper<TModel> : Html5Helper {
public Html5Helper(ViewContext viewContext, IViewDataContainer container)
: this(viewContext, container, RouteTable.Routes) {
}
public Html5Helper(ViewContext viewContext, IViewDataContainer container,
RouteCollection routeCollection) : base(viewContext, container,
routeCollection) {
ViewData = new ViewDataDictionary<TModel>(container.ViewData);
}
public new ViewDataDictionary<TModel> ViewData {
get;
private set;
}
}
Now you can write extension methods of Html5Helper<TModel> which will have access to the model type much like HtmlHelper<TModel> does.
As usual, if there’s a change you want to make, there’s probably an extensibility point in ASP.NET MVC that’ll let you make it. The tricky part of course, in some cases, is finding the correct point.
It pains me to say it, but ASP.NET MVC 3 introduces a minor regression in routing from ASP.NET MVC 2. The good news is that there’s an easy workaround.
The bug manifests when you have a route with two consecutive optional URL parameters and you attempt to use the route to generate an URL. The incoming request matching behavior is unchanged and continues to work fine.
For example, suppose you have the following route defined:
routes.MapRoute("by-day",
"archive/{month}/{day}",
new { controller = "Home", action = "Index",
month = UrlParameter.Optional, day = UrlParameter.Optional }
);
Notice that the month and day parameters are both optional.
routes.MapRoute("by-day",
"archive/{month}/{day}",
new { controller = "Home", action = "Index",
month = UrlParameter.Optional, day = UrlParameter.Optional }
);
Now suppose you have the following view code to generate URLs using this route.
@Url.RouteUrl("by-day", new { month = 1, day = 23 })
@Url.RouteUrl("by-day", new { month = 1 })
@Url.RouteUrl("by-day", null)
In ASP.NET MVC 2 the above code (well actually, the equivalent to the above code since Razor didn’t exist in ASP.NET MVC 2) would result in the following URLs as you would expect:
- /archive/1/23
- /archive/1
- /archive
But in ASP.NET MVC 3, you get:
In the last case, the value returned is null because of this bug. The bug occurs when two or more consecutive optional URL parameters don’t have values specified for URL generation.
Let’s look at the workaround first, then we’ll dive deeper into why this bug occurs.
The Workaround
The workaround is simple. To fix this issue, change the existing route to not have any optional parameters by removing the default values for month and day. This route now handles the first URL where month and day was specified.
We then add a new route for the other two cases, but this route only has one optional month parameter.
Here are the two routes after we’re done with these changes.
routes.MapRoute("by-day",
"archive/{month}/{day}",
new { controller = "Home", action = "Index"}
);
routes.MapRoute("by-month",
"archive/{month}",
new { controller = "Home", action = "Index",
month = UrlParameter.Optional}
);
And now, we need to change the last two calls to generate URLs to use the by-month route.
@Url.RouteUrl("by-day", new { month = 1, day = 23 })
@Url.RouteUrl("by-month", new { month = 1 })
@Url.RouteUrl("by-month", null)
Just to be clear, this bug affects all the URL generation methods in ASP.NET MVC. So if you were generating action links like so:
@Html.ActionLink("sample", "Index", "Home", new { month = 1, day = 23 }, null)
@Html.ActionLink("sample", "Index", "Home", new { month = 1}, null)
@Html.ActionLink("sample", "Index", "Home")
The last one would be broken without the workaround just provided.
The workaround is not too bad if you happen to follow the practice of centralizing your URL generation. For example, the developers building http://forums.asp.net/ ran into this problem as well during the upgrade to ASP.NET MVC 3. But rather than having calls to ActionLink all over their views, they have calls to methods that are specific to their application domain such as ForumDetailUrl. This allowed them to workaround this issue by updating a single method.
The Root Cause
For the insanely curious, let’s look at the root cause of this bug. Going back to the original route defined at the top of this post, we never tried generating an URL where only the second optional parameter was specified.
@Url.RouteUrl("by-day", new { day = 23 })
This call really should fail because we didn’t specify a value for the first optional parameter, month. If it’s not clear why it should fail, suppose we allowed this to succeed, what URL would it generate? /archive/23? Well that’s obviously not correct because when a request is made for that URL, 23 will be interpreted to be the month, not the date.
In ASP.NET MVC 2, if you made this call, you ended up with /archive/System.Web.Mvc.UrlParameter/23. UrlParameter.Optional is a class introduced by ASP.NET MVC 2 which ships on its own schedule outside of the core ASP.NET Framework. What that means is we added this new class which provided this new behavior in ASP.NET MVC, but core routing didn’t know about it.
The way we fixed this in ASP.NET MVC 3 was to make the ToString method of UrlParameter.Optional return an empty string. That solved this bug, but uncovered a bug in core routing where a route with optional parameters having default values behaves incorrectly when two of them don’t have values specified during URL generation. Sound familiar?
In hindsight, I think it was a mistake to take this fix because it caused a regression for many applications that had worked around the bug. The bug was found very late in our ship cycle and this is just one of the many challenging decisions we make when building software that sometimes don’t work out the way you hoped or expected. All we can do is learn from it and let the experience factor into the next time we are faced with such a dilemma.
The good news is we have bugs logged against this behavior in core ASP.NET Routing so hopefully this will all get resolved in the next core .NET framework release.
Today I’m pleased to announce the release of NuGet 1.1 to the VS Extension Gallery and CodePlex. If you have NuGet 1.0 installed, just launch the VS Extension Manager (via Tools | Extension Manager menu) and click on the Updates tab.
If you don’t see any updates, make sure to enable automatic detection of available updates.

If you are running VS 2010 SP1 Beta, you might run into the following error message when attempting to upgrade to NuGet 1.1 if you have an older version installed.
_3.png)
The workaround is to simply uninstall NuGet and then install it from the VS Extension Gallery.
It turns out that our previous VSIX was signed with an incorrect certificate and our updated VSIX is signed with the correct certificate. VS 2010 SP1 now compares and verifies that the certificates of the old and new VSIX match during an upgrade.
If you don’t have NuGet installed, click the Online tab and type in “NuGet” (sans quotes) to find it.

The VSIX and updated command line tool (used to create and publish packages) is also available on CodePlex.com.
What’s New in 1.1?
Much of the work in this release was focused on bug fixes. Now that CodePlex.com supports directly linking to filtered views of the issue tracker, I can provide you a link to all the issues fixed in 1.1. 
In this post, I’ll highlight some of the new features.
Recent Packages Tab
One of the first changes you might notice is that we have a new tab in the dialog that shows packages that you’ve installed recently. Click the screenshot below for a larger view.

The recent packages shows the last 20 packages that you’ve directly installed. This often comes in handy when you tend to use the same packages over and over again in multiple projects. Right now, the list simply shows the most recently used, but there has been discussion about perhaps changing the behavior to sort by the packages used most often. Feel free to chime in if you want the behavior changed.
By the way, you can also use the Powershell within the Package Manager Console to get this same information with the –Recent flag to Get-Package.

Progress Bar During Installation
When you install a package, you’ll now notice a progress bar dialog that shows up with output from installing the package.

The dialog is meant to give an indication of progress, but also gets out of your way immediately when the installation is complete so you’re not stuck clicking a bunch of Close buttons. But what happens if you actually want to review that output?
Package Manager Output Window
NuGet 1.1 also posts that output to the Output window now. When you go to the Output window, you’ll need to select output from the Package Manager to see that output as in the screenshot.

This allows you to review what changes a package made at your leisure after the fact.
Dependency Resolution Algorithm
NuGet 1.1 includes an update to our dependency resolution algorithm which is described in David Ebbo’s blog post on this topic in the section titled “NuGet 1.1 twist”.
Support for F# Project Types
If you are using F#, this one’s for you.
PowerShell Improvements
Thanks to our newest core contributor, Oisin Grehan a PowerShell MVP who really knows his stuff, NuGet 1.1 has a lot of improvements to the PowerShell Console and scripts. I have to admit, a lot of it is over my head as I’m no PowerShell guru, but we’re now much more compliant with PowerShell conventions. Or so I’ve been told. Oisin has been driving a lot of improvements with our PowerShell support.
We also now execute commands within the Powershell Console asynchronously. This means that a long running command won’t freeze the rest of Visual Studio while it runs.
And many others!
There were a lot of other tweaks, bug fixes, and minor improvements that were not worth mentioning here, but they are all listed in our release notes.
Breaking Changes?
There are some minor changes that hopefully won’t break 99.9% of you. If you recall, we made our PowerShell scripts fit with PowerShell conventions. If you have a package that calls one of these methods, your package might need to be updated.Here’s the list of changes we made:
- Removed
List-Package. Use Get-Package instead. Get-ProjectNames was removed. Use Get-Project instead and examine the Name property. Add-BindingRedirects was renamed to Add-BindingRedirect.
What’s next?
Our hope is to have a monthly point release, though we may adjust some iterations to be longer as needed. To see what we’re planning for the 1.2 release, check out this link of issues for 1.2 (note that by the time you read this, some of these features might already be implemented). We’re constantly refining our planning so nothing is set in stone.
For a small taste of what’s coming in 1.2, check out this video by David Ebbo showing a streamlined workflow for creating packages.
Get Involved!
I bet many of you have some great ideas on what we should and shouldn’t do for NuGet. We’d love to have you come over and share your great ideas in our discussion list. Or if you’re looking for other ways to contribute, check out our guide to contributing to NuGet.
Over a decade ago, Tim Berners-Lee, creator of the World Wide Web instructed the world know that cool URIs don’t change with what appears to be a poem, but it doesn’t rhyme and it’s not haiku.
What makes a cool URI?
A cool URI is one which does not change.
What sorts of URI change?
URIs don't change: people change them.
In a related article, URL as UI, usability expert Jakob Nielsen lists the following criteria for a usable site:
- a domain name that is easy to remember and easy to spell
- short URLs
- easy-to-type URLs
- URLs that visualize the site structure
- URLs that are "hackable" to allow users to move to higher levels of the information architecture by hacking off the end of the URL
- persistent URLs that don't change
The permanence of URLs is a fundamental trait of the web that seems to run counter to one of the benefits of using a feature like ASP.NET Routing. For example, one benefit of routing is you can change a route from {controller}/{action}/{id} to {controller}/{id}/{action} and have every URL in your site corresponding to that route automatically be updated.
This is very nice during development when you’re still fleshing out your URLs and haven’t committed to anything, but once you’ve published your site, changing a route URL violates the sacred trait of URL permanence.
This is exactly where I find myself with Subtext. All of our existing URLs end with the .aspx extension, a practice which Jon Udell convincingly argued is harmful. In the upcoming version of Subtext, we’re moving to extensionless URLs by building upon the great support built into ASP.NET 4 and Routing.
I could simply change our routes to remove the .aspx extension, but that would break nearly every existing URL in every blog running on Subtext. So much for URL permanence, right?
There’s a Better Way
Rather than changing routes, what I really want is a way to simply redirect the existing route to a new route. This is pretty easy, but there are a few caveats to keep in mind that make it non-trivial.
- Since you don’t want to generate URLs for the old route, the legacy route should never be selected for URL generation. It’s only for matching incoming requests.
- The legacy route should be registered after the new URL to ensure it doesn’t accidentally match and supersede the new URL.
I wrote a library that provides a RedirectRoute and a simple extension method for registering a RedirectRoute that satisfies these conditions. Let’s look at an example of how it would be used.
Let’s suppose we have the following route defined and the site has been published to the web..
routes.MapRoute("old", "foo/{controller}/{action}/{id}");
But later, we decide we want all such URLs to start with /bar instead and we want to re-order the id and action segments of the URL.
Here’s an example of how we can do that using this new library.
var route = routes.MapRoute("new", "bar/{controller}/{id}/{action}");
routes.Redirect(r => r.MapRoute("old", "foo/{controller}/{action}/{id}"))
.To(route);
This snippet registers the new route and passes that route to the RedirectRoute that was returned by a call to the Redirect extension method. The RedirectRoute delegates to the old route to match incoming requests. With this in place, every request matching the old route will be redirected to the new route.
Thus a request for /foo/home/index/123 will be redirected to /bar/home/123/index.
Why The Lambda Expression?
To fully understand what’s going on under the hood, I need to explain why the API takes in a lambda expression rather than simply taking in two routes, old route and new route.
Let’s suppose that the API did just that, simply accepted two routes. Here’s what a naïve attempt to use the method might look like.
var new = routes.MapRoute("new", "bar/{controller}/{id}/{action}");
var old = routes.MapRoute("new", "foo/{controller}/{action}/{id}");
routes.Redirect(old).To(new);
Hopefully it’s immediately apparent why this is not good. The old route is mapped before the redirect route. So the redirect route will never be matched.
The MapRoute extension method not only creates a route, but it adds it to the route collection. So we could have manually created the route, but that’s a pain if you’re already using the MapRoute method to create the route. Or, we could have done this:
var new = routes.MapRoute("new", "bar/{controller}/{id}/{action}");
var throwAway = new RouteCollection();
var old = throwAway.MapRoute("new", "foo/{controller}/{action}/{id}");
routes.Redirect(old).To(new);
Requiring the user of the API to create a throwaway route collection is ugly when the API itself could do it for you. Hence the lambda expression argument to Redirect. Internally, the method creates a throwaway route collection and calls the expression against that instead of against the main route collection.
Implementation Details
I won’t post the full source here, but the implementation details are pretty simple. Here’s the implementation of GetRouteData which is the method called when matching incoming requests.
public override RouteData GetRouteData(HttpContextBase httpContext) {
// Use the original route to match
var routeData = SourceRoute.GetRouteData(httpContext);
if (routeData == null) {
return null;
}
// But swap its route handler with our own
routeData.RouteHandler = this;
return routeData;
}
Notice that I use the source route, which is the old route passed into the redirect route, to match the request, but I swap the route handler with the redirect route. RedirectRoute also implements IRouteHandler. It was a little implementation shortcut I took which happens to work fine in this case.
The implementation of GetVirtualPath is even simpler.
public override VirtualPathData GetVirtualPath(RequestContext requestContext
, RouteValueDictionary values) {
// Redirect routes never generate an URL.
return null;
}
We never want to generate a URL to the old route, so this method always returns null.
As mentioned, RedirectRoute implements IRouteHandler, so we should look at its implementation.
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
var requestRouteValues = requestContext.RouteData.Values;
var routeValues = AdditionalRouteValues.Merge(requestRouteValues);
var vpd = TargetRoute.GetVirtualPath(requestContext, routeValues);
string targetUrl = null;
if (vpd != null) {
targetUrl = "~/" + vpd.VirtualPath;
return new RedirectHttpHandler(targetUrl, Permanent, isReusable: false);
}
return new DelegateHttpHandler(
httpContext => httpContext.Response.StatusCode = 404, false);
}
Notice that we make use of the DelegateHttpHandler which is something I wrote about a while ago.
Where to get it?
All the code I showed here is now part of the RouteMagic library I blogged about recently. I’ve updated the package so all you need to do is Install-Package RouteMagic within NuGet.