Bootstrapping ASP.NET Core - Part 1

In the first technical post in the Bootstrapping ASP.NET Core series we take a look at what makes up a new ASP.NET Core project from install to producing simple HTTP Responses and the building blocks we'll use to build Walk Fido, a dog walking application.

You can read the introduction to this project here

Learning to Crawl Before Walking

My oldest son has always been somebody who just does things his own way. From what he reads, how he learns music or even how he chose to play soccer when he was a kid. My wife and I knew we were in for a unique ride with the little guy when at 8 months old he refused to learn how to crawl and instead skipped straight to standing up and walking. As first-time parents we were caught a little unprepared for the rapidness of his mobility. Other than scrambling around the house to secure every cabinet we could find we didn't give much thought to the fact that he had never learned to crawl. We did have one friend who repeatedly reminded us of some study she had read in college that indicated that our boy would not learn how to read well if we didn't force him to learn to crawl first. This seemed like a humorous conclusion and other than providing a good laugh we ignored it and continued securing cabinets.

At the risk of ruining the punchline my boy taught himself to read at a young age. We discovered that he could read and not just memorize his story books when he loudly asked us what "Hooters" meant one day while we drove past the local mall. After taking a large breath I answered,

"I don't know son. It looks like it has something to do with owls."

So much for that crawling and learning to read thing I smugly told myself as I drove home. Until a few weeks later when I found myself crammed into a plastic tube on the top of a fast food play set trying to drag a screaming toddler down three stories to safety. My son had grown too tall to walk through the tubes and still had not learned how get down on all fours and crawl to the other side. We started learning how to crawl as soon as we got home, well after we got home and finished our ice-cream.

Cute story but what does this have to do with learning ASP.NET Core?

I wanted to start the series with this story because between modern IDE's like Visual Studio and the available project starter templates it is very easy to begin walking with a new technology or framework before we have ever really learned it. With a few button clicks the default new project template in Visual Studio gets you started with a new application containing MVC, Configuration Files, Entity Framework, Database Migrations, User Authorization and Registration and probably more features that I didn't notice.

Eventually our applications will grow and like my son at the top of the play set we will encounter an obstacle that forces us to go back and learn what we skipped over. So instead of starting with a working application we are going to start with an empty project and build our way up beyond the starter templates. It may take longer than just jumping in but my hope is it will make us more capable later on.

Prerequisite Installs

Before you can follow along with the code in series you will need complete the following installs:

  1. Visual Studio 2017 RC and .NET Core
  2. Git Client

Visual Studio 2017 RC

You can install Visual Studio 2017 RC and .NET Core by following the installation guide here. I will be using Visual Studio 2017 RC but there are also instructions at this link for installing .NET Core with Visual Studio, 2015 which should work fine for most of this series.

Once you've completed the installation process and can see the ".NET Core" option from the Project -> New dialog you should be all set.

visualstudio

Git Client

All the source code for this series will be hosted in GitHub at https://github.com/hansonio/fido. The plan right now is to keep each part in a dedicated branch. You can clone the repisitory to follow along.

git_clone_fido

Create the Project

Now that everything is installed we can create a new empty project and begin crawling our way through ASP.NET Core.

The first thing that we are prompted with after Project->New in the .NET Core folder is a option of 5 project types.

projecttypes

The first two Console App and Class Library are pretty straight forward. The next two options are for a couple of different flavors of Unit Test projects. We'll likely return at some point and create a class library but the last one ASP.NET Core Web Application (.NET Core) is the one that we want.

We'll name the project Fido.Web and click okay. We are then asked to select a Template.

aspnetcore_web_templates

Since we are crawling first we'll select an Empty project but if you want walk around for a bit in the deep end you should select Web Application and change the authentication to "Individual User Accounts" to get the full meal deal.

Notes:
* docker support looks interesting
* WebAPI template only supports Active Directory, Windows or None for Authentication options. I would have hoped for some sort of token based option as well

Empty Project

Surprise, surprise the empty project is not empty! Okay maybe that's not a surprise but the project is pretty bare.

project_structure

As I crawl around the project I find 2 files I care about in Program.cs and Startup.cs and one file I used to care about a lot but I am told I shouldn't care about so much any more in web.config.

Update NuGet Projects

Because the project templates in Visual Studio and the NuGet packages it references are likely updated on different schedules I always like to update my NuGet packages immediately after creating the project. In this case it looks like there has been an update for the packages since the template was created so I want to run an updated and restore.

nuget_update

