Lesson Weekend

Now that we have a basic understanding of server-side frameworks and MVC, let's build our first C# web application together.

Over the next few lessons, we'll create a website called "Friend Letter" that displays a custom electronic postcard to our friends while we're on vacation. This lesson will focus on constructing and configuring the project directory. Upcoming lessons will explore individual elements of an ASP.NET Core MVC web application including views, controllers and models.

Project Setup for Friend Letter


Let's create a new project directory. This will have some similarities to the projects we created last section but with several new elements.

  • Create a parent directory named FriendLetter.Solution.
  • Within it, add one subdirectory called FriendLetter. (We won't add testing in this first application, so we can focus solely on new MVC concepts).
  • Create three files in the FriendLetter.Solution/FriendLetter subdirectory:
    • FriendLetter.csproj
    • Startup.cs
    • Program.cs
  • In the parent FriendLetter.Solution directory we'll also create a .gitignore file.

The resulting structure should look like this:

FriendLetter.Solution
├── .gitignore
└── FriendLetter
    ├── FriendLetter.csproj
    ├── Program.cs
    └── Startup.cs

ASP.NET Core MVC Packages

We'll need to add a .csproj file that includes packages for our new framework. We'll add the following code:

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

The Startup Class

We've created a new file that we didn't use last section: Startup.cs. This file is required in every ASP.NET Core MVC project. It provides instructions on compiling and running a web application. We'll add code to ours one step at a time. This code is complex but there's no need to memorize it. This code will be very similar for future projects as well.

First, we'll add using statements to import necessary dependencies:

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

These import built-in .NET namespaces that are required for creating a web application. They can help us construct HTTP requests, configure our project, and ensure necessary built-in functionality is present in the correct areas.

Next, we'll add a namespace and class declaration:

FriendLetter/Startup.cs
...

namespace FriendLetter
{
  public class Startup
  {

  }
}

We declare a Startup class in the FriendLetter namespace. It's standard practice to use a namespace that reflects the name of the project.

Next, we'll add a constructor to our Startup class:

FriendLetter/Startup.cs
...

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

    public IConfigurationRoot Configuration { get; }

  }
}

This constructor will create an iteration of the Startup class that contains specific settings and variables to run our project successfully. It's required for configuring a basic ASP.NET Core MVC project.

We also add a line of code below our constructor: public IConfigurationRoot Configuration { get; }.

This is part of adding custom configurations to our project. We'll continue configuring by adding a ConfigureServices() method below it:

FriendLetter/Startup.cs
...

    public IConfigurationRoot Configuration { get; }

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

ConfigureServices() is a required built-in method used to set up an application's server. We can use it to configure other framework services. For instance, services.AddMvc() adds the MVC service to the project. This is a bit like ensuring our dependencies are available in the necessary areas.

Finally, we'll add one last required method called Configure():

FriendLetter/Startup.cs
...

    public IConfigurationRoot Configuration { get; }

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

    public void Configure(IApplicationBuilder app)
    {

    }
...

The Configure() method is built-in and required in all ASP.NET Core apps. ASP.NET calls Configure() when the app launches. It's responsible for telling our app how to handle requests to the server.

Let's add code to this method that states which area of our application should load by default when it launches:

FriendLetter/Startup.cs
...

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

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

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

The first block, which includes app.UseRouting() and app.UseEndpoints(...), tells our app to use the MVC framework to respond to HTTP requests. This block of code also sets up default routing for our application. It tells the project to use the Index action of the Home Controller as the default route. This will be our homepage. We'll discuss routing in greater detail in a few lessons.

The second block, which starts with app.Run(...), is not actually required to successfully launch our project. However, it will allow us to test that our Configure() method is working properly. We'll revisit this in the next lesson.

Program.cs

We also need to create our Program.cs file. It'll contain our Program class and Main() entry point method used to launch our project. We'll be able to reuse most of its code between projects. We'll begin with the necessary using statements at the top of the file and also add a namespace and class.

Then well declare both a namespace and class:

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

namespace FriendLetter
{
  public class Program
  {

  }
}

Note that both Startup.cs and Program.cs files contain code in the same FriendLetter namespace. This ensures the code blocks in Startup.cs and Program.cs have access to each other. This will be important later on.

Finally, we'll add a Main() entry point method to our Program class:

FriendLetter/Program.cs
...

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

      host.Run();
    }
  }
...

In the next lesson, we'll learn how to build and launch a basic ASP.NET Core MVC app.


Example GitHub Repo for Friend Letter

Sample .csproj File

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

Sample Startup.cs File

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

namespace ProjectName
{
  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.UseRouting();

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

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

Sample Program.cs File

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

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

      host.Run();
    }
  }
}

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