In the MVC Future Assembly there lives a super handy class called "LinkBuilder". This class takes an expression and builds a URL using your configured routes.
Creating an extension method in your own project to use this class is pretty straight forward:
public static string Action<TController>(this UrlHelper helper, Expression<Action<TController>> action)
where TController : Controller
{
return Microsoft.Web.Mvc.LinkBuilder.BuildUrlFromExpression(helper.RequestContext, helper.RouteCollection, action);
}
You can also use this library to create your own "ActionLink" extensions too. BUT, this isn't why I wrote this article.
I wanted to extend this method to specify an EXACT route to use, as I had a special route to format the URLs and the above method uses the first route it finds that could work - usually the default route.
After struggling for hours trying to parse the expression myself (UGH!), a simple solution presented itself:
public static string Action<TController>(this UrlHelper helper, Expression<Action<TController>> action, string routeName)
where TController : Controller
{
var routeCollection = helper.RouteCollection;
// Check to ensure this route exists first. If not, don't filter the routes.
if (helper.RouteCollection[routeName] != null)
routeCollection = new RouteCollection { helper.RouteCollection[routeName] };
return Microsoft.Web.Mvc.LinkBuilder.BuildUrlFromExpression(helper.RequestContext, routeCollection, action);
}
This method filters the RouteCollection down to the exact route you are want to use and passes the filtered collection to the LinkBuilder... ahhh, routing-bliss.
Now you can use it in your views like this:
<%= Url.Action<CredentialsController>(c => c.Edit(credID), "CredentialActions") %>