21

I am rendering a menu from a Partial Action directly to the layout, using:

@Html.Action(MVC.Menu.Index())

This action, determines which Menu partial to render. For instance, a public menu partial. Within these partials, I am also using T4MVC to render the links:

<ul id="navHolder">
<li class="level1">
    <ul class="mainMenu">
        <li><b>@Html.ActionLink("Welcome", MVC.Home.Index())</b>
           ... 

For some reason, the Urls rendered by T4MVC include "?Area=" at the end:

 <ul id="navHolder">
    <li class="level1">
        <ul class="mainMenu">
            <li><b><a href="/home/index?Area=">Welcome</a></b>
               ...

I have NO areas in my project and I have turned the "IncludeAreasToken" setting to false. Oddly, this only happens if I render the partial using "@Html.Action" -- if I pull it in as "@Html.Partial" the parameter isn't rendered and the link is clean and correct. (I don't want to render it as a partial though, so please don't offer that as a suggestion ;)

Anyone out there run into this before?

marcind
  • 52,944
  • 13
  • 125
  • 111
Jason Wicker
  • 3,416
  • 2
  • 25
  • 32

3 Answers3

30

I solve this issue in a very easy way, simply by adding to all routes that are not in area empty area route like this:

routes.MapRoute(
"Default",
"{controller}/{action}/{i​d}",
new { controller = "Home", action = "Index", area = "", id = UrlParameter.Optional });
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
panec
  • 301
  • 3
  • 2
  • Just tested this and it seems like the easiest solution - just add an area of String.Empty to the default route and all the URLs generate correctly. – Brad R Feb 07 '12 at 08:25
  • This doesn't work if you use attribute routing in your project. See my answer which I copid from mvccontrib archive, workitem 7154 because you cannot find it easily on the archived Codeplex site now. – mare Apr 08 '21 at 10:01
10

Something strange is going on here, and I wonder if there is some kind of MVC bug at the root. Even without using T4MVC, this happens if you write:

@Html.ActionLink("Welcome", "Index", "Home", new { Area = "" }, null)

In a regular view, this doesn't generate the bogus ?Area=, while in a Html.Action call it does. I need to ask someone on the team.

For now, you can workaround by deleting this line (around line 310) in t4mvc.tt:

<# if (MvcVersion >= 2) { #>result.RouteValueDictionary.Add("Area", area ?? "");<# } #> 
David Ebbo
  • 42,443
  • 8
  • 103
  • 117
  • I just added a check to see if the area was supplied, if so I add it to the dictionary: `if (!String.IsNullOrWhiteSpace(area)) {result.RouteValueDictionary.Add("Area", area ?? "");}` – Brad R Aug 05 '11 at 09:02
  • @BradR: the problem with this change is that I think it's not always correct. When you're in an Area view and you're trying to generate a link to a top level (non-Area) view, then passing an empty area is the correct thing to do to 'escape' the current area. But with your check that won't happen. – David Ebbo Aug 05 '11 at 22:21
  • 3
    It turns out that MVC only generates the bogus token if the app *doesn't* have any areas. So we should just fix T4MVC to only add this token if the app uses areas. – David Ebbo Dec 06 '11 at 08:31
  • @DavidEbbo has this checking been implemented? I'm getting the same issue with the latest T4MVC – DLeh Sep 24 '14 at 14:19
  • No, but there is a simpler workaround here: https://mvccontrib.codeplex.com/workitem/7154 – David Ebbo Sep 24 '14 at 18:01
0

Copied from workitem 7154 comments is a solution provided by @DavidEbbo:

A simpler workaround is to add a bogus area to your site. e.g.\n\n- Right click Project and choose Add / Area. Name it 'Dummy' (or whatever)\n- You can delete everything in there except for the DummyAreaRegistration.cs file

Make sure you have the AreaRegistration.RegisterAllAreas(); call in your Global.asax

This also works with attribute routing in place.

mare
  • 13,033
  • 24
  • 102
  • 191