Donald
Donald

Reputation: 481

ActionLink not working but RouteUrl does

I have a route

// Sample URL: /Fixtures/Team/id
routes.MapRoute(
     "Fixtures-by-TeamID",
     "Fixtures/Team/{teamId}",
     new { controller = "Fixtures", action = "GetByTeamID", },
     new { teamId = @"\d{1,3}" }
);

and I am trying to use ActionLink in ASP.net MVC p5.

<%= Html.ActionLink(g.HomeTeam.TeamName, "Team", new { teamId = g.HomeTeam.TeamID })%>

However it is not working and giving me

<a href="/Fixtures/Team?teamId=118">Team A</a>

If I use Url.RouteUrl i get the correct link.

<a href="<%=Url.RouteUrl("Fixtures-by-TeamID", new { teamId = g.HomeTeam.TeamID })%>"><%=g.HomeTeam.TeamName%></a>   

<a href="/Fixtures/Team/118">Team A</a>

Any help would be great? Will this change in ASP.net MVC beta?

Thanks

Donald

Upvotes: 4

Views: 3941

Answers (4)

Rob
Rob

Reputation: 1983

Have you tried this yet?

Html.ActionLink<FixturesController>(c => c.GetByTeamID(g.HomeTeam.TeamID), "Team")

Also

You might want to add action = "GetByTeamID" to your constraints.

Upvotes: 1

Carlyle Dacosta
Carlyle Dacosta

Reputation:

When a parameter ("action" in this case) is defined only in defaults and not in the route url, it has to be an exact match (unless you force it to go against a particular route as in the RouteUrl case).

To make everything work as is right now, you could add another route to the list just below the above route:

routes.MapRoute( "Fixtures-by-TeamID1", "Fixtures/Team/{teamId}", new { controller = "Fixtures", action = "Team", }, new { teamId = @"\d{1,3}" } );

OR you could add the action parameter to the route url,

OR you could use the named route as you did.

Upvotes: 0

user1228
user1228

Reputation:

Try this:

// Sample URL: /Fixtures/Team/id
routes.MapRoute(
     "Fixtures-by-TeamID",
     "Fixtures/Team/{teamId}",
     new { controller = "Fixtures", action = "Team", teamId = -1 }
);

your controller should look like:

public class FixturesController : BaseController // or whatever 
{
  /*...*/
  public ActionResult Team(int teamId)
  {
     return View("Detail", Team.GetTeamById(teamId)) // or whatever
  }
  /*...*/
}

And your link would look like

<%= Html.ActionLink("Click here for the team details", "Team", "Fixtures", new { teamId = ViewModel.Data.Id /*orwhateverlol*/ }) %>

(I don't have MVC on this machine so this is all from memory; may have a syntax error or some arguments reversed).

Note your route map's path matches your 1)controller, 2) action 3) argument name. I've found the default action (third argument in MapRoute) works, whereas your overload of that method I've never seen before (may be a holdover from a previous release).

Also observe how your FixturesController matches the path (Fixtures) and the action name matches (Team), and the argument matches as well (teamId).

Lastly, your ActionLink's last argument must match your controller's arguments in name (teamId) and type.

Its a bit too "magical" at this point (there's LOTS of string comparisons going on in the background!). Hopefully this will improve over time. The old Expression style was MUCH MUCH better. You essentially called the method you wished to run, with the values you wished to pass it. I hope they bring that expression style back into the framework. Haack?

Upvotes: 1

Brad Wilson
Brad Wilson

Reputation: 70586

In my experience, the only time action routes really work properly is when you only have the single default route. As soon as you start adding custom routes like yours above, action routes become... I guess "finicky" is the right word. The matching system doesn't work exactly how you'd expect it to.

In this case, you said the action was "Team", but this route doesn't match an action of "Team", it only matches "GetTeamByID". So the routing system keeps going and ends up giving you a route based on the default route. The teamId isn't explicitly part of your default route, so it ends up as a query parameter tacked on the end.

MVC Beta has already shipped, and this behavior is unchanged.

Also, don't you find the named route to be clearer anyway? Personally, I do.

I even go one step further and actually create route helpers for all my custom routes, which might look like this in your current example:

<a href="<%= Url.FixturesByTeam(g.HomeTeam.TeamID) %>"><%= g.HomeTeam.TeamName %></a>

Or even:

<%= Html.LinkToFixturesByTeam(g.HomeTeam) %>

where you can pull the values for name and ID directly from the model.

Upvotes: 1

Related Questions