Change the name of your parameter year
to id
and this will match the default route that MVC adds to your project.
So for further clarification, let's take a look at the default route added by ASP.NET MVC:
routes.MapRoute(
"default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
In this route you can see three tokens that are named specifically for controller
, action
, and the third token which is passed to the action is id
. When a request comes into your application, ASP.NET MVC will analyze the routes that are currently mapped and try to find a method signature that matches them by using reflection against your controllers.
When it looks at your Movie
controller, it sees an action called ByYear
, however that method takes an integer called year
, not id
. This is why you end up with something like /Movie/ByYear?year={year}
when you create an ActionLink
for that particular Action. So to fix this, you have two options:
The first and most simple method to fix this is to just change the method signature for your Action to accept a parameter named id
which is what I recommended above. This will work fine, but I can see where it might cause a little bit of confusion when you go back to that source later and wonder why you called that parameter id
.
The second method is to add another route that matches that method signature. To do this, you should open your Global.asax and just add the following (untested, but should work):
routes.MapRoute(
"MoviesByYear",
"Movies/ByYear/{year}",
new { controller = "Movie", action = "ByYear" }
);
This route is hard-coded, yes, but it won't break the other routes in your system, and it will allow you to call the method parameter year
.
EDIT 2: Another thing to note is that the routing engine will stop on the first route it finds that matches your request, so any custom routes like this should be added before the default route so you are sure they will be found.