我正在实现一个网站,其搜索可以通过从两个不同路径访问的Controller方法执行。一个挂起默认路由(使用Post数据或搜索参数的查询字符串值),一个是SEO优化网址,它通过两个路由值获取位置和短语。第二条路线如下:
routes.MapRoute("SEOSearch", "Search/{seoLocation}/{seoSearchString}",
new { controller = "Search",
action = "SEOResults",
seoLocation = (string)null,
seoSearchString = (string)null });
您可能想知道为什么我有两条不同的路线 - 这是因为搜索提供了许多其他参数,而不仅仅是位置和短语 - 但我希望SEO'd网址将这两个包含在路径中,而不是使用查询字符串
正如我所说,第一条路线是默认的/controller/action/id
路线,正确的控制器/动作是“搜索”和“索引”。
最后,两个动作在控制器中执行相同的搜索操作,并且两者都将使用索引视图呈现其结果,因为它们的结果模型是相同的。
在索引视图中,我使用搜索词的局部视图,另一部分用于结果,另一部分用于分页。
我遇到的问题是让分页控件呈现正确的链接,以使用与当前请求相同的URL格式启动当前搜索下一页。
因此,假设您已导航到/Search?Location=[location]&Phrase=[phrase]
,我希望寻呼机生成的第2页链接为/Search?Location=[location]&Phrase=[phrase]&Page=2
。
但是,如果您使用/Search/[location]/[phrase]
启动了搜索,我希望第2页的链接为/Search/[location]/[phrase]?Page=2
。
我最接近的是:
<%= Html.RouteLink("Previous Page",
RouteHelpers.Combine(ViewContext.RouteData.Values,
new RouteValueDictionary() { { "Page", Model.Results.PageNo + 1}})) %>
其中RouteHelpers.Combine
是我编写的扩展,它接受两个对象并将它们合并到一个RouteValueDictionary中。通过将RouteValues作为当前请求,我能够持久保存当前的Controller和Action名称(无需知道它们是什么) - 但是这会错过ModelState中的一些重要信息 - 即提供的任何额外搜索参数 - 即如果当前的Url为/Search/London/Widgets
,则会有效,但如果它是/Search/London/Widgets?PageSize=50
,则PageSize
参数不会持久保存到外发链接中。
更糟糕的是,如果它是非SEO的网址 - 即/Search?Location=London&Phrase=Widgets
,则传出的网址只会变为/Search?Page=x
。
我的搜索参数从请求中读取到模型类型中,然后被提供给主页和寻呼机本身,所以理论上我可以简单地从那里生成它们 - 但我最终得到了所有url中的参数,即使它们是默认值(因此不需要提供) - 所以url看起来很难看。
我如何实现我想要的目标!?我觉得我突然对MVC一无所知!
答案 0 :(得分:3)
您不必使用RouteHelper
来合并路线值。当您使用ActionLink时,这些值会自动与您的匿名对象结合使用。将覆盖所有现有值并添加新值。这个电话会为你做这件事:
RouteValueDictionary values = RouteValuesHelpers.MergeRouteValues(
actionName,
controllerName,
requestContext.RouteData.Values,
routeValues,
includeImplicitMvcValues); // true for ActionLink; false for RouteLink
routeValues
是来自匿名对象的值。它们合并到requestContext.RouteData.Values
。
所以你仍然可以使用:
Html.ActionLink(
"whatever",
this.ViewContext.RouteData.Values["action"],
this.ViewContext.RouteData.Values["controller"],
new { Page = /* whatever needs to be */ },
null)
最后必须为空,因此不会将匿名对象与HTML属性混淆。
但是你确实遇到了路由问题,除非你还在默认路由上设置路由约束以仅使用某些操作,否则你的/Search/SeoLocation/SeoSearchString
仍将由默认路由处理,SeoLocation
成为你的行动和SeoSearchString
id
。
反正。如果您的代码是正确的,那么所有这些值都应该在您的路由值字典中,并按预期传播到您的链接。