MapRoute without affecting ActionLinks - asp.net-mvc

Typically I want the default route used when generating URLs ("backwards" mapping), even if I've added alternate or legacy routes to reach an action ("forwards"):
routes.MapRoute("Legacy", "legacy/home/index", // want forward-only mapping!
new { controller = "Home", action = "Index" };
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
In this case, I'd still want the default route used when I call:
#ActionLink("Index", "Home") // generates legacy URLs ;(
In the thread: Routing legacy requests with and without querystring (issue #1), the solution is to add two MapRoute statements for each legacy route, or specify the route name in each ActionLink call.
Is there a way to define a route used only for URL -> Action mapping, not the inverse?

I can't find a way to have the route statements apply only one way, so I installed the IIS URL Rewrite module. This works to rewrite the URL transparently, or 301-redirect it in the case of legacy URLs.
It's a more maintainable solution than editing the global.asax anyway.

Related

Mapping controllers/action in route table

Is it necessary to map all the controllers/actions to the route table in MapRoute function in an application ?
If not so, then how they added to the route tables ?
Using the default convention-based route will cover basic routing for many cases, especially those that aren't concerned so much with what the URL looks like. Since there is only 1 route in the route table, this is the best performing option, and it automatically "just works" for any controller or action that is added to the project.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Typically, other than that URLs are statically added either by using the MapRoute method or [Route] attributes, meaning they are compiled into the application and cannot change at runtime. This makes routes testable so the configuration can be verified before release.
However, if the goal is to make some sort of CMS where the application has control over the URLs and you want them to automatically be "made live" as you add records to your database you can extend RouteBase to handle that (along with virtually any other) routing scenario.

ASP.NET MVC4 Routing - Multiple routes to the same location

I am in the process of setting up a Single Page Application (SPA) and would like to setup, currently two routes. For instance:
Route 1: http://localhost - this is the default route which requires authentication (Admin area)
Route 2: http://localhost/<client>/<clients project name>/ - this does not require authentication (view only)
In the admin area, they setup the <client> and <clients project name>, therefore I know I need to setup this configuration in MVC4 Routes, but it is unclear to me how I would approach this.
Another caveat would be, if the <clients project name> was not entered into the URL, it would present a search page for that client.
One of the great things about routing in MVC is the ability to route anything to anywhere, regardless of whether the url matches the naming of controllers and action methods. The RouteConfig allows us to register specific routes to cater for this. Let me show you how you can achieve this.
Route 1:
This is handled by the default route in the route config.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional });
Hitting http://localhost will take you to the Home controller and the Index action method.
Route 2:
We can set up one route that will cater for http://localhost/<client> and http://localhost/<client>/<clients project name>
routes.MapRoute(
"Client",
"{client}/{title}",
new { controller = "Home",
action = "Client",
title = UrlParameter.Optional });
Hitting either http://localhost/bacon or http://localhost/bacon/smokey will take you to the Home controller and the Client action method. Notice the title is an optional parameter this is how we can get both urls to work with the same route.
For this to work on the controller end our action method Client would need to look like this.
public ActionResult Client(string client, string title = null)
{
if(title != null)
{
// Do something here.
}
}

ASP.MVC 3 routing : how to get url with default action included?

Suppose I have the following routing
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
Now, when you generate an url using Url.Action("Index","MyController") you will get as expected : /MyController
But in one exceptional case, I would like to get the full url /MyController/Index
(without changing the routing)... does anyone know if this is possible?
It is possible. But you need to modify the routing.
Create an own routing class that derives Route
Override the GetVirtualPath() method to include /index for the pages that needs it.
Configure the default route using your routing class instead.
I am afraid this is not possible. And it shouldn't matter as both urls will resolve to the same controller action.

MVC Routing: Trying to get dynamic root value working

I am trying to define dynamic sections of my site with the root url of the site. I am having some trouble defining the right MVC Route for it. Can someone please help.
My desired url will look like this: http://website.com/[dynamic-string]
But I have other standard pages like: http://website.com/about or http://website.com/faq or even just http://website.com.
My routes don't work correctly with that dynamic string. As shown below.
This is the route for the dynamic-string.
routes.MapRoute(
"CommunityName", // Route name
"{communityName}", // URL with parameters
new { controller = "Community", action = "Community", communityName = UrlParameter.Optional }
);
This is the route for all other STANDARD PAGES
routes.MapRoute(
"Default", // Route name
"{action}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
My routes just don't match up. Everything either gets diverted to one or the other route depending on which route is declared first.
There is no difference between the two routes you mention. How can MVC know which url should be mapped to communityName and which to action? Any url can match both.
You can define your standard pages as a route (before the CommunityName route) or you can catch them in your Community action, see if the name matches a function in your Home controller and then call the right action function.
I've never done this before but you might be able to create a more intelligent routehandler that looks at your controller actions, checks if the action really exists and if true selects that route.
this is beacuse the routes are effectively the same. When you declare the action route you do not state any constraints to the route, for this reason anything will be assumed to be a the action name.
If you want two routes to capture at the same level then you must constrain the action names to those that exist on your controller, this way if it does not match it will pass to the next route.
You can see an example of and advanced constraint here:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Custom-route-constraint-to-validate-against-a-list.aspx

How does MVC routing understands the URL?

Global.asax.cs has the following code on initialization:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
What I'm asking is, how does it know that what it gets for "{controller}" will be the name of the Controller class to be invoked? Are there tokens defined somewhere? if so, can I list them?
If I define additional tokens (like "{lang}") will it assume they are additional parameters?
(I'm developing a custom URL rewrite/redirect handler, and I need it to work with MVC...)
What is the most practical way to define custom patterns and "aliases" for URLs?
The Mvc runtime has the controller and action tokens hardcoded. In addition there is also "area" but thats about it.
#TDaver If I define additional tokens (like "{lang}") will it assume they are additional parameters?
yes. If you define, for instance, a parameter like lang, it wil detect it. Think about like that, it will be the querystring field called lang of the page. and you can create a route for a pretyy url. Like below;
routes.MapRoute(
"Default", // Route name
"{lang}/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
so the url will be like ; http://example.com/en/home/about
Also, the most important part of routing is to understand that the routes will be picked by order. for instance, if you have multiple routes matching your current request, the first route will be picked by MVC Framework.
I reccomend you to have a look at phil haccked's RouteDebugger
Also you can create route constraints for advanced routing options as well.

Resources