Routing to an Area home page in ASP.NET MVC - 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
);

Related

Default route in MVC project with areas

I have an ASP MVC 4 project which contains areas and is structured as follows:
Areas
MyArea
Controllers
MyAreaController.cs
MyAreaRegistration.cs
Controllers
HomeController.cs
Global.asax
In Global.asax, I register first the area routes and then the global routes:
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
I have a default route in RegisterRoutes:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Controllers" }
);
Now, I want the default route of the project to point to an action (the login page with an return url as parameter) in MyArea without affecting the rest of the routes. I tried to set a default route in MyAreaRegistration:
context.MapRoute(
"MyArea_Default",
"{controller}/{action}/{returnUrl}",
new { controller = "MyArea", action = "LogOn", returnUrl = "/Home/Index" },
new[] { "Areas.MyArea.Controllers" }
);
This is working, the projects starts on the desired view. However, the problem is that many routes used across the project (for example /Home/Help) will match the MyArea_Default route since it is registered before the Default route. Trying to set the area DataToken in RegisterRoutes also messes up every other route not in the area.
How can I achieve a default route in the area without messing up everything else?
Any help is appreciated.

MVC Tell one view to one use controller, and another view to use another

I have an application where I don't want to use any "folders". EG
http://mydomain/Index ,
http://mydomain/Edit ,
http://mydomain/Admin ,
and so on....
I modified my defauly RouteConfig initially to look like this:
routes.MapRoute(
name: "maproute1",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional }
);
I have a Views/Home folder with all my views.
It works like a charm so whenever I enter the actionname, I don't have any issues.
If, hypothetically, I wanted to KEEP this url structure the same where I ONLY show the root domain / action-page... and I want to have SOME of these actions use one controller (HomeController.cs) and other actions (e.g. Admin) use another contoller (AdminController), is there I way I can modify my routes to say... ok.. if the action is "Admin" then use the AdminController? I have the AdminController set up with the action for "Admin" defined. I tried changing my routeconfig like this:
routes.MapRoute(
name: "maproute1",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "maproute2",
url: "{action}/{id}",
defaults: new { controller = "Admin", id = UrlParameter.Optional }
);
and then I set up a Views/Admin folder for the Admin view (and some other actions/views I want)
But it doesn't work. IF I have an "Admin" action in the home controller, it fires from the home controller. But I want the action to fire from the AdminController. Keep in mind I'm not just going to use ActionLinks to navigate to these pages so I can't just use an Actionlink and specify the controller. Some people are going to be going to links via a direct URL/bookmark.
If I wanted to keep my URL structure like this (http://mydomain/Action) I could just slap all my actions into ONE single controller and it would work, but I like to keep my code neat so that one controller handles functionality related to one set of models and another controller related to another set of models. For now it seems like I have to either (a) have one MASSIVE controller that is just going to get bigger and bigger or (b) I HAVE to have a more detailed path in there to have something to tell MVC what controller to use.
(BTW, I can't use querystrings... long story... don't ask)
MVC was designed to give people more control over layout from what I understand. I've been a web forms programmer for 13 years, but so far it seems that MVC has done this at the expense of giving you less control in other areas.
You may need to hardcode your Action names in your routes.
routes.MapRoute(
name: "maproute1",
url: "Home/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "maproute2",
url: "Admin/{id}",
defaults: new { controller = "Admin", action = "Index", id = UrlParameter.Optional }
);
http://localhost/Admin should take you to the Admin/Index view and http://localhost/Home should go to Home/Index view
one simple workaround is to create an admn action in home controller and then redirect from there to Admin controller but i am not sure you want to do ths as it may hit performence
public ActionResult Admin()
{
return Redirect("Admin/Index");
}
i would say try something other if you can and even then if you cant find a way out use this workaround

MVC3 Catch all path segments in URL

I'm trying to embed a legacy Area of our MVC3 application into an iframe within the website's new root layout.
The aim is to save time and avoid Javascript and CSS styling conflicts between new and old sections of the website.
I have so far been able to conditionally redirect traffic from the old Area to a new URL within the OnActionExecuting method in the Area's controllers.
e.g. http://localhost:80/Area/Account/Profile to http://localhost:80/App/Area/Account/Profile
My trouble now is setting up a catch all route that can pass the entire URL to a specific action and controller so I can take the URL and apply it to the iFrame.
I have this in my routing but it does not pass the path to the action and if there is more than one segment in the path it does not hit the route at all:
routes.MapRoute(
"AppRedirect", // Route name
"App/{*page}", // URL with parameters
new { controller = "Home", action = "App", page = UrlParameter.Optional }
);
Is there a way a can get the route working with the full path including all segments?
Or is there a better way to embed one of the projects Areas into an iFrame within the new root layout, while maintaining a readable URL similar to the old configuration? I do not want to modify the structure or routing configuration of the old Area if it can be helped.
Do you know how many possible segments there could be in the URLs? You could set up several routes (heirarchically - most segments filtering down to one) pointing to the same controller action and do the rest in there.
routes.MapRoute(
"AppRedirect2", // Route name
"App/{seg1}/{seg2}", // URL with parameters
new { controller = "Home", action = "App", seg1 = UrlParameter.Optional, seg2 = UrlParameter.Optional }
);
routes.MapRoute(
"AppRedirect1", // Route name
"App/{seg1}", // URL with parameters
new { controller = "Home", action = "App", page = UrlParameter.Optional }
);
etc...

Not including area name in URL results in "The view 'Index' or its master was not found" instead of 404

When I use this URL:
http://www.domain.com/Dashboard/Admin/Index
My page works as expected. Dashboard is an MVC Area, Admin is the controller and Index is the view.
If I remove the area name, like this:
http://www.domain.com/Admin/Index
Then I get the following error:
That's only kind-of expected; shouldn't it be a 404?
Why does MVC still successfully locate the controller and attempt to find the view when I don't specify the area?
How do I force it to return 404 when area is not included?
I've tried changing namespaces but it doesn't make a difference.
By default the built-in controller factory will find all implementations of matched controllers regardless of namespace. While the view engine will search for the associated view in context of the request (i.e. won't search in an area if the area route has not been matched). In short you need to limit the route engine definitions to only search in 'defined' namespaces, then the 404 will be thrown.
This is accomplished by using an overload of the MapRoute method, and passing the namespaces:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
null, // object constraints
new string[] { "Namespace.Application.Controllers" } // namespaces
);
For experimental purposes to see what the controller factory does with multiple controllers of the same name, try adding another AdminController to the root Controllers folder and then run the same request.

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

Resources