нужна помощь, канонизирующая форму HTTP GET в asp.net mvc - PullRequest
0 голосов
/ 20 января 2011

У меня есть форма на сайте 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 есть 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 будет перенаправлено на действие «Поиск» только в том случае, если ключевое слово не является пустым или пустым.Это не хорошо, так как делает невозможным просмотр результатов на странице, когда не введено ключевое слово.

Я думаю, что я все перепробовал - присвоив ключевому слову значение по умолчанию в контроллере, добавив 4-й маршрут, который добавляет ключевое слово к трем другим параметрам и т. Д. Однако, единственный способ, которым я могу это сделать, - эторабота заключается в сохранении ключевого слова в качестве параметра строки запроса.(На самом деле я могу заставить его работать, добавив подчеркивание к ключевому слову в CanonicalizeSearch и убрав его в поиске, но это довольно забавно).

Любая помощь?

Ответы [ 2 ]

1 голос
/ 20 января 2011

Я думаю, что наткнулся на лучшее решение, пытаясь решить другую проблему.

Скажите, что кто-то вводит "мои условия поиска" в поле для ключевых слов. Отправка, которая заставляет метод 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

... и маршрут всегда будет совпадать.

1 голос
/ 20 января 2011

Вы пытались установить UrlParameter.Optional для параметра keyword в вашем первом маршруте? Звучит очевидно и глупо, но вы никогда не исключали этого.

...