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

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.
}
}

Related

.NET MVC custom route different default controller

.NET MVC. I am having some problems defining and using custom routes.
I have a controller with just 2 actions. These action methods receive 2 parameters each. I have added a custom route in RouteConfig.cs (before the default route), like this
routes.MapRoute(
name: "customRoute",
url: "MyController/{action}/{entityType}/{id}",
defaults: new { controller = "MyController", action = "Index", entityType = UrlParameter.Optional, id = UrlParameter.Optional }
);
this works if MyController does contain an Index method (and corresponding view).
the problem is, MyController does not contain an Index method (only the 2 action methods refered before), and I want the route.default to be something like Home/Index instead. but if I change the route to this:
routes.MapRoute(
name: "customRoute",
url: "MyController/{action}/{entityType}/{id}",
defaults: new { controller = "Home", action = "Index", entityType = UrlParameter.Optional, id = UrlParameter.Optional }
);
it does not work. Apparently, the controller in route.url must be the same as the one in route.defaults...
CORRECTION: the route works for a correct url, but for an incorrect one (for example adding another parameter at the end) it shows 404 error (makes sense, because MyController.Index does not exists)
so, how can this be achieved?
url: "MyController/{action}/{entityType}/{id}"
Here, what you are saying is the URL pattern for your custom route should start with MyController(My/).
If the url pattern does not match with the configured routes(including the default one) you will have 404 Error.
I can suggest 2 ways of achieving what you want...
Either create a third method in your MyController that will act as the default one and its task would be to redirect to Home/Index.
Or
Create a new method in Home controller having parameters for entityType and Id.
You can't create an overload for Home/Index because you can only have a maximum of 2 action methods with the same name on a controller.
See this.
Routing: The current request for action [...] is ambiguous between the following action methods

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.

MVC Routing access path

I am quite new to MVC. I am facing a problem with routing right now. My project URL is /account/Create. I can access controller and do my stuff for Create, but
I need to access /account controller because I need to write code in that level.
/account/create - I can access the code this level
/account - dont know how to access this controller
Project Stucture:
Sample Project
Controler
Model
View
What am I supposed to change in the following code?
//global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } //Parameter defaults
);
}
/account/create is accessing code in the Account controller. Create has to be a method on the Account controller (unless you modify the default routes). Any public method you define on the account controller is accessible via /account/method URL. Based on the route you posted, going to /account URL is going to call the account controller Index method:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
**new { controller = "Home", action = "Index", id = UrlParameter.Optional }** // Parameter defaults
);
That action = "Index" part above is defining what the default method on the account controller is, so going to /account URL is equivalent in this case to /account/index URL
And I just noticed that you spelled account wrong in the question, not sure if that may be your issue ;)
Update
Not sure if this is what you're after, but if you need to write code at the /Account level you can do this in the constructor of the controller.
Unless you substantially customize MVC, then controllers correspond to classes derived from Controller in mvc, and actions correspond to methods on those controllers.
What are you trying to achieve when you say you can't access the controller /Account?
The controller is only a container for Actions so you need to specify an Action. Of course, you can have a default Action in case an action isn't specified. That is specified in default the route above. It's called Index

MapRoute without affecting ActionLinks

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.

Routing to an Area home page in ASP.NET MVC

I'm trying to route to the home page of an Area in MVC, e.g.
myDomain.com/myArea/Home/Index
when I use the URL:
myDomain.com/myArea
MVC appears to by trying to find a Controller called "myArea" in the root Controllers folder and thereby would route to:
myDomain.com/myArea/Index
if the Controller existed.
Again, I want:
myDomain.com/myArea
to route to:
myDomain.com/myArea/Home/Index
I figure that I should be able to do this in Global.asax without having to resort to creating a dummy controller that re-routes to the area controller, but I've drawn a blank.
One way I used to get around this was to set the namespaces property on the default route in the Global RegisterRoutes method, this seemed to resolve that problem. Had to add this restriction to some other routes where I had conflicts between Controller in the main website and the area.
var namespaces = new[] { "CompiledExperience.Website.Web.Controllers" };
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces
);

Resources