我正在实现一个站点,该站点具有可以通过从两个不同路径访问的 Controller 方法执行的搜索。一个挂断默认路由(使用 Post 数据或查询字符串值作为搜索参数),一个是 SEO 优化 url,它通过两个路由值获取位置和短语。第二条路线如下所示:
routes.MapRoute("SEOSearch", "Search/{seoLocation}/{seoSearchString}",
new { controller = "Search",
action = "SEOResults",
seoLocation = (string)null,
seoSearchString = (string)null });
您可能想知道为什么我有两条不同的路线 - 这是因为搜索提供了许多其他参数而不仅仅是位置和短语 - 但我希望 SEO 的 url 将这两个包含在路径中,而不是使用查询字符串.
正如我所说,第一个路由是默认的 /controller/action/id
路由,正确的 Controller /操作是“Search”和“Index”。
最后,两个 Action 在 Controller 中执行相同的搜索操作,并且都将使用索引 View 呈现它们的结果,因为它们的结果模型是相同的。
在索引 View 中,我对搜索词使用了一个部分 View ,对结果使用了另一个 View ,对分页使用了另一个 View 。
我遇到的问题是让分页控件呈现正确的链接以启动当前搜索下一页使用与当前请求相同的 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 的 url - 即 /Search?Location=London&Phrase=Widgets
,传出 url 只会变成 /Search?Page=x
.
我的搜索参数从请求中读入一个模型类型,然后被提供给主机页面和寻呼机本身,所以理论上我总是可以简单地从中生成它们——但我最终得到了所有url 中的参数,即使它们是默认值(因此不需要提供它们)- 因此 url 看起来很难看。
我如何实现我想要的!?我突然觉得我对 MVC 一无所知!
最佳答案
您不必使用 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)
末尾的 null 是必需的,因此它不会将匿名对象与 HTML 属性混淆。
但是你确实有路由问题,除非你也在你的默认路由上设置一个路由约束以仅使用某些操作,否则你的 /Search/SeoLocation/SeoSearchString
仍将由你的默认路由处理,通过 SeoLocation
成为您的操作和 SeoSearchString
id
。
无论如何。如果您的代码是正确的,那么所有这些值都应该在您的路由值字典中,并按预期传播到您的链接。
关于c# - 从使用当前路由值和模型状态的 Paging UserControl 生成 ActionLink/RouteLink,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2425650/