0

我在一个 asp.net mvc 站点中有一个表单,它有 3 个用途:分页、排序和搜索。这些项目都应该以相同的形式呈现,因为返回正确的搜索结果取决于所有 3 个方面的变量。我想要做的是将参数移出查询字符串并将它们放在规范的 URL 中。

我快到了,这是我到目前为止的 3 个路由配置(使用 T4MVC 作为区域、控制器和操作名称):

context.MapRoute(null,
    "my-area/my-widgets/search/{size}-results-max/page-{page}/order-by-{sort}",
    new
    {
        area = MVC.MyArea.Name,
        controller = MVC.MyArea.MyWidgets.Name,
        action = MVC.MyArea.MyWidgets.ActionNames.Search,
        page = UrlParameter.Optional,
        size = UrlParameter.Optional,
        sort = UrlParameter.Optional,
    }
);

context.MapRoute(null,
    "my-area/my-widgets/canonicalize-search",
    new
    {
        area = MVC.MyArea.Name,
        controller = MVC.MyArea.MyWidgets.Name,
        action = MVC.MyArea.MyWidgets.ActionNames.CanonicalizeSearch,
    }
);

context.MapRoute(null,
    "my-area/my-widgets",
    new
    {
        area = MVC.MyArea.Name,
        controller = MVC.MyArea.MyWidgets.Name,
        action = MVC.MyArea.MyWidgets.ActionNames.CanonicalizeSearch,
    }
);

视图中的表单使用以下语法提交到 CanonicalizeSearch 路由:

@using (Html.BeginForm(MVC.MyArea.MyWidgets.CanonicalizeSearch(), 
    FormMethod.Get))

在 MyWidgetsController 中,有 2 个操作方法:

[ActionName("canonicalize-search")]
public virtual RedirectToRouteResult CanonicalizeSearch(string keyword, 
    int page = 1, int size = 10, string sort = "Title-Ascending")
{
    var result = RedirectToRoutePermanent(new
    {
        area = MVC.MyArea.Name,
        controller = MVC.MyArea.MyWidgets.Name,
        action = MVC.MyArea.MyWidgets.ActionNames.Search,
        page = page,
        size = size,
        sort = sort,
        keyword = keyword,
    });
    return result;
}

[ActionName("search")]
public virtual ViewResult Search(string keyword, 
    int page = 1, int size = 10, string sort = "Title-Ascending")
{
    // code to perform query
    return View(model);
}

这适用于将所有查询字符串变量移动到规范化路由中,除了关键字。如果我将关键字参数添加到第一个路由,CanonicalizeSearch 操作仅在关键字不为空、空或空格时重定向到搜索操作。这不好,因为当没有输入关键字时,它会导致无法浏览页面结果。

我想我已经尝试了一切——在控制器中给关键字一个默认值,添加第四条路由,将关键字添加到其他 3 个参数等。但是我似乎可以让它工作的唯一方法是保持关键字为一个查询字符串参数。(实际上,我可以通过在 CanonicalizeSearch 中的关键字前加上下划线并在 Search 中将其剥离来使其工作,但这很 hacky)。

有什么帮助吗?

4

2 回答 2

1

您是否尝试在第一条路线中设置UrlParameter.Optional参数keyword?听起来很明显和愚蠢,但你从来没有排除过它。

于 2011-01-20T04:59:17.047 回答
1

我想我通过尝试解决另一个问题偶然发现了一个更好的解决方案。

假设有人在关键字框中输入“我的搜索词”。提交导致 CanonicalizeSearch 方法路由到路径:

/my-area/my-widgets/search/10-results-per-page/page-1/
    order-by-Title-Ascending/my%20search%20terms

那些 %20 符号很烦人。我希望 URL 看起来像这样:

/my-area/my-widgets/search/10-results-per-page/page-1/
    order-by-Title-Ascending/my-search-terms

我可以通过以下方式完成此操作(注意从永久重定向到临时重定向的更改):

[ActionName("canonicalize-search")]
public virtual RedirectToRouteResult CanonicalizeSearch(string keyword, 
    int page = 1, int size = 10, string sort = "Title-Ascending")
{
    var result = RedirectToRoute(new
    {
        area = MVC.MyArea.Name,
        controller = MVC.MyArea.MyWidgets.Name,
        action = MVC.MyArea.MyWidgets.ActionNames.Search,
        page = page,
        size = size,
        sort = sort,
        keyword = (string.IsNullOrWhiteSpace(keyword)) 
            ? "no-keywords" : keyword.Replace(' ', '-'),
    });
    TempData["keyword"] = keyword;
    return result;
}

[ActionName("search")]
public virtual ViewResult Search(string keyword, 
    int page = 1, int size = 10, string sort = "Title-Ascending")
{
    keyword = TempData["keyword"] as string ?? keyword;
    // code to perform query
    return View(model);
}

这解决了我在这里发布的问题和 %20 符号的删除。每当关键字为空或空格时,它将呈现 URL

/my-area/my-widgets/search/10-results-per-page/page-1/
    order-by-Title-Ascending/no-keywords

...并且路线将始终匹配。

于 2011-01-20T06:19:30.923 回答