After performing the update I received a compile error complaining about my framework version. I had to go into the project settings and update the Target framework option to use .NETCoreApp 1.1. You may or may not encounter the same issue.

target_framework

The .csproj

The NuGet package manager still works as expected from my experience with other projects in the past but I noticed that there is no packages.config file in the project root directory. I recall that at one point during the development of ASP.NET Core a new project file format was introduced called project.json. My understanding is that project.json is being removed and projects will again be defined in an msbuild files with a .csproj extension. So I cracked open the .csproj and I am pleasantly relieved to see a new ItemGroup for PackageReferences.

<ItemGroup>
    <PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.0.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.0.0" />
  </ItemGroup>

There is also an ItemGroup for a list of folders to include in the project. This means that any file I place in an included folder will be included in my project.

    <ItemGroup>
        <Folder Include="wwwroot\" />
    </ItemGroup>

Program.cs

I have built a lot of web applications using previous versions of ASP.NET so this file felt out of place at first but in ASP.NET Core the Output type for the project is Windows Application not Class Library as in previous version of .Net. I think I could dive into a lot of detail on why that is but for now it is only important to know that Program.cs is the entry point to our application.

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

There is a lot going on under the hood in each of those method calls but at a high level they perform the following:

UseKestrel() Use the web server included with ASP.NET Core.see more
UseContentRoot(Directory.GetCurrentDirectory()) Path to application files
UseIISIntegration() Run using IIS if available
UseStartup() Class to use as our application startup class. This is were the meat of the application will hook in

For most of our scenarios, and all scenarios I can think of for our application, these default values in Program.cs will not need to be changed. But it's good to know that it's there.

Startup.cs

Now that we've seen where the Startup class is referenced when a new instance of the application is created we can review how an ASP.NET Core application is configured.

The class was created with two default methods ConfigureServices and Configure. These methods represent the two key building blocks for an ASP.NET Application; services and the request pipeline.

public class Startup
    {
       public void ConfigureServices(IServiceCollection services)
        {
             
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            //...//
        }
    }

Configure Services

The ConfigureServices method is used to setup the Dependency Injection container for the application. In previous version of ASP.NET we would have to make the choice to add and register a container. Often this would be a container like StuctureMap, Autofac or Unity and then we would have to find the correct place and way to integrate the container into the application.

In ASP.NET Core dependency injection is baked in. The very first method ConfigureServices is there to allow the container to be configured.

public void ConfigureServices(IServiceCollection services)
{
         services.AddScoped<IMyInterface, MyImplementation>();
         
}

I'm sure I'll come back here as the application is built out.

Configure - Setting up the Pipeline

In previous versions of ASP.NET we would have various events to hook into during the Request Life Cycle, knowing the request life cycle even became a common interview question.

In ASP.NET Core the event driven life cycle is removed and replaced with a single, simplified request pipeline. The request pipeline is composed of a series of request handlers called Middleware.

The middleware instances are called in the order that they are added to the app instance during the Configure method.

Each piece of middleware may choose to perform some logic when it receives a request, send the request to the next piece of middleware in the pipeline, perform some logic after the next middleware has handled the request or short circuit the pipeline and return a response to the request without calling the remaining instances in the pipeline.

pipeline diagram

The empty project adds two middleware instances to the request pipeline.

if (env.IsDevelopment())
{
	app.UseDeveloperExceptionPage();
}

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

UseDeveloperExcxeptionPage is added to the request pipeline only when we are running in development. This middleware captures any exceptions thrown while processing the request and returns an HTML error page to the developer instead of leaving the application unhandled.

app.Run(...) is a terminal middleware call. The method can be used to run some code on the current request HttpContext. It will never run subsequent middleware.

Running the Application

Now that we understand the application structure we can crawl our mouse up to the toolbar and click debug button to launch "Hello World" in a browser.

helloworld

If we update the app.Run call to throw an exception we can see the developer exception page at work.

app.Run( (context) =>
{
	throw new Exception("No Hello World for you!!");
});

developer_exception

The async operator was removed for simplicity.

Next Steps

There really isn't much to the source code yet but you can still get it from the GitHub Repo here.

In the following parts we will implement the following:

  • Add MVC to the project
  • Define our initial REST API using simple Controllers and Routing
  • Configure the default Javascript serializer
  • Publish to Azure from Visual Studio

After that we'll look at:

  • Configuration in ASP.NET Core including .json files, environment variables and users secrets
  • Handling different ASP.NET Core environments
  • Database Access and Management with Entity Framework Core

Also, you should register for Boise Code Camp or come and present a session yourself.