organizing admin related controllers and viewpages - asp.net-mvc

admin section is at www.example.com/admin
so I have an admincontroller.
But I also have user admin related controllers, and configuration controllers, I want the url to be like:
www.example.com/admin -> adminController
www.example.com/admin/user/ -> adminUserController
www.example.com/admin/user/edit
www.example.com/admin/user/add
I hate the name AdminUserController, any suggestions?
View pages are organized like:
/views/admin
/views/admin/user/
so in just manually reference the view page like return View("~/views/admin/user/add");
What other options do I have?

You can use multiple areas in the same project (in MVC 2). You could have an admin area. This lets you organize all the controllers in a sensible way, and fixes the naming issue: You'd have a "UserController" in the "Admin" area.

There is no direct relation between the Controller/Views Name and physical location and your Route, you can control this in the Global.asax, If you have an AdminController you can define a Route like
example.com/Admin/Manage/
In your Global will be like :
routes.MapRoute(
"AdminSection",
"Admin/Manage/{action}/{id}",
new { controller = "AdminController", action = "Index", id = "" }
);
So when a Route like this example.com/Admin/Manage/ is entered you redirect to the desired controller and action, the name of the controller is not strictly the one on the route.
Hope it Helps.

Related

Is there a way to get rid of /Index in url of every controller in an MVC application

I am a bit new to the MVC so started off with MVC3 with ASPX engine.
my scenario is, that when I create a controller it automatically generates an Action named "Index" so suppose if I create a "Users" Controller + some actions, it would look something like this.
UserController
Index
Add
Delete
Edit
other actions
Then I create another controllers named "Products", "Company", etc with lets say the same set of Actions,
So normally when I would go to the link ../Users/Index I have the logic to show all users and it would do the same for ..Product/Index and ..Company/Index etc. It would show all products and all companies respectively.
This part of story is working good.
Now what I want to achieve is, I want to get rid of /Index everywhere in the url, not just for these three controllers, but for every controller that I create in future.
I want to consume "Index" Action but in a way that it doesn't need being typing everywhere.
It just makes me remember of old days where there used to be /index.html.
I have seen the links like these,
MVC Routing get rid of /Index in URL
they suggest i change the route for a specific situation, but I want this done not just in one or two controllers but every controller there is in my app.
Thanks.
In every route, specify Index as the default action, e.g.:
routes.MapRoute(null, "{controller}/{action}/{id}",
new { controller = "Home", action = "Index" });

asp.net mvc 4 Controller within a contoller

Can I have a controller within a controller.
I already have a users controller and I now want to add a Roles controller, But i want to access the roles controller from within the users controller like so: /users/roles/index rather than creating another controller and accessing it via /roles/index
If you want to keep to a typical REST implementation then I would suggest avoiding that and assign a controller to each of your root models (users, roles etc.).
Alternatively, if you want the Roles to be accesible only through the user, as a nested resource (meaning that you want to show, update, delete only roles of a particular user) then you can define routes like this:
routes.MapRoute(
"RolesForUser", // Route name
"user/{userId}/{controller}/{action}/{id}",
new { controller = "roles", action = "index", id = UrlParameter.Optional}
);
So a link to user/3/roles/index will take you to the Index action of the Roles controller, for user 3.
If instead your intention is to hide the roles management behind a /user/ url then I would go a bit further and create an user (or admin) Area in your MVC project (this is as simple as right-clicking on the project in Visual Studio and selecting Add -> Area...)

How do I tell what is part of a route is the controller and what is just a sub folder?

When looking at an MVC page and looking at the form action I can see it is set to:
/admin/WikiAdmin/edit/
So I spent my time looking for a controller called admin. I looked in the routes in the global and nothing was there.
Eventually I found that this url actually maps to the WikiAdmin controller which is confusing. Do does this mean you can have controllers in sub-folders? How does the app know not to forward the request to the admin controller and to actually send it to the WikiAdmin controller?
The admin part of the url is called area. You could read more about areas in this article. And a video here. Basically areas allow you to group multiple controllers sharing some common functionality on the site.
Yes, you can have controllers in sub-folders. With routing it could be a lot of possible URLs.
For example, if you have a route registered as below:
routes.MapRoute(
"admin1",
"admin/{controller}/{action}/",
new { controller = "WikiAdmin", action = "Index"}
);
The url can be /admin/WikiAdmin/Index/ or /admin/WikiAdmin/Edit/ or something else that matches the route. (Assume that there is an Edit action in WikiAdmin controller)
More example, if you have a route registered as below:
routes.MapRoute(
"admin2",
"account/{action}/", //no controller specified in url
new { controller = "WikiAdmin", action = "Index"}
);
Then the url can be /account/Index/ or /account/Edit/ or even /account/. (Because default controller is WikiAdmin and default action is Index)

