JK.
JK.

Reputation: 21822

MVC Routing Html.ActionLink creates URLs with ?id=1 instead of /id

When I use Html.ActionLink() the URL created is not in the desired format:

Html.ActionLink(Model.ProductCode, "Update", new { id = Model.ProductId })

Makes this URL

/Update?id=1

When I want to have this URL:

/Update/1

What routing options create the 2nd URL? This is our preferred URL style.

Both URLs work and the correct page is displayed - however we want to only use /id

In Global.asax the MVC default route handles both URLs

routes.MapRoute(
    "Default",                                               // Route name
    "{controller}/{action}/{id}",                            // URL with parameters
    new { controller = "Home", action = "Index", id = "" }); // Parameter defaults

Upvotes: 6

Views: 2981

Answers (4)

Joe
Joe

Reputation: 2601

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

Upvotes: 0

Alex.Buchatsky
Alex.Buchatsky

Reputation: 1

I've just stumbled upon this and decided to answer. It turned out that both Url.Action() and Html.ActionLink() use the first route in the route collection to format the resulted URL. So, the first mapped route in the RegisterRoutes() shoild be:

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

instead of "{controller}/{action}/{id}". The route name (i.e. "Default") does not matter, only the order does matter

Upvotes: 0

rejj
rejj

Reputation: 1216

See This question/answer.

Which version of MVC are you using? If you're in MVC3, you'll need to add a fourth parameter to your call to Html.ActionLink(), passing in a null.

Upvotes: 0

Tommy
Tommy

Reputation: 39807

I can replicate the issue by having a route about my default route that still matches the general pattern. Example:

routes.MapRoute(
                            "Default2", // Route name
                            "{controller}/{action}", // URL with parameters
                            new { controller = "Home", action = "Index"} // Parameter defaults
                        );

When places above my default route, I get the ?id=1 in my URL. Can you confirm that this ActionLink is not matching any routes above the route that you are expecting it to match?

EDIT: The below does not impact the URL

However, it could still be advantageous to use the UrlParameter.Optional in other scenarios. Leaving for prosperity unless mob rule says otherwise.

new UrlParameter.Optional value. If you set the default value for a URL parameter to this special value, MVC makes sure to remove that key from the route value dictionary so that it doesn’t exist.

I think you need to adjust your route slightly. Change id = "" to id = UrlParameter.Optional

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

This is what we use for the default route and the behavior that you are looking for is how our applications behave.

Upvotes: 2

Related Questions