【问题标题】:ASP.NET MVC 3 Multiple routes to accommodate filteringASP.NET MVC 3 多个路由以适应过滤
【发布时间】:2011-07-16 09:23:16
【问题描述】:

我正在构建各种搜索,其中有各种可用的过滤器。

我想将这些过滤器选项映射到一个不错的 URL - 但是我在设置路由时遇到了问题,我觉得必须有更好的方法来做到这一点。

我对我的Flights 控制器执行了以下操作(作为示例):

public ActionResult Find(string origin, string destination, DateTime? DepartureDateTime, int? flexibleDays, int? Page, string someValue)
{
    //do fun stuff here
}

我希望以下所有 URL 都路由到此操作:

example.com/Flights/
example.com/Flights/From/London/
example.com/Flights/To/Fiji/
example.com/Flights/From/London/To/Fiji/
example.com/Flights/From/London/To/Fiji/2011-07-16/    (here I wish a default value of zero be applied to flexibleDays)
example.com/Flights/From/London/To/Fiji/2011-07-16/flexible/   (here I wish a non-zero default value to be set to the flexibleDays parameter)
example.com/Flights/From/London/To/Fiji/2011-07-16/flexible/5/    (here a value is specified for flexibleDays)

我希望前两件事的顺序也是可逆的,例如:

example.com/Flights/From/London/To/Fiji/
example.com/Flights/To/Fiji/From/London/

除了那些“基本”网址,我还希望能够添加查询字符串:

example.com/Flights/From/London/To/Fiji/2011-07-16/flexible/5/?Page=2&someValue=foobar

这些查询字符串参数在不存在时将为空/空。

现在我已经描述了我想要的东西,这是我的第一次破解。基本上,我刚刚开始为搜索的每个排列添加不同的路由规则。

routes.MapRoute(
            "Bad1", // Route name
            "Flights/from/{origin}/to/{destination}/{DepartureDateTime}/flexible/{flexibleDays}", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional, flexibleDays = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Bad2", // Route name
            "Flights/to/{destination}/from/{origin}/{DepartureDateTime}/flexible/{flexibleDays}", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional, flexible = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Bad3", // Route name
            "Flights/from/{origin}/to/{destination}/{DepartureDateTime}/", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Bad4", // Route name
            "Flights/to/{destination}/from/{origin}/{DepartureDateTime}/", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Bad5", // Route name
            "Flights/from/{origin}/{DepartureDateTime}/flexibe/{flexibleDays}", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional, flexible = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Bad6", // Route name
            "Flights/to/{destination}/{DepartureDateTime}/flexible/{flexibleDays}", // URL with parameters
            new { controller = "Flights", action = "Find", DepartureDateTime = UrlParameter.Optional, flexible = UrlParameter.Optional } // Parameter defaults
        );

现在这主要是有效的,但它正在迅速失控。假设我使用的这个例子是简化的,并且有更多的查询字符串,例如,还有一些像上面的/flexible/{flexibleDays}这样的“URL参数”。

是否有更好、更易维护、更可扩展的解决方案?还是我只需要非常仔细地绘制出我想要的每一个 URL 组合?

另外,我愿意接受有关其他 URL 结构的建议。虽然我仍然对是否有更好的方法来设置我指定的路线感兴趣。

【问题讨论】:

  • 路线一定是这样吗?或者你也可以考虑使用查询字符串?
  • 不,不一定是这样,但是我并不真正希望所有内容都是查询字符串。我想这是主观的,但我认为example.com/Flights/From/London/To/Fiji 看起来更好/比example.com/Flights/?from=London&to=Fiji 更具可读性,特别是当 URL 变得非常长和复杂时。 (example.com/Flights?from=London&to=Auckland&DepartureDateTime=2011-07-16&flexibleDays=5&someValue=foo)。正如我所提到的,我确实计划添加一些查询字符串,但是我希望能够“深入”到某些小节,并在此之上应用额外的过滤。

标签: asp.net-mvc asp.net-mvc-3 search routing filter


【解决方案1】:

如果不为所有可能的组合创建路线,就没有内置的方法来做你想做的事。您可以编写自定义路线,但这并不容易。您想要的基本上是解析键值对,其中键和值都可以具有默认值并且值可以具有约束。也不要忘记从这些值构建 url 并返回。

  • 来自/{字符串}
  • 到/{字符串}
  • {datetime}(无键)
  • 灵活/{int}(默认值)

DepartureDateTime 指定键会稍微简化它(=每个值都有键)。自定义路由的 url 看起来像 "Flights/{p1}/{p2}/{p3}/{p4}/" 等,其中所有参数都默认为 UrlParemeter.Optional 或“Flights/{*args}”。然后您将在GetRouteDataGetVirtualPath 中映射到所需的路由值。

另一种方法是编写基于参数创建所有组合的方法,但如果您想扩展这些参数,最终可能会损害性能。

【讨论】:

    【解决方案2】:

    为了稍微减轻您的痛苦,您可能需要考虑创建 From 和 To 操作方法。这将使您的路由更容易一些。

    作为参考,您可能会发现以下链接很有帮助。 http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

    编辑:就我个人而言,我必须在航班控制器上使用 To 和 From 操作方法,并将其余的作为 qs 变量传递:

    /Flights/From/Auckland?to=London
    /Flights/To/London?from=auckland
    

    这意味着更少的路由,同时保持你的网址干净(即使有额外的参数)

    【讨论】:

    • 所以我会有Flights/FromFlights/To 操作,然后(基本上)为所有其他情况的两个操作复制routes.MapRoute 条目?这会不会是相同数量的工作,因为我仍然必须为这两个操作指定每个路由组合?
    • 如果你想坚持你的路由,那么是的,我想它并不能保存所有这些。就我个人而言,其余部分我会使用带有 qs 变量的 from 和 to 控制器操作。所以你会有航班/从/奥克兰?到=伦敦。这减少了您的映射,并且仍然干净易读
    • 我猜这是个人选择
    猜你喜欢
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多