Переключение на {controller} / {id} / {action} прерывает RedirectToAction - PullRequest
9 голосов
/ 06 июля 2011

Я пытаюсь использовать правильные REST URL с MVC. Для этого я переключил маршрутизацию по умолчанию с:

{controller}/{action}/{id}

до

{controller}/{id}/{action}

так вместо:

/Customer/Approve/23

есть сейчас

/Customer/23/Approve

ActionLink работает нормально, но следующий код в CustomerController:

[CustomAuthorize]
[HttpGet]
public ActionResult Approve(int id)
{
    _customerService.Approve(id);
    return RedirectToAction("Search");  //Goes to bad url
}

заканчивается на URL /Customer/23/Search. Пока оно должно идти на /Customer/Search. Как-то запоминается 23 (id).

Вот мой код маршрутизации в global.cs

    routes.MapRoute(
        "AdminRoute", // Route name
        "{controller}/{id}/{action}", 
        new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        new { id = new IsIntegerConstraint() }
        );

    routes.MapRoute(
        "Default", 
        "{controller}/{action}", 
        new { controller = "Home", action = "Index" });

Если я переключаю две функции, RedirectToAction начинает работать, но с использованием:

Html.ActionLink("Approve", "Approve", new { Id = 23})

Теперь генерирует /Customer/Approve?id=23 вместо /Customer/23/Approve.

Я мог бы указать прямые URL-адреса, такие как ~/Customer/23/Approve, вместо использования ActionLink и RedirectToAction, но предпочел бы придерживаться функций, предоставляемых MVC.

Ответы [ 6 ]

2 голосов
/ 07 июля 2011

Когда вы используете RedirectToAction (), внутренне MVC будет использовать существующие данные маршрута (включая значение Id) для построения URL. Даже если вы передадите нулевой RouteValueDictionary, существующие данные маршрута будут объединены с новыми пустыми данными значения маршрута.

Единственный способ обойти это, я вижу, это использовать RedirectToRoute () следующим образом:

return RedirectToRoute("Default", new { controller = "Customer", action = "Search"});

Counsellorben

1 голос
/ 06 июля 2011

Попробуйте передать новый (пустой) RouteValueDictionary в вашем контроллере

return RedirectToAction("Search", new System.Web.Routing.RouteValueDictionary{});

А здесь:

Html.ActionLink("Approve", "Approve", new { Id = 23})

Я даже не знаю, как он может подобрать контроллер Клиента, поскольку вы его нигде не определяете. Попробуйте предоставить и контроллер, и действие для помощника ActionLink.

0 голосов
/ 31 августа 2014

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

routes.MapRoute(
    "Default", 
    "{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Если в вашем маршруте по умолчанию действительно нет идентификатора, вы также можете попробовать:

routes.MapRoute(
    "Default", 
    "{controller}/{action}", 
    new { controller = "Home", action = "Index", id = string.Empty });
0 голосов
/ 15 сентября 2011

У меня была похожая проблема.Значения маршрутов, которые были переданы моему действию контроллера, использовались повторно, когда я пытался перенаправить пользователя с помощью RedirectToAction , даже если я не указал их в новом RouteValueDictionary .Решение, с которым я пришел (после прочтения поста Counsellorben), состояло в том, чтобы очистить RouteData для текущего запроса.Таким образом, я мог бы запретить MVC объединять значения маршрутов, которые я не указал.

Итак, в вашей ситуации вы могли бы сделать что-то вроде этого:

[CustomAuthorize]
[HttpGet]
public ActionResult Approve(int id)
{
    _customerService.Approve(id);
    this.RouteData.Values.Clear();  //clear out current route values
    return RedirectToAction("Search");  //Goes to bad url
}
0 голосов
/ 18 июля 2011

Удалить эту часть:

id = UrlParameter.Optional

может решить проблему; когда вы определяете «id» в качестве необязательного параметра и у вас есть карта «Default», «Default» и «AdminRoute» совпадают! С уважением.

0 голосов
/ 07 июля 2011

Попробуйте передать данные текущего маршрута метону в действии вашего контроллера:

return RedirectToAction("Search", this.RouteData.Values);
...