MVC Attribute routing with Url.Action not resolving route
Asked Answered
E

3

15

I cannot get @Url.Action to resolve to the url I am expecting based on the attribute route I have applied:

My action (SearchController but with [RoutePrefix("add")])

     [Route("{searchTerm}/page/{page?}", Name = "NamedSearch")]
     [Route("~/add")]
     public ActionResult Index(string searchTerm = "", int page = 1)
     {
       ...
     }

Call to Url.Action

@Url.Action("Index", new { controller = "Search", searchTerm = "replaceMe", page = 1 })

This results in a url of

/add?searchTerm=replaceMe&page=1

I would expect

/add/replaceMe/page/1

If I type the url manually then it resolves to the correct action with the correct parameters. Why doesn't @Url.Action resolve the correct url?

Excusatory answered 28/3, 2016 at 20:44 Comment(0)
A
20

Since you have a name for your pretty route definition, you may use the RouteUrl method.

@Url.RouteUrl("NamedSearch", new {  searchTerm = "replaceMe", page = 1})

And since you need add in the url, you should update your route definition to include that in the url pattern.

[Route("~/add")]
[Route("~/add/{searchTerm?}/page/{page?}", Name = "NamedSearch")]
public ActionResult Index(string searchTerm = "", int page = 1)
{
 // to do : return something
}
Andersen answered 28/3, 2016 at 20:58 Comment(4)
Thanks, adding a name to both routes and using RouteUrl was the only reliable way of getting this working for both routes.Excusatory
For those who come here and want a route to an action in an ApiController: @Url.HttpRouteUrl gets the trick in this case;-)Lithograph
This helped me pass the correct Route to Troy Goode's PagedList. Was racking my head for almost a day!Adao
What if the search term and page are dynamic parameters??Suu
R
5

Routes are order sensitive. However, attributes are not. In fact, when using 2 Route attributes on a single action like this you may find that it works on some compiles and not on others because Reflection does not guarantee an order when analyzing custom attributes.

To ensure your routes are entered into the route table in the correct order, you need to add the Order property to each attribute.

[Route("{searchTerm}/page/{page?}", Name = "NamedSearch", Order = 1)]
[Route("~/add", Order = 2)]
public ActionResult Index(string searchTerm = "", int page = 1)
{
    return View();
}

After you fix the ordering problem, the URL resolves the way you expect.

@Url.Action("Index", new { controller = "Search", searchTerm = "replaceMe", page = 1 })

// Returns "/add/replaceMe/page/1"
Roxannaroxanne answered 29/3, 2016 at 4:17 Comment(1)
Thanks, I found that this fixed the 'NamedSearch' route but broke the base route (order = 2) if I used @Html.ActionLink("Add Issues", "Index", new { controller = "Search" }). The only reliable way I could get this to work was to add names to both.Excusatory
W
0

To return full URL use this

@Url.Action("Index", new { controller = "Search", searchTerm = "replaceMe", page = 1}, protocol: Request.Url.Scheme)

// Returns "http://yourdomain.com/add/replaceMe/page/1"

Hope this helps someone.

Wootan answered 7/5, 2017 at 23:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.