asp mvc routing problem - asp.net-mvc

I have this two routes.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"Paging", // Route name
"{controller}/{action}/p{currentPage}",
new { controller = "Home", action = "Index" },
new { currentPage = "\\d+" });
I have this Controller
public class MyController
{
public ActionResult All(int currentPage = 1)
{
// some code executed here
return View(pList);
}
}
Why this url goes to the first route /My/All/p5
Can someone point me to good tutorial about routes?

Routes need to be registered in the right order, as they are processed in the same order in which they are registered. Your first route is essentially a catch all, so it will also match /My/All/p5. Register that route first:
routes.MapRoute(
"Paging", // Route name
"{controller}/{action}/p{currentPage}",
new { controller = "Home", action = "Index" },
new { currentPage = "\\d+" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Reading : Steven Sanderson has very good explanation of routing in his book ( Pro MVC 2 ) in chapter 8. (You can find it here)
From the book:
If there’s one golden rule of routing,
this is it: put more-specific route
entries before less-specific ones.
Yes, RouteCollection is an ordered
list, and the order in which you add
route entries is critical to the
routematching process.

I have a series of blog posts on Routing you can read here: http://haacked.com/tags/Routing/default.aspx
Also, the route debugger http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx is a useful tool for playing around with routing and understanding why a route you think should match is not matching.
BTW, Matthew Abbot is correct. You need to re-order the routes. Nazar's quote from Steven Sanderson's book has the reason why that's the case. Routing evaluates routes in order and the first one wins.
Here's the simple exercise I would have done to debug this situation. Looking at your request:
/My/All/p5
I would go through each route one at a time in my system and ask, "would it match?". The first route where the answer is yes is the one that will match. In your example, you can see that route is the first route. This is why Steven suggests putting more-specific routes first, so they match.
And the Route Debugger I mentioned earlier does this exercise for you. It shows you every route that would match a given request.

Related

Creating A new Route in MVC

In MVC, the default route url pattern is - url : "{controller}/{action}/{id}"
When I add a new route as shown below before the default route, the url for the default route is shown as something like Home/Index?id=5 and not Home/Index/5. How can this be fixed.
routes.MapRoute(
name: "Name",
url: "{controller}/{action}/{name}",
defaults: new { controller = "Home", action = "Browse", name = UrlParameter.Optional }
);
The default route will never be hit because the route you added is exactly the same, from a routing perspective. So your route will catch everything that the default route would catch if it were the only one, or placed before yours. Both will match one, two and three-segment URLs.
That route is unnecessary and pretty much useless.
like what #asymptoticFault says, it serves the same purpose as the default one.

How do I use constraints in ASP.net MVC 4 RouteConfig.cs?

I'm trying to get some routing constraints working using the latest asp.net mvc 4 architecture. Under App_Start there is a file called RouteConfig.cs.
If I remove the constraints section from my example below, the url works. But I need to add some constraints so that the url doesnt match on everything.
Should work: /videos/rating/1
Shold NOT work: /videos/2458/Text-Goes-Here
This is what I have:
//URL: /videos/rating/1
routes.MapRoute(
name: "Videos",
url: "videos/{Sort}/{Page}",
defaults: new { controller = "VideoList", action = "Index", Sort = UrlParameter.Optional, Page = UrlParameter.Optional },
constraints: new { Sort = #"[a-zA-Z]", Page = #"\d+"}
);
If you want multiple optional parameters on the same route, you will run into trouble because your urls must always specify the first one in order to use the second one. Just because you use constraints doesn't stop it from evaluating the parameters, it instead fails to match this route.
Take this for example: /videos/3
When this is trying to match, it finds videos, and says, "OK, I still match". Then it looks at the next parameter, which is Sort and it gets the value 3, then checks it against the constraint. The constraint fails, and so it says "OPPS, I don't match this route", and it moves on to the next route. In order to specify the page without the sort parameter defined, you should instead define 2 routes.
//URL: /videos/rating/1
routes.MapRoute(
name: "Videos",
url: "videos/{Sort}/{Page}",
defaults: new { controller = "VideoList", action = "Index", Page = UrlParameter.Optional },
constraints: new { Sort = #"[a-zA-Z]+", Page = #"\d+"}
);
//URL: /videos/1
routes.MapRoute(
name: "Videos",
url: "videos/{Page}",
defaults: new { controller = "VideoList", action = "Index", Sort = "the actual default sort value", Page = UrlParameter.Optional },
constraints: new { Page = #"\d+"}
);
I put the most specific routes first when possible and end with the least specific, but in this case the order should not matter because of the constraints. What I mean by specific is most defined values, so in this case you must define the sort in the first route, and you also can specify the page, so it is more specific than the route with just the page parameter.
My input maybe rather late, but for others still searching for answers.To keep things simple, i would use the following in my RoutesConfig file
routes.MapRoute(
name: "Videos",
url: "{controller}/{action}/{id}",
defaults: new { controller = "VideoList", action = "Index", id="" },
constraints: new { id = #"\d+"}
);
Depending on your choice of implementation, id could be UriParameter.Optional, but in this scenario it is going to be id="" ,because we will be passing a string/int during runtime.
This style was adopted from http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/creating-a-route-constraint-cs
One thing to keep in mind by convention controller classes always end with controller e.g VideoListController class. This class should be listed under the controller folder containing the following method
public ActionResult Index(string id)
{
// note this maps to the action
// random implementation
ViewBag.Message=id;
View()
}
// note this approach still matches any string...
To match only integers, the Index method has to be rewritten
public ActionResult Index(int id)
{
// note this maps to the action
ViewBag.Message=id;
View()
}
Consequently, this approach works for VideoList/Index/12
but upon putting VideoList/Index/somerandomtext it throws an error during runtime. This could be solved by employing error pages.
I hope this helps. Vote if its quite useful.

Can't Route An MVC Controller

I have tried routes.mapRoute but i can't figure a way in MVC 3 to use it make a root path route to an action. e.g mywebsite.com/party should redirect to mywebsite.com/events/party where events is the controller and party is the action.
Is this even possible?
Without seeing your existing routes, its hard to give you an exact solution.
One rule to keep in mind:
MVC will resolve the first in your route collection that matches the requested URL
not necessarily the most specific match.
Make sure you do not have another rule that would also satisfy that route placed earlier in your code, e.g. the routing algorithm might be finding a "party" controller and "index" action because you have a default rule like:
routes.MapRoute(
"Default",
"{action}",
new { controller = "Home", action = "Index" }
);
placed before your rule.
You need to put something like
routes.MapRoute(
"PartyRoute",
"party",
new { controller = "Events", action = "Party" }
);
BEFORE any route that might match a URL with just a single parameter
routes.MapRoute(
"Default",
"{action}",
new { controller = "Events", action = "Index" }
);

Vanity MVC Routes?

I want to have a route that looks something like: www.abc.com/companyName/Controller/Action/Id
However, all the company names need to map to the same "base" controllers, regardles of what the name is. I only need the companyName for authentication purposes.
Also, if there's no companyName provided, I need to map to a different set of controllers altogether.
How do I do this? I'd also appreciate a good routing resource so I don't have to ask questions like this.
routes.MapRoute(
"CompanyRoute",
"{companyName}/{controller}/{action}/{id}",
new { controller = "MyBaseCompanyController", action = "Index", id = "" }
);
routes.MapRoute(
"NoCompanyRoute",
"{controller}/{action}/{id}",
new {controller = "DifferentDefaultController", action = "Index", id = "" });
Routing is quite a complex topic, but it's covered well in Professional ASP.Net MVC 1.0. For online resources, I would suggest starting here, and then coming back to Stack Overflow ;)
In case if you wish to Resolve the errors caused due to routing . i suggest the following tool , which i found to be extremely useful.
Route Debugger
Go to Global.asax.cs, and add the following route in the RegisterRoutes() method before the "Default" route:
routes.MapRoute(
"Vanity", // Route name
"{company}/{controller}/{action}/{id}", // URL with parameters
new { company = "", controller = "Home", action = "Index", id = "" } // Parameter defaults
);

Asp.net MVC routing ambiguous, two paths for same page

I'm trying out ASP.NET MVC routing and have of course stumbled across a problem. I have a section, /Admin/Pages/, and this is also accessible through /Pages/, which it shouldn't. What could I be missing?
The routing code in global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Pages", // Route name
"Admin/Pages/{action}/{id}", // URL with parameters
// Parameter defaults
new { controller = "Pages", action = "Index", id = "" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
// Parameter defaults
new { controller = "Home", action = "Index", id = "" }
);
}
Thanks!
I'd suggest adding an explicit route for /Pages/ at the beginning.
The problem is that it's being handled by the Default route and deriving:
controller = "Pages"
action = "Index"
id = ""
which are exactly the same as the parameters for your Admin route.
For routing issues like this, you should try out my Route Debugger assembly (use only in testing). It can help figure out these types of issues.
P.S. If you're trying to secure the Pages controller, make sure to use the [Authorize] attribute. Don't just rely on URL authorization.
You could add a constraint to the default rule so that the {Controller} tag cannot be "Pages".
You have in you first route {action} token/parameter which gets in conflict with setting of default action. Try changing parameter name in your route, or remove default action name.

Resources