Reputation: 86937
here are two routes from my global.asax file. I'm trying to go to the second route and I'm getting a default 404 resource not found error.
When i remove the first route (listed in this example), it works.
How can i fix this, please?
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 });
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
Upvotes: 10
Views: 9785
Reputation: 81
The problem is that you have specified Default Values for controller and actions in your first Mapping.
Now any incoming request is handled by the first route, if the controller name is missing, its replaced by the default value and if the action name is missing that is also replaced by the default value.
So in reality when you say http://localhost/SomeRoute The first mapper comes into action and considers the string "SomeRoute" as a Controller name, then it does not find the action so it uses the default action you specified which is "AlertCreate" in your example. So now the mapper tries to find a Action called AlertCreate in the "SomeRoute" controller.
Bottom line is the second mapping does not kick into action because the first mapping is handling all your routing request. (because you have default values specified)
Upvotes: 0
Reputation: 1719
If you have another issue like this, try Phil Haack's url debugger at http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Upvotes: 1
Reputation: 13788
Your first route is a "greedy" route and will happily accept "create" as the alertId in the last parameter. It appears that you intend the alertId parameter to be numeric only, so you should add a constraint to tell the route system that that last parameter must be numeric.
See this tutorial.
For example:
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 },
new { alertId = @"\d+" });
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
Note, you can also reverse the order of the routes, but even if you do, you should still include a constraint for correctness if you want alertId to always be a number.
Upvotes: 20
Reputation: 32698
You want the routes to be defined the other way round so that the exact match on create
comes before the unconstrained match for alertId
. That, or you can add a constraint to alertId
as stated by Twisty Maze.
This is because the routing works by trying to match the routes from top to bottom. /user/PureKrome/Alert/create
matches on the User-Alert-Details
route as it thinks create
is the value for alertId
. By switching them around it will only match the User-Alert-Create
route if the 4th segment is explicitly create
and it will fall through to User-Alert-Details
if it doesn't.
For clarity, they should work this way around:
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 });
Upvotes: 1