【问题标题】:The urlHelper build wrong path.. What is a rison for this?urlHelper 构建错误的路径.. 这有什么风险?
【发布时间】:2016-05-30 09:13:31
【问题描述】:

我有一个路由规则:

routes.MapRoute("HotToursPage",
            "HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}/{param4}/{param5}",
            new
            {
                controller = "HotTours",
                action = "Index",
                countryTo = UrlParameter.Optional,
                resort = UrlParameter.Optional,
                param1 = UrlParameter.Optional,
                param2 = UrlParameter.Optional,
                param3 = UrlParameter.Optional,
                param4 = UrlParameter.Optional,
                param5 = UrlParameter.Optional
            }
        );

在我的代码中:

var dictionary = new RouteValueDictionary();
        aaa.Add("countryTo", countryToInfo.Translit);
        aaa.Add("resort", resort);
        aaa.Add("param1", param1);
string url = urlHelper.Action("Index", "HotTours", dictionary);

如果有param5、param6等,那么

url =/hottours/?countryTo=tailand&resort=bangkok&param1=price_from_50000,

但如果我删除 param5、param6 和其他,那么一切正常:

url =/hottours/tailand/bangkok/price_from_50000

为什么如果段数小于 7,一切正常?我需要 9 个段,但 urlHelper 在这种情况下构建了错误的 url。

【问题讨论】:

  • 只有最后一个参数可以是可选的(除非您提供所有参数,否则路由引擎无法确定哪个值属于哪个段,因此将这些值添加为查询字符串值)
  • 不,不仅最后一个参数可能是可选的。在我的情况下,所有参数都可以是可选的。我可以写 localhost:9285/hottours/tailand/bangkok/price_from_50000 或 localhost:9285/hottours/tailand/bangkok/price_from_50000/from_moscow 并且所有的工作都是正确的。直到我在路由规则中写的变量不超过 6 个。当我在路由规则中添加超过 6 个变量时,urlHelper 构建 url 错误
  • 不,你不明白 只有路由定义中的最后一个参数可以用UrlParameter.Optional标记。如果您尝试使用Url.Action(),如果您不提供所有参数,它将生成查询字符串值(不是路由值)。删除countryTo = UrlParameter.Optional, ...... param4 = UrlParameter.Optional,,只留下param5 = UrlParameter.Optional
  • 但是为什么所有工作都是正确的,当我写 url localhost:9285/hottours/tailand/bangkok/price_from_50000 和 localhost:9285/hottours/tailand/bangkok/price_from_50000/from_moscow 和 localhost:9285/hottours /泰国/曼谷/?并且 UrlHelper 构建 url 绝对正确,当我在 RouteValueDictionary 中给出 2、3、.. 6 参数时
  • 除非参数完全按顺序添加,否则不会 - 尝试string url = urlHelper.Action("Index", "HotTours", new { param3 = "xxxx"); 了解。但是你的路由只有 7 个段,所以任何额外的都必须是查询字符串值

标签: asp.net-mvc routes segments urlhelper


【解决方案1】:

在构建 URL 时,您必须提供 URL 模式中的所有路由值。有一个例外 - 当最后一个参数是可选的时,您不需要包含它。

因此,要始终如一地处理长 URL 模式中可能是可选的段,您需要多个路由。每条路线只能有一个UrlParameter.Optional,并且它必须是最右边的路段。

routes.MapRoute("HotToursPage3",
    "HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}/{param4}/{param5}",
    new
    {
        controller = "HotTours",
        action = "Index",
        param5 = UrlParameter.Optional
    }
);

routes.MapRoute("HotToursPage2",
    "HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}",
    new
    {
        controller = "HotTours",
        action = "Index",
        param3 = UrlParameter.Optional
    }
);

routes.MapRoute("HotToursPage1",
    "HotTours/{countryTo}/{resort}/{param1}",
    new
    {
        controller = "HotTours",
        action = "Index",
        param1 = UrlParameter.Optional
    }
);

注意:我在这里假设您的{countryTo}{resort} 参数是必需的。将它们设为可选似乎并不明智。但是,如果我弄错了,您需要另一条路线来处理这两个段是可选的,或者您应该为它们提供合理的默认值。一般来说,如果某个值没有合理的默认值,则 URL 中应该是必需的。

请注意,您仍然只能将一个片段设为可选如果没有提供它右侧的片段。因此,这种组合将起作用:

var dictionary = new RouteValueDictionary();
dictionary.Add("countryTo", "test1");
dictionary.Add("resort", "test2");
dictionary.Add("param1", "test3");
var url = Url.Action("Index", "HotTours", dictionary);

但是这种组合仍然会构建一个查询字符串:

var dictionary = new RouteValueDictionary();
dictionary.Add("countryTo", "test1");
dictionary.Add("resort", "test2");
dictionary.Add("param1", "test3");
dictionary.Add("param2", "test4");
dictionary.Add("param5", "test5");
var url = Url.Action("Index", "HotTours", dictionary);

如果您希望所有 5 个参数都是可选的(并且以任何顺序),您应该使用查询字符串,而不是将它们放入路径中。

routes.MapRoute("HotToursPage",
    "HotTours/{countryTo}/{resort}",
    new
    {
        controller = "HotTours",
        action = "Index"
    }
);

另一种选择(我不推荐)是建立一系列具有标识符段的路由,这样您就可以按任何顺序放置值。见ASP.Net MVC Handling Segments with Route

【讨论】:

  • 好的,我理解并且我会执行所有这些规则,但是请解释一下,如果只有一个参数可能是 UrlParameter.Optional,接下来如何使用我的 previuos 规则:localhost:9285/hottours/tailand/bangkok/price_from_50000localhost:9285/hottours/tailand/bangkok/price_from_50000/… ?
  • 在我上面的示例中,这两个 URL 都将匹配(并生成自)HotToursPage2,因为最后一个参数 {param3} 是可选的。它们不会匹配HotToursPage3,因为缺少{param4},因此路由引擎将尝试列表中的下一条路由,直到找到匹配项。
【解决方案2】:

正如您在下面提到的那样,不是主要原因

Http.sys 服务的编码默认为每个 Url 段最多 260 个字符。

此上下文中的“Url 段”是Url 中“/”字符之间的内容。例如:

可以通过注册表设置更改允许的最大 URL 段长度:

Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
Value: UrlSegmentMaxLength
Type: REG_DWORD
Data: (Your desired new Url segment maximum allowed length, e.g. 4096)

允许的最大值为 32766。如果指定了更大的值,它将被忽略。

需要重新启动 PC 才能使对此设置的更改生效。

【讨论】:

  • 感谢您的重播,但我的情况与片段长度无关。我的网址始终是:localhost:9285/hottours/tailand/bangkok/price_from_50000 我不会更改它。 Params2... params5 仅在 RouteConfig 中描述当我在路由规则中添加超过 6 个变量时,urlHelper 构建 url 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 2018-09-11
相关资源
最近更新 更多