Lesson Sunday

So far we've been using a single controller to handle our routes. However, larger projects often use many controllers and it's common to create a controller for each model in our application. In this lesson, we'll walk through the correct way to implement more than one controller.

Project Structure


Let's alter our To Do List to use multiple controllers. Our HomeController will handle a central homepage to greet users. It will be handled by a HomeController. Then, all logic, routes, and views meant to work with To Do List Items will be handled by a new ItemsController.

  • Create an ItemsController.cs file in the existing ToDoList/Controllers directory.
  • Create a corresponding Items subdirectory in the ToDoList/Views directory.
  • Move the existing Views/Home/Index.cshtml file into the Views/Items subdirectory.
  • Move our existing Views/Home/CreateForm.cshtml file into the Views/Items subdirectory.
  • Add a new, empty Index.cshtml file into the Views/Home directory.

The resulting project structure should look like this:

ToDoList.Solution
├── ToDoList
│   ├── Controllers
│   │   ├── HomeController.cs
│   │   └── ItemsController.cs
│   ├── Models
│   │   └── Item.cs
│   ├── Program.cs
│   ├── Startup.cs
│   ├── ToDoList.csproj
│   └── Views
│       ├── Home
│       │   └── Index.cshtml
│       └── Items
│           ├── CreateForm.cshtml
│           └── Index.cshtml
└── ToDoList.Tests

ItemsController


We'll cut the contents of HomeController.cs and paste them into ItemsController.cs. This controller will be responsible for handling the routes that pertain to Items. By convention, we pluralize the class name, which is why it's ItemsController not ItemController.

Then we'll update the class name to state ItemsController instead of HomeController:

ToDoList/Controllers/ItemsController.cs
...

namespace ToDoList.Controllers
{
    public class ItemsController : Controller
    {

      ...
   ...
...

Next, we'll need to alter the path of our Index() route:

ToDoList/Controllers/ItemsController.cs
...

    [HttpGet("/items")]
    public ActionResult Index()
    {
      List<Item> allItems = Item.GetAll();
      return View(allItems);
    }

...

Here we simply change the path in the route's decorator to read "/items" instead of "/". The entire updated ItemsController.cs file should look like this:

ToDoList/Controllers/ItemsController.cs
using Microsoft.AspNetCore.Mvc;
using ToDoList.Models;
using System.Collections.Generic;

namespace ToDoList.Controllers
{
  public class ItemsController : Controller
  {

    [HttpGet("/items")]
    public ActionResult Index()
    {
      List<Item> allItems = Item.GetAll();
      return View(allItems);
    }

    [HttpGet("/items/new")]
    public ActionResult CreateForm()
    {
      return View();
    }

    [HttpPost("/items")]
    public ActionResult Create(string description)
    {
      Item myItem = new Item(description);
      return RedirectToAction("Index");
    }

  }
}

Note that we now have two routes that use the "/items" path. We can do this because GET and POST are two different requests. We use [HttpGet()] for the GET request and [HttpPost()] for the POST request. This way the server can easily tell them apart even if they use the same path.

Views for ItemsController Routes

Let’s revisit the views we've created for this controller. .NET will automatically look in a Views subdirectory that has the same name as the controller. This means our new ItemsController's views will reside in the Views/Items directory we just created.

We've already created Index.cshtml and CreateForm.cshtml and then moved them to the new Views/Items subdirectory so our views require no further changes.

HomeController


Let's build our HomeController now. It should look like this:

ToDoList/Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;

namespace ToDoList.Controllers
{
    public class HomeController : Controller
    {

      [HttpGet("/")]
      public ActionResult Index()
      {
        return View();
      }

    }
}

Views for HomeController Routes

Finally, we need to create a new Index view in the Home folder inside of the Views folder:

ToDoList/Views/Home/Index.cshtml
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My To-Do List!</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  </head>
  <body>
    <h1>Welcome to the To Do List!</h1>
    <a href='/items/new'>Add a new item</a>
    <a href='/items'>See list of items</a>
  </body>
</html>

We've successfully separated our code so that it uses two controllers. One handles Items while the other handles the home page.

Repository Reference

Follow the link below to view how a sample version of the project should look at this point. Note that this is a link to a specific commit in the repository.

Example GitHub Repo for To Do List

Lesson 26 of 38
Last updated more than 3 months ago.