Simon
Simon

Reputation: 6152

MVC Attribute routing with Url.Action not resolving route

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?

Upvotes: 15

Views: 10718

Answers (3)

Ram Pratap
Ram Pratap

Reputation: 1119

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.

Upvotes: 0

NightOwl888
NightOwl888

Reputation: 56849

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"

Upvotes: 5

Shyju
Shyju

Reputation: 218702

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
}

Upvotes: 20

Related Questions