开发者

Url.Action reuses route data when I don't want it to

In my layout page, the links to the main sections that make up my site are rendered with a call like this:

@SiteSectionLink("index", "blog", "blog")

Where SiteSectionLink is a helper that looks like this:

@helper SiteSectionLink(string action, string controller, string display)
  {
  <li>
    <h1>
      <a class="site-section" href="@Url.Action(action, controller)">@display</a></h1>
  </li>
}

On the actual blog page, all links al开发者_StackOverflow中文版so refer to the "Index" action but also specify either a date parameter (such as "blog/4-2011" or "blog/2010") that is used to filter the posts by a date period. In addition to that, there's also an optional postID parameter that is used to refer to a specific post.

To accomplish that, I have the following routes:

routes.MapRoute(
 "Blog", 
 "blog/{date}/{postID}", 
  new 
  { 
    controller = "blog", 
    action = "index", 
    date = UrlParameter.Optional, 
    postID = UrlParameter.Optional 
  } 
);

routes.MapRoute(
  "Default", // Route name
   "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

Now, the problem is that when I have clicked a link that is something like "blog/11-2010" or "blog/11-2010/253" then the link in my layout page that refers to my blog in general now also refers to that same URL when I want it to just link to "blog/", not "blog/11-2010".

If I change the SiteSectionLink helper to explicitly pass in null for date and postID like this:

<a class="site-section" href="@Url.Action(action, controller, 
  new { date = (string)null, postID = (int?)null})">@display</a></h1>

The current route values are still used but now it looks like "blog?date=11-2010".

I saw this similar question but the accepted answer doesn't work for me, and I don't use ActionLink in the first place and I suspect that ActionLink would use Url.Action under the hood.


While the issue you are experiencing is not quite the behavior detailed by Phil Haack in this blog post regarding a bug with MVC3 routing and a route with two optional parameters, I would suggest applying the fix described in Phil's post.

I also would suggest never creating a route with two optional parameters, and instead follow the pattern of breaking the desired routing into two separate routes.


Yes Url.Action method puts the parameters in the querystring. You can change your helper like this:

@helper SiteSectionLink(string action, string controller, string display, string date = null, string id=null)
{ 
  <li> 
    @if (date == null)
    {
        <h1><a class="site-section" href="~/blog/@controller/@action">@display</a></h1> // simple workaround or better use P. Haack workaround
    }
    else 
    {
        <h1><a class="site-section" href="@Url.RouteUrl("blog", new { action = @action, controller = @controller, date = @date, id = @id })">@display</a></h1> 
    }
  </li> 
} 

So you can use SiteSelectionLink like these:

@SiteSectionLink("Index", "Blog", "test", "2011", "4")
@SiteSectionLink("Index", "Blog", "test2", "2011")
@SiteSectionLink("Index", "Blog", "test3")
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