Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC - Nesting Routes / Controllers

Tags:

c#

asp.net-mvc

I have an ASP.NET MVC app. I have seen similar question asked. However, I haven't found a good answer. Essentially, I want to use the following routes:

/admin/users
/admin/users/create
/admin/users/[someId]
/admin/roles
/admin/roles/create
/admin/roles/[someId]

I have the following file structure:

/Controllers
  AdminController.cs
  /Admin
    UsersController.cs
    RolesController.cs
/Views
  /Admin
    Index.cshtml
    /Users
      Index.cshtml
      Detail.cshtml
      Create.cshtml
    /Roles
      Index.cshtml
      Create.cshtml
      Detail.cshtml

When I run my app, I just get The resource cannot be found.

What am I doing wrong? I set breakpoints, but none of them are being hit. It's like the routes aren't mapping to the controllers. I'm not sure what I need to do though.

like image 477
user70192 Avatar asked Mar 31 '16 16:03

user70192


2 Answers

You do not need to create sub folders for this to work. Just have 2 controllers(UsersController and RolesController) and you can use attribute routing to define the custom routing pattern you want.

Assuming you have attribute routing enabled

public class UsersController : Controller
{
  [Route("admin/users")]
  public ActionResult Index()  { // to do : Return something }

  [Route("admin/users/create")]
  public ActionResult Create()  { // to do : Return something }

  [Route("admin/users/{id}")]
  public ActionResult View(int id)  { // to do : Return something }    
}

Or you can do the RoutePrefix on the controller level.

[RoutePrefix("admin/users")]
public class UsersController : Controller
{
  [Route("")]
  public ActionResult Index()  { // to do : Return something }

  [Route("create")]
  public ActionResult Create()  { // to do : Return something }

  [Route("{id}")]
  public ActionResult View(int id)  { // to do : Return something }    
}

You can do the samething for the RolesControllers as well.

You can enable attribute routing in the RegisterRoutes method in RouteConfig.cs file.

public static void RegisterRoutes(RouteCollection routes)
{            
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes(); //This line enables attribute routing 
   //Existing default Route definition goes here
}

You may also consider creating an "Admin" area and put your controllers inside that. Areas are the right solution if you want to logically group similar functionality.

If you do not prefer attribute routing ( why not ?) , you an define these custom route patterns in your RouteConfig. The order in you define the route matters.So make sure you define your specific routes before the default generic one.

like image 102
Shyju Avatar answered Oct 13 '22 11:10

Shyju


You can also override your route tables by decorating your action methods with the RouteAttribute class.

For example:

class AdminController
{
    [Route("/admin/users/create")]
    public ViewResult CreateUser()
    {
        ...
    }
}

This has the advantage of separating the method name from the url component.

You can also route multiple URLs to a single method:

class AdminController
{
    [Route("/admin/users/{someId:guid}")]
    [Route("/admin/users/{someId:guid}/details")]
    public ViewResult UserDetails(Guid someID)
    {
        ...
    }
}

As mason said, the file structure isn't important in MVC routing.

like image 34
ReflexiveCode Avatar answered Oct 13 '22 11:10

ReflexiveCode