Avoiding the Controller with Routing Rules in ASP.NET MVC

I've created a website with ASP.NET MVC. I have a number of static pages that I am currently serving through a single controller called Home. This creates some rather ugly URLs.
example.com/Home/About
example.com/Home/ContactUs
example.com/Home/Features
You get the idea. I'd rather not have to create a controller for each one of these as the actions simply call the View with no model being passed in.
Is there a way to write a routing rule that will remove the controller from the URL? I'd like it to look like:
example.com/About
example.com/ContactUs
example.com/Features
If not, how is this situation normally handled? I imagine I'm not the first person to run in to this.
Here's what I've done previously, using a constraint to make sure the shortcuts don't conflict with other routing rules:
routes.MapRoute(
"HomeShortcuts",
"{action}",
new { controller = "Home", action = "Index" },
new { action = "Index|About|ContactUs|Features" }
);
Add defaults for the controller names in the new statement. You don't have to have {controller} in the url.

How can I create 1 route with 2 differents user's access in ASP.NET MVC?

How can I do this: I have on page named "Schedule" and it can be accessed through 2 differente ways:
URL 1- www.bla.com/Admin/Schedule
URL 2- www.bla.com/Schedule
"URL 1" will be accessed by users with Admin previlegies and this View will show some Admin stuff, and users must be LoggedOn.
In the otherhand, "URL 2" will be accessed by users NOT LoggedOn and it will NOT show the admin stuff.
But, they are the same page, just with some differences depending on user's access.
I already have AdminController and I intend to put this "Schedule" View as part of this controller. As result, I know if I type "URL 1" it will work. But, if I type "URL 2"? Will I have to create a "ScheduleController" just to handle this?
I wonder if there is a way to resolve this by Global.asax, configuring the routing... I don't know...
Thanks!!!
You can map the /Schedule route to the /Admin/Schedule action from the Global.asax.cs like this:
routes.MapRoute(
"Schedule",
"schedule",
new { controller = "Admin", action = "Schedule" }
);
This will solve your immediate problem of wanting two separate routes resulting in the same action/view.
However, this will not solve your scenario properly. The main issue is that the identity of the logged on user is orthogonal to the route the request takes. In other words, you can't force the admin user to always hit the /Admin/Schedule route, they could just as well hit the /Schedule route and still would expect the same end result. Not only that, but doing it this way will prevent you from using the [Authorize] attribute on the Admin controller or the action to force the user to login and will have to implement custom logic checking which route the action was hit through and decide whether you want to force login or let the user through.
Thus, you have to make a decision:
you share the controller, action and the view and determine whether to show the additional information in the view based on the identity and the role membership of the logged on user (if any). You will have to change the name of the controller then, as /Admin will not reflect the new role this class has;
you share only the view and have two separate controllers and actions - Admin.Schedule and User.Schedule. You will have to put the view in the /views/shared folder and return the same view fromboth actions, potentially passing different model. You'll end up with two routes - /Admin/Schedule and /User/Schedule;
you have two separate controllers, actions and views.
In all three cases, you can still have the rule above pointing to the appropriate controller, if you want to have also the shortest /Schedule route.
Make the View shared and just render it from both controller actions. Pass the appropriate data via the model (or ViewData) so the View knows not to render the admin stuff when rendered from the non-admin controller action.
And, yes, create the Schedule controller. Make the routing simple and handle sharing the generation code on the back end.
AdminController
public ActionResult Schedule( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = true
} );
}
ScheduleController
public ActionResult Index( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = false
} ); }
Sounds like you don't really need a different URL if it's the same page. However if for some reason you still want to use 2 different URLs...
Url 1:
routes.MapRoute("ScheduleAdmin", "Admin/Schedule",
new
{
controller = "AdminController",
action = "Schedule"
});
Url 2:
routes.MapRoute("Schedule", "Schedule",
new
{
controller = "ScheduleController",
action = "Index"
});
You didn't make it clear what action you were using for the schedule controller so feel free to change that.

Resources