I am having an issue where UrlHelper's RouteUrl method only returns an empty string when run in my tests, though function properly when executing in the real HttpContext. It is, however, finding the route - as I do properly get an exception if I try to resolve a route name which has not been defined.
I have mocked the HttpContext and friends using the code provided by Scott Hanselman/Kzu and added the code needed to bootstrap the Application's Routes into the mocked instance
To reduce the number of variables in my situation, I've written a simple test:
[Test]
public void UrlHelperReturnsCorrectUrl()
{
var controller = new MyController();
controller.SetFakeControllerContext().LoadUrlHelper();
Assert.AreEqual("My/Route/Path", controller.Url.RouteUrl("MyRoute"));
}
Interestingly enough, accessing the RouteCollection directly and using VirtualPath does work:
[Test]
public void GetVirtualPathReturnsCorrectUrl()
{
var controller = new AccountController();
controller.SetFakeControllerContext().LoadUrlHelper();
Assert.AreEqual("My/Route/Path",
Controller.Url.RouteCollection["MyRoute"]
.GetVirtualPath(
controller.Url.RequestContext,
new RouteValueDictionary())
.VirtualPath);
}
For reference, Here is my implementation of the LoadUrlHelper extension method:
public static Controller LoadUrlHelper(this Controller controller)
{
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
controller.Url = new UrlHelper(
controller.ControllerContext.RequestContext,
routes);
return controller;
}
And here is my route as defined in my application's Global.asax:
routes.MapRoute(
"MyRoute", "My/Route/Path",
new {controller = "Home", action = "Index"});
Has anyone run into this? Am I missing something?
EDIT:
I've followed the MVC code down to the point that it hands the route processing off to System.Routing and found something very interesting. The code that MVC eventually runs to lookup the desired URL (condensed, of course) returns an empty string:
Controller.Url.RouteCollection.GetVirtualPath(
Controller.Url.RequestContext,
"MyRoute", new RouteValueDictionary()).VirtualPath;
whereas an extremely similar variant returns the expected string:
Controller.Url.RouteCollection["MyRoute"].GetVirtualPath(
Controller.Url.RequestContext,
new RouteValueDictionary()).VirtualPath;
I can't seem to go any further in the underlying code to see what is actually happening differently here, but thought it might help someone understand what setup I am missing. (I'm not going to yell bug yet, as the fact stands that the UrlHelpers do work when in a real HttpContext)