需要帮助规范化asp.net mvc中的HTTP GET表单

时间:2011-01-20 04:27:37

标签: asp.net-mvc asp.net-mvc-routing query-string http-get canonical-link

我在asp.net mvc网站上有一个表单,它有三个用途:分页,排序和搜索。这些项目都应以相同的形式呈现,因为返回正确的搜索结果取决于所有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中,有两种操作方法:

[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中为关键字添加下划线并在搜索中删除它来使其工作,但这非常hacky)。

任何帮助?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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

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