2011-02-01 116 views
3

Global.asax中路由值如何使用Html.ActionLink覆盖路由表的默认值?

 routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional, filterDate = DateTime.Now.AddDays(-1), filterLevel = "INFO" } // Parameter defaults 
     ); 

这里是我的ActionLink

 @Html.ActionLink(item.MachineName, "Machine", new { id = item.MachineName, filterLevel = "hello" }, null) 

当ActionLink的指定了filterlevel,它会产生这样的网址:

http://localhost:1781/LoggingDashboard/log/level/VERBOSE 

是哪个与我目前相同的页面。如果我改变ActionLink的使用其他的属性不是一个有路由表(是的,如果我使用filterDate它也打乱了)的默认值,它会产生一个像这样的链接:

@Html.ActionLink(item.MachineName, "Machine", new { id = item.MachineName, foo = "bar" }, null) 

http://localhost:1781/LoggingDashboard/log/Machine/C0UPSMON1?foo=bar 

这是行为正确吗?我应该不能覆盖路由表中设置的默认值吗?我已经证实,如果我删除从路由表中的filterLevel默认情况下此工程,我想到:

http://localhost:1781/LoggingDashboard/log/Machine/C0UPSMON1?filterLevel=VERBOSE 

---编辑--- 对不起,这里是行动

 public ActionResult Machine(string id, DateTime filterDate, string filterLevel) 
     { 
... 
      var model = new LogListViewModel { LogEntries = logEntries }; 
      return View(model); 
     } 

因为我想知道如何重写了在从Global.asax中的路由指定的“默认”值赏金。即我想能够覆盖filterLevel和filterDate。

+0

什么是你的行动的签名看起来像? filterLevel是以字符串还是枚举类型的形式出现的? – StriplingWarrior 2011-02-01 17:17:28

+0

我会在动作中定义这个,但是我想要一个像DateTime filterDate = DateTime.Now.AddDays(-1)这样的默认参数,它不能进入​​方法参数--FilterDate的默认参数值必须是编译时常量 – BlackICE 2011-02-01 17:34:25

+0

你的路线是什么? – SLaks 2011-02-07 14:47:09

回答

3

SLaks已经说过可能是解决这个问题的最好方法。我不知道这是否会起作用,但是,如果将此放在现有路线的上方会发生什么情况(现在您的global.asax中会有两个)?

 routes.MapRoute(
      "Filtered", 
      "{controller}/{action}/{id}?filterLevel={filterLevel}&filterDate={filterDate}", 
      new 
       { 
        controller = "Home", 
        action = "Index", 
        id = UrlParameter.Optional, 
        filterDate = DateTime.Now.AddDays(-1), 
        filterLevel = "INFO" 
       } 
      ); 

此外,它只是想到,我不喜欢SLaks的解决方案的原因是,它可能是重复的。由于您只有一个路由,因此这些参数可能表示全局功能,而不是操作范围的功能。您可以通过在每个控制器上的操作筛选器中添加值来解决此问题,或者您可以使用自定义路由处理程序将其应用于全局。其中任何一个都可以让您将filterLevelfilterDate字段带出您的路线定义,并且仍然可以获得您想要的范围。那么在查询字符串中传递参数Html.ActionLink()应该没问题。

为了与路由处理做到这一点,你的路线定义修改为:

 routes.Add(
      new Route(
        "{controller}/{action}/{id}", 
        new RouteValueDictionary(new{ controller = "Home", action = "Index", id = UrlParameter.Optional}), 
        new CustomRouteHandler())); 

你实现路由处理的将是这样的:

public class CustomRouteHandler : IRouteHandler 
{ 
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     var routeValues = requestContext.RouteData.Values; 
     if(!routeValues.ContainsKey("filterLevel")) 
     { 
      routeValues.Add("filterLevel","INFO"); 
     } 
     if(!routeValues.ContainsKey("filterDate")) 
     { 
      routeValues.Add("filterDate", DateTime.Now.AddDays(-1)); 
     } 
     var mvcRouteHandler = new MvcRouteHandler(); 
     return (mvcRouteHandler as IRouteHandler).GetHttpHandler(requestContext); 
    } 
} 
1

我认为违约是始终在URL中定义条目,你不能定义默认省略的东西不是在核心URL,以及其他任何作为查询字符串传递。

有趣的问题。

HTH。

1

你应该在你的方法指定默认值,就像这样:

public ActionResult Machine(string id, DateTime? filterDate = null, string filterLevel = "INFO") 
{ 
    filterDate = filterDate ?? DateTime.Now.AddDays(-1); 
    var model = new LogListViewModel { LogEntries = logEntries }; 
    return View(model); 
} 
1

如果有没有 URL模式指定为默认值,则不能覆盖他们,因为他们是用于在匹配URL生成路由时确定路由选择。

让我给你举个例子。假设你有以下两条路线。

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

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

请注意,“filterLevel”有一个默认值,但URL模式中没有“{filterLevel}”参数。

,当你这样做哪些URL应该匹配?

@Html.ActionLink(item.MachineName, "Machine", 
new { id = item.MachineName, filterLevel = "RANDOM" }, null) 

如果您可以覆盖filterLevel的默认值,那么您会期望两个路径匹配。但这没有道理。在这种情况下,两者都不匹配,因为filterLevel不在URL模式中,因此提供的filterLevel必须匹配默认值。这样,你可以这样做:

@Html.ActionLink(item.MachineName, "Machine", 
new { id = item.MachineName, filterLevel = "INFO" }, null) 

//AND 

@Html.ActionLink(item.MachineName, "Machine", 
new { id = item.MachineName, filterLevel = "DEBUG" }, null) 

分别为第一和第二路由生成一个URL。

这种困惑是为什么我总是推荐到always use named routes