Lesson Sunday

Now that we've had some practice building ASP.NET MVC Core applications, let's create an MVC interface for the to do list program we made last section. We'll then continue building upon this codebase throughout the course.

Starter Project for To Do List


We'll continue from where we left off in the last section. Your repository should match the code from the first commit of the following example repository except for two things:

  • The .gitignore file, which we'll create shortly.
  • The Priority property from last section's lesson on overloaded constructors, which we've removed.

Example GitHub Repo for To Do List after Section Two Lessons

Implementing an MVC Web Interface


We'll update this project to work with ASP.NET Core MVC. First we'll add the necessary components to our project structure.

  • In the ToDoList production project, create the following files:
    • Program.cs
    • Startup.cs
  • Remaining in ToDoList, create the following subdirectories:
    • Controllers
    • Views
  • In ToDoList/Controllers create a HomeController.cs file.
  • In ToDoList/Views create a Home subdirectory.
    • In this home subdirectory, create a single Index.cshtml file.
  • Finally, in the uppermost parent directory, ToDoList.Solution, create a .gitignore file.

The resulting structure should look like this:

ToDoList.Solution
├── .gitignore
├── ToDoList
│   ├── Controllers
│   │   └── HomeController.cs
│   ├── Models
│   │   └── Item.cs
│   ├── Program.cs
│   ├── Startup.cs
│   ├── ToDoList.csproj
│   └── Views
│       └── Home
│           └── Index.cshtml
└── ToDoList.Tests
    ├── ModelTests
    │   └── ItemTests.cs
    └── ToDoList.Tests.csproj

Add ASP.NET Core MVC

We'll also add the MVC framework package by updating the production project's .csproj file to include .Web in the SDK:

ToDoList/ToDoList.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
</Project>

Navigate to the ToDoList production project in the terminal and run $ dotnet restore.

Startup Class

We'll populate ToDoList/Startup.cs with the same general configuration code we've used so far:

ToDoList/Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ToDoList
{
  public class Startup
  {
    public Startup(IWebHostEnvironment env)
    {
      var builder = new ConfigurationBuilder()
          .SetBasePath(env.ContentRootPath)
          .AddEnvironmentVariables();
      Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
      app.UseDeveloperExceptionPage();
      app.UseRouting();

      app.UseEndpoints(routes =>
      {
        routes.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
      });

      app.Run(async (context) =>
      {
        await context.Response.WriteAsync("Hello World!");
      });
    }
  }
}

Program Class

We'll also populate ToDoList/Program.cs with configuration code as well:

ToDoList/Program.cs
using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace ToDoList
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

      host.Run();
    }
  }
}

The Item Model

The Item model should look like this from the last course section:

ToDoList/Models/Item.cs
using System.Collections.Generic;

namespace ToDoList.Models
{
  public class Item
  {
    public string Description { get; set; }
    private static List<Item> _instances = new List<Item> {};

    public Item (string description)
    {
      Description = description;
      _instances.Add(this);
    }

    public static List<Item> GetAll()
    {
      return _instances;
    }

    public static void ClearAll()
    {
      _instances.Clear();
    }

  }
}

.gitignore

We'll add the following to our .gitignore file to keep our directory tidy:

.gitignore
*/obj/
*/bin/

Let's also ensure any obj or bin directories already committed are no longer tracked by Git with the following commands in the top level of our project:

$ git rm --cached obj -r
$ git rm --cached bin -r

(If you receive a did not match any files response, it means you're already ignoring these directories so there was nothing to remove from Git. This is normal.)

Controller

In the ToDoList/Controllers/HomeController.cs we'll add the standard import statements, namespace, and class:

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

namespace ToDoList.Controllers
{
  public class HomeController : Controller
  {


  }
}

In addition to the Microsoft.AspNetCore.Mvc namespace, we're also using our ToDoList.Models namespace. This grants access to our Item class in the controller.

Now we can add our first route:

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

namespace ToDoList.Controllers
{
  public class HomeController : Controller
  {

    [Route("/")]
    public ActionResult Index()
    {
      Item starterItem = new Item("Add first item to To Do List");
      return View(starterItem);
    }

  }
}
  • We create an Index() route method with a route decorator specifying a URL path of /, which means this is the root route for localhost:5000.

  • When the route is invoked, we create a placeholder Item to populate our to do list. We can access Items because we are using ToDoList.Models; at the top of this file.

  • We pass starterItem into the View() method. Let's create a corresponding view now.

Views

Add the following to Index.cshtml:

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>To Do List</h1>
    <ul>
      <li>@Model.Description</li>
    </ul>
  </body>
</html>

We use @Model.Description to display the property of the starterItem object we passed into View() in the controller.

Launching the Project

Let's check out the project in the browser. Run the following in the ToDoList production project directory to install packages:

$ dotnet restore
$ dotnet build

Our build report should have no warnings or errors.

Now let's run our project:

$ dotnet watch run

If we visit http://localhost:5000, our to do list homepage loads correctly.

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