4

I am following this post RedirectToAction with parameter to do this

return RedirectToAction("index","service",new {groupid = service.GroupID});

for some reason, the URL it returns is not what expected. For example, instead of http://localhost/appname/service/index?groupid=5, it returns http://localhost/appname/service?groupid=5. Is there a way to make it return the expected URL?

Update: RouteConfig.cs

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

Thanks

Community
  • 1
  • 1
T L
  • 504
  • 2
  • 11
  • 27
  • Show your routes from `RouteConfig.cs` –  Jun 11 '15 at 00:41
  • 1
    I can't reproduce your issue (works fine for me). Although I suggest you change the parameter of your `Index()` method in `ServiceController` to `int id` rather than `int groupid` and use `return RedirectToAction("index","service",new {id = service.GroupID});` so it generates `../Service/Index/5` rather than `../Service/Index?groupid=5` (or add a specific route with `url: "Service/Index/{groupid}", –  Jun 11 '15 at 01:10
  • @Ryios: GroupID is an integer type. – T L Jun 11 '15 at 02:06
  • @Stephen: after changing groupid to id. It works. thank you – T L Jun 11 '15 at 02:12

2 Answers2

2

What is happening is that your default route is defined as

url: "{controller}/{action}/{id}",

but the Index() method does not have a parameter named id (its groupId) so the routing engine just uses the default value for {action}. You can generate the route you want by either changing the parameter name to id

public ActionResult Index(int id)

and in the other method use

RedirectToAction("Index","Service",new {id = service.GroupID})

or add a new route definition before the default route

routes.MapRoute(
  name: "Service",
  url: "Service/Index/{groupId}",
  defaults: new { controller = "Service", action = "Index", groupId = UrlParameter.Optional }
);

Note in both cases this will produce ../Service/Index/5 rather than ../Service/Index?groupId=5 but this is generally consider better anyway (if your really do want the second option then change the route above to just url: "Service/Index", (omit the last parameter)

1

Ok, I figured this out and reproduced it in a test environment. It is because of the routing.

In MVC when you use a generic catch all route like you did here:

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

It will always treat index as the default action mapped to the root of the controller. So localhost/somecontroller will always call index, and the url will load index at either localhost/somecontroller or localhost/somecontroller/index.

There are 2 ways to solve this problem starting with the easiest

Solution 1:

On the service controller, don't name your method Index, name it anything else, like NotIndex, IDoStuff, whatever. Just doing that will cause the redirect to redirect to Service/IDoStuff (w/e). However, doing this method means localhost/appname/service will produce a 404 (as the default action "Index" does not exist).

Solution 2: Allows you to keep actions named Index

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "Home",
            url: "Home/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
        routes.MapRoute(
            name: "Service",
            url: "Service/Index/{id}",
            defaults: new { controller = "Service", action = "Index", id = UrlParameter.Optional }
        );

Solution 2 Problem Specifying strict routes like this, breaks your default route catch all, and if you bring the default catch all route back your back to your original problem, because MVC will go through the collection of routes and apply each route to the url until it finds one that matches, the first one that matches is the one it uses, if it finds no matching route, then bam 404 (Page not found/no resource).

However, like you I want strict urls, not defaulting, so what I did is I used Solution 2.

Then to get back my root url loading Home -> Index I added a rewrite rule to my web.config

<system.webServer>
  <rewrite>
    <rules>
      <rule name="RootRedirect" stopProcessing="true">
        <match url="^$" />
        <action type="Redirect" url="/Home/Index/{R:0}" />
      </rule>
    </rules>
  </rewrite>    
</system.webServer>

For that to work you need to have the UrlRewrite features enabled in IIS (installed) so that it exists in the gac/machine config etc.

Also the reroute rule appears to be a permanent redirect rule, so the browser will redirect to it without making 2 requests to the server once the client browser has visited the site one time before.

Ryan Mann
  • 5,178
  • 32
  • 42
  • @Stephen Muecke had more information with the id != groupid part, I think both answers are technically correct. – Ryan Mann Jun 11 '15 at 02:47