Route Actions to same URL - c#

I'd like to hide requests for several controllers 'create' action in a common url. The controllers all are in a sub-folder in the Controllers directory:
Controllers \ mydirectory \ controller1
\ controller2
I've tried it this way
routes.MapRoute(
name: "controller1Create",
url: "buy",
defaults: new { controller = "controller1", action = "Create" }
);
and have changed controller1 to
../mydirectory/controller1
/controller1
But anytime I go to the create action, the url remains the same .. .com/controller1/create
How to do that right? Thank you for your help!

First, creating a folder for these controllers won't actually do what you want. ASP.NET MVC doesn't care about where your controllers are, it will scan the assembly and all controllers will behave like they are in the root.
If you put a controller named Controller1 in Controllers/MyDirectory. It will still be reachable from /Controller1 URL and MyDirectory/Controller1 will fail.
What you need is an area. You have to create an area for these controllers put them inside its own Controllers folder.
Then you can use an area route like this in AreaRegistration class:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyDirectory/{controller}/{action}/{id}",
new { action = "Create", id = UrlParameter.Optional }
);
}

Related

How to route to url.com/ControllerA/ControllerB/ControllerB's action in MVC

So I have a ProjectsController with the default route url.com/projects/action and I have a Controller for each Project like MosaController. The URL for the project should be url.com/projects/{ProjectName}/action, so in the Mosa example url.com/projects/Mosa/action.
I have set up a route in the RouteConfig that can solve this problem
routes.MapRoute(
name: "ProjectViewRoute",
url: "projects/{controller}/{action}",
defaults: new { controller = "Projects", action = "Index" }
);
This works I can call url.com/projects/action and url.com/projects/Mosa/action and the correct controller is selected, but when I call the URL url.com/{ProjectName}/action it invokes the action, because of the default route. Is there a way to ignore the default route? Or is a there better way of concatenating controllers like this?
Thanks!
Do you need the default route for other portions of your app? If not, why not simply remove it and just have the ProjectViewRoute? Or consider creating "Projects" as an MVC "Area" (https://www.c-sharpcorner.com/article/getting-started-with-area-in-asp-net-mvc/). This would eliminate the project-specific route outside of the Projects area.

How to disable default route on controller ASP.NET MVC 5

I'm building a web application (ASP.NET MVC 5) with a custom admin section where all the parameters of the apps are.
I want to be able to easily change the name of this section.
E.g.
myapp.com/admin/{controller}/{action}
could be
myapp.com/custom-admin-name/{controller}/{action}
I've tried to use areas but it seems like it would be hard to edit their name since all the controllers and models are bound to the area's namespace.
I've also tried to set custom routes
routes.MapRoute(
"AdminControllerAction",
"custom-admin-name/{controller}/{action}",
new { controller = "Dashboard", action = "Index" }
);
So I could do
mywebsite.com/custom-admin-name/dashboard/index
But the problem with that is that my admin controllers and actions are still callable using
mywebsite.com/dashboard/index
Is it possible to cancel the default routing of a controller/action ?
Is there any more viable solutions to this problem that I wouldn't have thought about ?
There is a way to restrict the controller namespaces for a given route, so controllers which don't belong to those namespaces will be ignored.
For example, the following will be restricted to controllers in the namespace YourApp.Controllers (You can add multiple namespaces if needed):
Route route = routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "YourApp.Controllers" }
);
route.DataTokens["UseNamespaceFallback"] = false;
Disabling the namespace fallback is important, otherwise you will just be prioritizing those namespaces.
So, you could restrict the default route to the namespace YourApp.Controllers as above and create a custom admin route restricted to the namespace YourApp.Controllers.Admin:
Route route = routes.MapRoute(
"AdminControllerAction",
"custom-admin-name/{controller}/{action}",
new { controller = "Dashboard", action = "Index" },
namespaces: new[] { "YourApp.Controllers.Admin" }
);
route.DataTokens["UseNamespaceFallback"] = false;
Please note that as mentioned by Tareck, the admin route has to be defined before the general route.
Try removing with this
RouteTable.Routes.Remove(RouteTable.Routes["NAME ROUTE YOU WISH TO RMOVE"]);

Adding route for admin controllers

I have placed all my admin controllers inside an Admin folder in Controller folder. Since one of my admin controller matches the name of another controller in Controller folder, I am getting the following error.
Multiple types were found that match the controller named 'Product'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
I tried adding the following route, but still the problem is same
routes.MapRoute(
"", //Route name
"Admin/{controller}/{action}/{id}", // Url with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
How can i get rid of this error. Changing the name of controller is the last option on my mind. Right now, I am looking for a way to preserve the name and see if i can find another way around this.
I have placed all my admin controllers inside an Admin folder in Controller folder
Well, that's your problem. How do you expect the default controller factory to know which controller you want to be instantiated given the following request /admin/index (the one in the Controllers folder or the on in the Controllers/Admin folder)? Remember that the default controller factory searches for types in the loaded assemblies that derive from Controller. It doesn't really care in which folder they were declared. So when it finds that you have 2 controllers with the same name it doesn't know which one to pick.
One possibility is to use Areas. Then you could specify namespaces when registering the route:
routes.MapRoute(
"",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AppName.Areas.Admin.Controllers" }
);
Also in your Global.asax make sure that you specify the namespace for the non-area controllers:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AppName.Controllers" }
);

