Nelson Reis
Nelson Reis

Reputation: 4810

T4MVC creates incorrect URL for ActionLink when using Areas

In my project I'm trying to create an URL in a view inside an area.
The code is this:

@Html.ActionLink("Cancel", MVC.MyArea.MyController.Index(), new { @class = "btn" })

When I view the result in the browser, the generated code is the following:

<a class="btn" href="/MyArea/MyController/MyCurrentAction?Count=3&amp;Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&amp;Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D">Cancel</a>

I went looking for the code in T4MVC and found that this was the method generating the code above (inside the T4Extensions class):

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes, string protocol = null, string hostName = null, string fragment = null) {
    return htmlHelper.RouteLink(linkText, null, protocol, hostName, fragment, result.GetRouteValueDictionary(), htmlAttributes);
}

Apparently, the RouteLink method is not being able to use the result.GetRouteValueDictionary() as it should.

So, I checked the ASP.NET MVC source code and tried to replicate the same functionality. I've changed my T4MVC to this:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes, string protocol = null, string hostName = null, string fragment = null) {
    var t4mvcResult = result.GetT4MVCResult();
    var actionName = t4mvcResult.Action;
    var controllerName = t4mvcResult.Controller;
    var routeValues = new RouteValueDictionary(t4mvcResult.RouteValueDictionary);
    var htmlAttribs = new RouteValueDictionary(htmlAttributes);
    return new MvcHtmlString(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttribs));
}

Now it's working (which is great, of course), at least for the tests I've made, but I'm afraid that I'm doing something wrong in the first place and that this path can lead me into some problems ahead.

Upvotes: 1

Views: 887

Answers (1)

David Ebbo
David Ebbo

Reputation: 43183

Darn, this looks like a regression in 2.6.69. Can you try 2.6.68 to verify that indeed it worked before? I have hidden 2.6.69 for now so others don't get it automatically in new projects (and when updating).

This was the bug that triggered the bad fix: http://mvccontrib.codeplex.com/workitem/7191

Also, could you try the exact fix mentioned in the last comment in that bug? Change the method to:

    public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes, string protocol = null, string hostName = null, string fragment = null)
    {
        return htmlHelper.RouteLink(linkText, null, protocol, hostName, fragment, result.GetRouteValueDictionary(), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

Sorry about the break!

Upvotes: 1

Related Questions