Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switching to {controller}/{id}/{action} breaks RedirectToAction

I am trying to use proper REST urls with MVC. To do that I switched default Routing from:

{controller}/{action}/{id}

to

{controller}/{id}/{action}

so instead of:

/Customer/Approve/23

there is now

/Customer/23/Approve

ActionLink seems to work ok, but the following code in CustomerController:

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

ends up on url /Customer/23/Search. While it should be going to /Customer/Search. Somehow it remembers 23 (id).

Here is my routing code in 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" });

If I switch the two functions, RedirectToAction starts working, but using:

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

Now generates /Customer/Approve?id=23, instead of /Customer/23/Approve.

I could specify direct urls like ~/Customer/23/Approve, instead of using ActionLink and RedirectToAction, but would rather stick to functions provided by MVC.

like image 242
Eric P Avatar asked Jul 06 '11 13:07

Eric P


2 Answers

When you use RedirectToAction(), internally, MVC will take the existing route data (including the Id value) to build the url. Even if you pass a null RouteValueDictionary, the existing route data will be merged with the new empty route value data.

The only way around this I can see is to use RedirectToRoute(), as follows:

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

counsellorben

like image 175
counsellorben Avatar answered Nov 03 '22 20:11

counsellorben


Try passing in new (empty) RouteValueDictionary in your controller

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

And here:

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

I don't even know how can it pick up the Customer controller, since you are not specifying it anywhere. Try providing both controller and action to ActionLink helper.

like image 1
mare Avatar answered Nov 03 '22 20:11

mare