Correct Process for Routing with Admin Subsite

I'm building my first Asp.Net MVC2 Site, and i'm now trying to add an /Admin area to the site.
I don't want this area to be visibile to the main set of users so will only be accessible when you enter http://Intranet/Admin
What I have is a NewsController for my regular users but I also want an Admin NewsController and I'm not sure how to setup the Class hierarchy and folders so that when I add the Views they are in the correct location.
Inside my Global.Asax.cs I've added and the routes resolve correctly.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Intranet.Controllers" }
);
routes.MapRoute(
"Admin", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Intranet.Controllers.Admin" }
);
And in the folder hierarchy I've setup
Views/
Admin/
News/
...I want the new view to go here...
In the Controllers
Controllers/
Admin/
AdminController.cs
NewsController.cs (this is the one i want for administration)
NewsController.cs (this is the regular one for viewing the list, specific item etc)
The problem I face is when I go into the admin/NewsController.cs on Index and Add View it tries to create it at the /News/Index.aspx rather than /Admin/News/Index.aspx.
This is the code for my admin news controller Controllers/Admin->Add->Controller
namespace Intranet.Controllers.Admin
{
public class NewsController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
Is there something I'm doing incorrectly, or what should I change so that when I add the views they are being created in the /Admin/{area} directory.
Since you're using MVC2, the easiest way to solve this is the create an actual MVC "Area" for your Admin section. Right now you're doing everything in the default section and just using an Admin folder. If you create an Admin area (under the well-known location Areas) folder, then you'll have an AdminAreaRegistration - where is where you'll configure your Admin routes. Because you'll do this as part of the Area, then the first segment of the URL "/Admin" will be used for the "area" token. This will disambiguate which controller to use and correctly pick up the controller you want. So you're folder structure will be:
/Areas
/Admin
/Controllers
NewsController.cs
etc.
When you try to create a View for the existing Controller Action it always create on the root folder of the Views. The default route for the View is always pointing to the root of the Views folder.
For example:
Controllers
Admin
AdminController.cs
HomeController.cs
HomeController.cs
In that hierarchy, both of the HomeController inside Admin and root shares the same Views in the Views Folder.
Views
Home
Index.aspx
Unless you return a specified View() in all of the ActionResults in your HomeController inside the Admin Folder of your Controllers. It will map to a certain View.
Example, ActionResult inside the HomeController.cs of Admin folder in Controllers.
namespace Intranet.Controllers.Admin
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Home/Index");
}
}
}
This will be mapped in the Views folder like this
Views
Admin
Home
Index.aspx
But if you do not specify the View path when you return a View in your ActionResult it will map to the default location of the Views which is like this.
Views
Home
Index.aspx
The reason for this is that even though you specify the routes in the Global.asax, that is only to map to which controller the url should point, not the Views folder.
When you right click and Create View on ActionResult of any Sublevels of the Controllers, it always create on the root of the Views folder to its corresponding Controller.

Why does my route get redirected, this doesn't make any sense to me

I have these 2 routes mapped out:
routes.MapRoute(
"Admin",
"admin/{controller}/{action}/{id}",
new { controller = "Admin", action = "index", id = "" }
);
and then I have:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
So the 2 routes are identical, except the first one has /admin prefixed in the URLS.
This is what is happening, I have no idea how to explain this:
When I go to:
www.example.com/user/verify
it redirects to
www.example.com/admin/user/complete
instead of
www.example.com/user/complete
The action Verify simply redirects to Complete like this:
return RedirectToAction("complete", "user");
And all the complete action does is populate the ViewModel, and then calls the view.
How can it be redirecting and adding the prefix /admin/ to the URL?
I believe it is redirecting to the Admin route because the Admin route is the first with all the matching parameters (controller and action in the case provided). If you want to use something like this you will need to either look into using areas (MVC2) or using a named route redirect.
admin is your controller, you dont need an admin/controller/action the default route works just fine
all you need is an admin controller and the default route will find it for you
ie {controller}/{action}/{id}
will send /admin/addproduct to a controller named admin and an action called addproduct
you only need to add routes if you want something custom for example
/products/televisions/hdtv/2
where products would be a controller and the last 3 are category,subcategory and pagenumber
on the controller you point it to within your route.
hope that makes sense
Not sure exactly how your controllers are structured, but you can add a constraint to the first MapRoute to limit it to the specific controllers you want the route to apply to:
routes.MapRoute(
"Admin",
"admin/{controller}/{action}/{id}",
new { controller = "Admin", action = "index", id = "" } ,
new { controller = "[Some regex Expression - e.g. Admin]" }
);
Which will make the route only applicable for those controllers related routes. You can also use this tool to debug your routes. Depends how you have things structured, but like #NickLarson said - sounds like your using area functionality of MVC 2.
mvc goes from top to bottom while matching router, that' why you are dealing with this problem

Categories