I am trying to test the outbound URL of an action method in an MVC area using the MvcContrib TestHelper's static OutBoundUrl
class. Here is what I have:
OutBoundUrl.Of<ErrorsController>(action => action.NotFound())
.ShouldMapToUrl("/errors/404");
I stepped into the source and found that the UrlHelper
was returning null for the outbound URL. Basically it creates a new UrlHelper and delegates the task to UrlHelper.Action(action, controller, routeValues)
.
When invoked, routeValues
does not contain anything (the action method takes no args). Is this a bug? Or do I need to do something extra to make this work with areas? The following line comes just before the above line in the unit test, so my routes are registered (the UrlHelper.RouteCollection
contains 100+ routes).
"~/errors/404".WithMethod(HttpVerbs.Get)
.ShouldMapTo<ErrorsController>(action => action.NotFound());
The route is not named, and I don't want to name it, so please don't suggest I use the OfRouteNamed
method.
Update
I made an extension method that could work, except for one thing. The OutBoundController
Of<TController>
method has this code:
var methodCall = ((MethodCallExpression)action.Body);
var methodName = methodCall.Method.Name;
There is similar, but critically different code in the RouteTestingExtensions
ShouldMapTo<TController>
method:
var methodCall = (MethodCallExpression) action.Body;
// this line is not important
string expectedAction = methodCall.Method.ActionName();
The ActionName()
extension method is kind of awesome if you use ActionNameAttributes
:
/// <summary>
/// Will return the name of the action specified in the ActionNameAttribute
/// for a method if it has an ActionNameAttribute.
/// Will return the name of the method otherwise.
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public static string ActionName(this MethodInfo method)
{
if (method.IsDecoratedWith<ActionNameAttribute>())
return method.GetAttribute<ActionNameAttribute>().Name;
return method.Name;
}
Back to the question... is this by design, and if so, why? The fact that OutBoundUrl
does not use the .ActionName()
extension is the one thing keeping me from writing an extension method to generate outbound url's for area actions decorated with [ActionName]
.