2

My question is very similar other questions. When using an ActionLink in MVC .Net 4.5, I am getting a query string for one parameter, instead of just a URL path. I tried the solution HERE, but it did not work.

CODE-

Inside RouteConfig.cs -

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

  routes.MapRoute(
            name: "MyControllerRoute",
            url: "{controller}/{action}/{id}/{description}",
            defaults: new { controller = "MyController", action = "MyAction", id = UrlParameter.Optional, description = UrlParameter.Optional }
        );

Inside HomeController.cs -

public ActionResult Index(){
  --do stuff--
   return View();
}

Inside MyController.cs -

public ActionResult Vote(int id, string description){
   --do stuff--
   return View();
}

Inside Index.cshtml

@Html.ActionLink(
       "This is stuff", 
       "MyAction", 
       "MyController", 
       new { id = 123, description = "This-is-stuff"  }, 
       null)

GETTING THIS RESULT - (NOT WHAT I WANT)

<a href="/MyController/MyAction/123?description=This-is-stuff">This is stuff</a>

DESIRED RESULT - (HOW CAN I GET THIS?)

<a href="/MyController/MyAction/123/This-is-stuff">This is stuff</a>
4
  • 1
    Move MyControllerRoute before the default route. And remove id = UrlParameter.Optional, description = UrlParameter.Optional from the MyControllerRoute route (only the last parameter can be marked as optional Commented Jul 11, 2016 at 4:52
  • That worked, thanks Stephen! Do you want to make an "official" answer so I can give you credit? If not, I will make an official answer for others to reference. Commented Jul 11, 2016 at 5:20
  • The reason I haven't added an answer yet is because its unclear why you would mark both parameters in the MyControllerRoute route as optional. Is there ever a case where you would only provide either id or description? (in which case you would need another solution) Commented Jul 11, 2016 at 5:22
  • They should not have been optional. That was a mistake. They will both always be needed. Commented Jul 11, 2016 at 5:24

1 Answer 1

1

You need to swap the order of the routes. I would also recommend that you use the controller name (and optionally the action name) in the url definition to prevent possible conflicts with other routes. In addition, only the last parameter can be marked as UrlParameter.Optional (otherwise if only one of the parameters were provided, the route would be ignored and the url would revert to using query string values). Your definitions should be (in order)

routes.MapRoute(
    name: "MyControllerRoute",
    url: "MyController/MyAction/{id}/{description}",
    defaults: new { controller = "MyController", action = "MyAction" }
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks so much for this, Stephen. Could you explain why the order matters and why it was messing up the URL?
When you use ActionLink() (or any other methods that generate urls), the method looks up the route dictionary generated by your route definitions and steps through them in the order that they are defined and stops searching as soon as possible match is found which is why the order is significant. This article - the section titled How URLs Are Matched to Routes - explains the behavior.
Tried to find Attribute Routing in that article with no success. Can you tell us @StephenMuecke where Attribute routes factor in 'the order' ?
@ScottK.Fraley, I'm not sure what you mean. Do you have multiple [Route] attributes applied to a method? Note that the RouteAttribute has an Order property.
@StephenMuecke Well, I have a [RoutePrefix("controller")] on my Controller class, then a [Route("Index/{rowId}/")] on the GET version of my Index method, but when called by a Uri with a query string parameter (.../Index?rowId=5058) vs. a "Url Parameter" (.../Index/5058/) I'd get a 404. I mention all of this because I'd SWEAR I've dealt with this before and the answer was simply to have that final '/' at the end of the [Route()] string. Also, I haven't touched the 'normal' route config stuff attribute routing came long. Lastly; tried it your way and still got the dang 404.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.