Does MVC routes look for pattern or names - asp.net-mvc

I am trying to understand routes, but am very confused.
The question is simply, does the default values have any impact on which router is chosen, or is it simply the pattern.
For example, consider the following
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{startIndex}",
defaults: new { controller = "Home", action = "Index", startIndex = UrlParameter.Optional }
);
routes.MapRoute(
name: "About",
url: "{controller}/{action}/{startIndex}",
defaults: new { controller = "About", action = "Index", startIndex = UrlParameter.Optional }
);
Regardless of whether the end result is the same, would MVC simply choose the first every time since the URL: pattern matches the request, and therefore ignore that they have different controllers?

Route selection uses pattern matching and will select the first matching pattern. In your example, there's no reason for your second route as the first will match /about/... as well as the second and result in the same action being invoked. If you need to have routes which have the same basic pattern, perhaps the values in the pattern affect the controller you use, you can use routing constraints to aid in choosing the correct route or use fixed values and place the route before the default route.
routes.MapRoute(
name: "Contact",
url: "/contact",
defaults: new { controller = "about", action = "contactus", id = "" }
);
routes.MapRoute(
name: "Help",
url: "/help",
defaults: new { controller = "about", action = "help", id = "" }
);
routes.MapRoute(
name: "Admin",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Admin", action = "Index", id= UrlParameter.Optional },
constraints: new { controller = "(admin)|(orgadmin)" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{startIndex}",
defaults: new { controller = "Home", action = "Index", startIndex = UrlParameter.Optional }
);

Related

Routes in ASP.NET MVC 5

My requirement is I need to set multiple routes to same controller/action method.
If user enters url http://localhost:xxxx/home/index , it will target "index" action method of "home" controller.
I also want "http://localhost:xxxx/products" and "http://localhost:xxxx/categories" to point to "index" action method of "home" controller.
I was able to achive this by adding two routes "categories" and "products" as mentioned below , and it is working fine.
routes.MapRoute(
name: "categories",
url: "categories",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "products",
url: "products",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
My question is , is there any way I combine those two routes "categories" and "products" in to one ?
You can achieve this by adding a constraint to your route.
Make the entire path a parameter, and then assign a regular expression rule to match this parameter.
routes.MapRoute(
name: "IndexMapper",
url: "{alternateIndexName}",
defaults: new { controller="Home", action="Index" },
constraints: new { alternateIndexName="(categories)|(products)"}
);
https://msdn.microsoft.com/en-us/library/cc668201.aspx#Anchor_6

MVC Routing Issue when trying www.example.com/id

Let say I have a website www.example.com
the default routing looks like
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
Ok that works fine but let's say I want my site when I go to www.example.com/id to go to www.example.com/login/index/id
How would I configure/add routing for this, without breaking my other pages where I am actually trying to go to www.example.com/controller?
EDIT: Unfortunately id is a string so I do not have any concrete constraints that I can think of that would work. Think of maybe instead of the id I should have said companyname or sitename so the URL would look like www.example.com/companyname .
The only solution that I have come up with so far is adding a maproute for each one of my controllers like this
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Settings",
url: "Settings/{action}/{id}",
defaults: new { controller = "Settings", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "companyname",
url: "{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This will work but I have many controllers and if I add one in the future and forget to adjust the routes it will fail. Also, this is unlikely but if a companyname happens to the be same as one of my controller names it would also fail.
In controller you may redirect to another Controller/action:
public ActionResult yourAction()
{
return RedirectToAction("nameAction","nameController");
}
Did you tried adding this mapping first:
routes.MapRoute( name: "Custom", url: "{id}", defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional } );
That should work but keep in mind that routes are evaluated secuentially, so you will have to organize mappings in order to reach out all pages in your site.
For example, routes like www.example.com/Product could be redirected to /Login by mistake.
EDIT: You can add constraints, so if id is an int value, you can try with the following:
routes.MapRoute("Custom", "{id}",
new { controller = "Login", action = "Index" },
new { id = #"\d+" }
EDIT 2: Having ids as string values, the only solution I see is to manually add each controller as you said, or to add something like this:
routes.MapRoute(
name: "Default",
url: "app/{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This way you don't need to update each route in the future.
Please try below routing
routes.MapRoute(name: "companylogin", url: "companylogin/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
routes.MapRoute(name: "default", url: "{controller}/{action}/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
Remove other controller specific routing. Now you can navigate to login using
url : - www.example.com/companylogin/{id} and all other url redirect default route.

Asp.net mvc routing without a controller or action name

I am trying to redirect all urls that don't match an existing controller to a certain controller.
For example, the url mywebsite.com/newyork should be processed as mywebsite.com/Cities/Info/newyork
I am using the following code in my RegisterRoutes but it doesn't seem to work as I get a 404 reponse:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Cities",
url: "{cityname}",
defaults: new { controller = "Cities", action = "Info", cityname= "" }
);
You should put your cities route first and drop the empty default parameter:
routes.MapRoute(
name: "Cities",
url: "{cityname}",
defaults: new { controller = "Cities", action = "Info" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The routes are processed in order so you should have most specific first to least specific ( your default route).
As your website.com/newyork matched the default route, it wasn't continuing to your city route.

Asp MVC 4 MapRoute specific url

I have web site root structure controllers for work with culture part in url,
like mysite.com/en/controller/action/id
but for one specific controller I don't want to use culture prefix.
mysite.com/controller/action/id
How I can do it ?
I have write it MyRoute but it dos't work
routes.MapRoute(
name: "MyNewRoute",
url: "MyNewRoute/",
defaults: new { controller = "MyNewRoute", action = "Data", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MemberTransfer",
url: "en/Member/Transfer",
defaults: new { culture = "en", controller = "Member", action = "Transfer", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ExecuteTransfer",
url: "en/Member/ExecuteTransfer",
defaults: new { culture = "en", controller = "Member", action = "ExecuteTransfer", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "",
defaults: new { culture = "en", controller = "Home", action = "Maintenance", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "HomePage",
url: "{culture}/{*pathInfo}",
defaults: new { culture = "en", controller = "Home", action = "Maintenance", id = UrlParameter.Optional }
);
Your "Default" route is overriding the last one. Try to swap the last two routes.
Btw, you can use handy route debugger from Phil Haack. It's really easy to set up and use (you just need to comment/uncomment one single line in your Global.asax.cs). It's absolutely must have tool for every Asp.Net MVC developer.
Swap your last two routes. Routes are evaluated top down, going with the first match, so you want to go from most specific to most generic in the order that you add them.

ASP.NET MVC route

I have only default route enabled:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Which will resove paths like: hostname/Home/Index, hostname/Home/Foo, hostname/Home/Bar/23 just fine.
But I must also enable route like this: hostname/{id} which should point
to:
Controller: Home
Action: Index
{id}: Index action parameter "id"
Is such a route even possible?
If id is a number you could add a route above the other one and define a regex constraint:
routes.MapRoute(
name: "IdOnlyRoute",
url: "{id}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { id = "^[0-9]+$" }
);
Not Tested :
Create your route like this
routes.MapRoute(
name: "custom",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
under your default route
Since I'm short on time, I have configured route for every action. Luckly there are not many of them. :)
routes.MapRoute(
name: "IndexWithParam",
url: "{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "IndexWithOutParam",
url: "",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Login",
url: "Home/Login",
defaults: new { controller = "Home", action = "Login" }
);
So last route was repeated for ever other action. Not sure if it can be done better, but it works.
Have you tried to play around with AttributeRouting package?
Then your code will look like this
[GET("/{id}", IsAbsoluteUrl = true)]
public ActionResult Index(string id) { /* ... */ }

Resources