ASP.NET Core with Docker Container – Part 2 Dockerfile

In ASP.NET Core with Docker Container – Part 1 Mounted Volume, I covered my experiment with Mounted Volume. In this post, I will explore the possibilities of Dockerfile. By reading on the internet, watching courses on Pluralsight, I know what Dockerfile is. “Know” means, well, just heard about it, saw people playing with it … on videos. Just like the first part, I want to explore it, do something with it.

I want to ship my application in a container. I want to be able to take that container and run it on another machine.

Dockerfile

I found a good article about it here by digital ocean. I feel it is too much to get started. And for a beginner, like me, it is hard to understand.

Dockerfile is a set of instructions to build a Docker image.

So the next question is what are the fundamental instructions to build an image? I always like to start with fundamental.

Fundamental Instructions

FROM

Instruct the base image we will use to build up. Docker gives you the ability to build your own image base on existing one. Think about it for a moment. We can take an existing aspnetcore-build image (which is made and maintained by Microsoft), and build our own image with some custom features.

FROM microsoft/aspnetcore-build

That’s all it takes to build your own custom image with full power of the aspnetcore-build.

MAINTAINER

It is nice to tell the docker that you maintain the image. It is you, the owner, the maintainer.

MAINTAINER thaianhduc

 

COPY

Start making your own custom image. The “COPY” instruction will tell Docker to copy a folder into a specific folder inside the container. It is the same concept as Mounted Volume, except, instead of creating a mapping, it copies the data.

COPY . /app

The above command will tell the Docker to copy the working directory into “app” folder inside the container. The equivalent in Mounted Volume is “-v ${pwd}:/app“.

WORKDIR

The directory that container will start. Think the same way when we open a Powershell or CMD in Windows. In our web application, it will be the web directory that we created in the COPY instruction.

WORKDIR /app

 

RUN

Given that the working directory, the container will run commands instructed by RUN. In our previous web application, we want to run “dotnet restore” and “dotnet run” commands. They might look like this

RUN dotnet restore

RUN dotnet run

Note: I might not want to build application inside the container. Most of the time, I want to ship my application, not source code.

EXPOSE

The port that a container exposes to the outside.

EXPOSE 8080

Which means other systems can communicate with it via port 8080.

ENTRYPOINT

All the above instructions tell Docker how to build an image. The ENTRYPOINT instruction tells containers what command to run once it starts. Let’s think about a web application scenario, once a container starts, we want to start our web server inside the container.

ENTRYPOINT ["dotnet", "Coconut.Web.dll"]

In Action

With the discovery from Dockerfile, I reframe my steps more precisely. I will/want

  1. Build an ASPNET Core Web Application on my host machine with VS2017 Community.
  2. Publish it to a local folder.
  3. Build a Docker image with the published application in.
  4. Start a container from my custom image.
  5. Access my web application from host browser.

Before started, I want to make sure that I have a working website published. This should be easy done by asking VS2017 to publish my project to a local folder. By default, it will publish to bin\Release\PublishOutput folder.

Website up and run well

So given at the published folder, when run “dotnet Coconut.Web.dll“, my website is up and run. So far so good.

How about recap the Mounted Volume approach? Which means I want to run this command

Recap: Run app with mounted volume

At the last line, I want to start an ASPNETCORE container to host my published application. Shall it work? Let’s find out.

It looks ok. Except, I cannot access the website from host browser. Which means something was wrong; well not a surprise at all. Turn out I made the wrong port mapping. It should be port 80 inside Container instead of 8080.

docker run -t -p 5000:80 -v ${pwd}:/app -w /app microsoft/aspnetcore bash -c "dotnet Coconut.Web.dll"

Create Dockerfile

A Dockerfile is a simple text file. You can create it with any your favorite editor.

# Custom image based on aspnetcore to host a web application
FROM         microsoft/aspnetcore
MAINTAINER   Thai Anh Duc
COPY         . /app
WORKDIR      /app
ENTRYPOINT   ["dotnet", "Coconut.Web.dll"]

For naming convention, I name it Dockerfile. I use VS2017.

Build a Custom Image

So far I have created a published application and a Dockerfile. Things seem ready. Next, we need to tell Docker to build an image from the Dockerfile.

The current folder structure looks like this

\bin
    \Release
            \PublishOutput
Dockerfile

Let’s try to run my very first build command. However, it failed right after build. Because that folder structure will cause some security issues. To make my life easy, I move the Dockerfile into the PublishOutput folder.

docker build -t thaianhduc/aspnetcore:0.1 .

Hey Docker, take the default Dockerfile at the current location (where the command is run), build an image, give it a name “thaianhduc/aspnetcore” and tag it with version “0.1”.

Do not forget the “.” at the end. It represents for “current location“.

// Run the command to list all the images. The new image should be there
docker images

Run It

Time to enjoy the fruit

docker run --name my-coconut -p 5000:80 thaianhduc/aspnetcore:0.1

Open the browser on my host machine, type in http://localhost:5000/hello_beautiful. Oh yeah! It works.

A Few Words

I have failed many times while experimenting and writing the post. Everything seems easy while you read it on the internet. However, when it gets down to actual do it. Evil hits your face at the first try. But that is actually a good thing. I have learned so much while trying to solve those problems. Some of them I understand, some I do not.

So far I have been playing around with the fundamentals of Docker. For every single command, for every single action, I try to explain to myself in my own language. The language that I can understand and explain to other.

Having small goals at the beginning keeps me focus. It allows me to temporary ignore some problems. Otherwise, you will wonder in the sea of information out there. Reading something is easy. Making something works for you is hard.

How do I take my custom image and use on other machines? Easy. I can push my image to Docker hub. Then I can run it just like other images. Things make sense now. I can resonate without effort.

Deployment Options Recap

I started with learning ASP.NET Core and other new cool stuff. I want to learn about the infrastructure that I can take advantages of. Let’s assume that I have a web application, how many options do I have to deploy it?

  1. Local host (IIS): Obviously I can simply press F5
  2. Deploy to Azure for free.
  3. Run it inside a container using Mounted Volume approach.
  4. Or deploy it as a Docker Image.

What’s Next?

I want to step further into the ASP.NET Core, from a fundamental point of view. Maybe later in the series, explore the possibilities of Docker in term of Microservices.

That would be fun!

 

ASP.NET Core with Docker Container – Part 1 Mounted Volume

One step further into Docker world, the biggest question I have to ask myself is “where do I want to go?“. What do I know about Docker? How could I explain in a simple sentence?

As far as I’ve known so far, Docker gives me a box (container), in which I can run something in an isolated environment. When I do not need it, I might throw it away. And when I need it, I can build it quickly.

MeWithDocker
I have a box. What should I do with it?

Given that I have a box, and I can open the box, what will I put in? what should I do with the box?

As a developer, the first thing I want to try is to put some code inside the box and be able to run it. Yes! That’s right! I will put ASP.NET Core web application code into the box, and run it.

In this post, I will go through all the things I have learned, collected so far and put them into practice.

Hey, Boss! How Do I Get The Source, Docker Asked?

Calm down! Calm down! Docker. Let’s me show you where to get the stuff you need.

External – Mounted Volume

Docker can refer to the source from an external (relative to itself) system. In a development environment, it is our host system, the folder where we put our code.

DockerConnectToExternalSource
Connect to external source, a folder on host machine

I will install a container that specializes for .NET Core. Should be easy, just head over to Docker hub, find Microsoft. Take the microsoft/aspnetcore image. Time to type some fun commands with Docker in Powershell (I started to love CLI interface). Because I am going to use it for a while, I will pull aspnetcore image from the registry.

docker pull microsoft/aspnetcore hit enter. Boom! you have the image ready to serve you.

DockerApsnetCore
Docker Aspnet Core Image

As a good habit should run the docker images and docker inspect to look into the container. Just to make sure everything is in place.

To connect, Docker introduces the Data Volume concept. You can read the full document at the website. However, I would like to go with the basic approach.

Think of Data Volume is a mean define a mapping between a location inside the Container and a location on the host machine.

We have

  1. A Docker container that can host and run a website.
  2. A folder where we develop our source code.

And Data Volume allows a running container access that folder. When it finishes, the folder is still intact. All the changes that the container made, persists there. Let’s try out.

I want to run a container that will start my website. Breaking down to small steps, when running a container, it must

  1. Start the container instance in background mode
  2. Connect to the folder where my code hosted (local drive)
  3. Start a Kestrel server to run my application

While experience, it seems I need to use the aspnetcore-build image instead. Because I need the Core SDK to run and build my application. Jump over the Powershell, I run my very first command with a smile. Boom! it does not work

Oops! Not work boy

Let’s try to make it worked first and then I will explain every single part in the command.

The best way we should do when investing an issue is to look into it, docker inspect command is your friend.

Docker inspects the problem

Something is wrong with the volume mapping.

After some investigations, the correct syntax that I should use

docker run --name coconut -i -p 5000:80 -v ${pwd}:/app -w /app microsoft/aspnetcore-build bash -c "dotnet restore && dotnet run"

In term of speaking language, the above command says

I want to run a container from the microsoft/aspnetcore-build image, named it as coconut. Once started, create a volume mapping between the current host folder (via ${pwd} keyword) and app folder in the container, create a port mapping between port 5000 (host machine) and port 80 (on the container). The finally runs the command dotnet run with under working folder app.

Just like before, I hit another error, saying that I should share the drive with the Docker. The solution is written here.

I must admit that thing is not easy as it seems. After struggling for a while, I finally manage to get it worked.

Pay attentions to

bash -c “dotnet restore && dotnet run”

The command instructs the container to restore NuGet packages and then run the application.

And

-p 5000:80

Once the application is started in the container, the website is exposed via port 80. Note: if you start an application on your host machine, it is exposed via port 5000. That is also why I take the port 5000 on the host machine.

The final result, a website running in a container

Initially, I wanted to write both the data mounted volume and Dockerfile in one post. However, the more I get my hands dirty, the more I learn. It is better to recap what I reap.

Recap

To run a container that starts an aspnet core application, uses this command

docker run --name coconut -i -p 5000:80 -v ${pwd}:/app -w /app microsoft/aspnetcore-build bash -c "dotnet restore && dotnet run"

The port mapping (-p 5000:80) is very important. It allows you to access your website from the host browser. To know the port that dotnet exposes after running the website, you should look at the output in the container console.

To map your current working directory to a folder in the container, use -v ${pwd}:/app. The ${pwd} on Powershell will get the current directory.

Because I made many mistakes, I learn to use the docker stop/start/rm commands. Now they are mine 🙂

Evil is everywhere. You should use docker inspect to look inside the container.

One of the biggest achievements is the feeling of getting started, of getting into. I am able to use many commands at my disposal.

What’s Next?

Finish what I have started – Use Dockerfile to build and ship my applications.

Updated: Part 2 ASP.NET Core with Docker Container – Part 2 Dockerfile.

Docker, What Does It Mean to Me?

Now that I finished the flow to push the code from my laptop up to the Cloud. I also started to play around with Docker; also a bit of ASP.NET Core. I have many dots. The next challenge, as always, is to connect them. Try to make sense from all pieces. Let’s focus a bit more on Docker; create a connection between Docker and ASP.NET Core.

There are many materials about Docker. It is easy to start playing around with Docker, as I wrote here. Pretty basic stuff. It is easy to find out how to run a command. The Docker website has an extensive documentation, which tells you everything you need to know about Docker.

But, to me, It is useless if I cannot make sense of “the why”. After playing around with commands, watching some courses (mostly from Pluralsight), I have to find the answer for questions

  1. Why do I need it?
  2. What problems does it solve?

I try to create an image of it in my mind. It is such an important step, that if I fail, I cannot continue. Just like, how can you run if you do not know why and where to run!

So let give it a try before moving deeper into the implementation detail.

Why Docker? Container Approach

I would like to call it “Container Approach“. Below are some benefits, in my opinion, that give me good reasons to invest in.

Improve Cooperation

If we develop small systems which are easy to setup and deploy, the need of Container might not be obvious. Because, as a developer, we can check out the code, hit F5 and we are good to go. If we want to deploy those systems to QA’s machine or some sort of central servers, it is still a trivial task.

However, when systems are big where there are many services, require complex infrastructure, things get complicated quickly and cost lots of time. Take an example of a web application. I would assume the system consists of

  1. Front end application: Build on top of AngularJS. This application will connect to a backend service via WebAPI endpoints.
  2. Backend service: The backend service built with ASP.NET Core. It supplies endpoints that Front end application will consume.
  3. Database: SQL family server. Can be SQL Server, SQL Express, SQLight, or MySQL. Use EF as Data Access Layer (ORM).

The team consists of Frontend Developer, Backend Developer, and Tester. Each might have to install the same infrastructure to run the application. Given that we have not had a central deployment place yet. It means that

  1. Front end developer has to install all requirement software, infrastructure, that only Backend Developer required.
  2. Back end developer has to install the things that only Front end developer needs.
  3. Tester has to install development environment even they do not know about coding. They might have to setup local IIS.

When a new member joins the team, there are so many repetitive works.

What if

  1. Front end developer will take the api component, and load it up on his machine without installing anything. He will focus on building the cool frontend, and connect to that API.
  2. A tester will take the application as a whole, and run it with a single click, without installing anything.

With a proper developed, Docker can help.

Develop Faster, Test Faster

Docker will give us the minimum-required infrastructure we need to build and test an application. For example, when I want to develop a system running with MongoDB. Instead of downloading and installing MondoDB locally, I can get a prebuilt docker image with MongoDB installed.

The ability to switch infrastructure gives developers a lot of flexibilities.

Develop Componentized Thinking

This might not be true for others. However, it works for me. I shape my thinking process. A system composes of many small components. Each component might run in a Container. This, in turn, will force me to think, what should I put in a single container.

What’s Next?

I try to make sense of Docker, try to explain it to me. I do not make any suggestion or judgment regarding its benefits. But will all those in mind, I am ready to invest more in the journey.

Docker helps

  1. Improve cooperation
  2. Develop faster, test faster
  3. Develop componentized thinking

The next step is, as usual, to try things out. Connect the dots between Docker and ASP.NET Core. This post intended to write about it. However, I changed the intention as I wrote.

ASP.NET Core Full Lifecycle From Laptop to Cloud

Given that you have to develop a full lifecycle of a web application, where will we start? If working in a company, where there are processes for developing and releasing products, the story might be different. But what if we want to develop our own pet projects, a web application, how could we do that? What is the minimum cost?

Asking a web developer, they might come up with many things, many pieces. They are dots. The question is how do we connect the dots?

As a developer, most of the time I play around with business code; solve business requirements with domain logics. In short, they are none-infrastructure code. When started my learning journey this year, I wanted to play around with the infrastructure.

After being able to build a minimal ASP.NET Core web application, I learned from Scott Allen Developing with Azure course. It is such a wonderful course as always. I decided to try my own with the newest .NET tools I have at hands. Try-and-write is a good way of learning. This makes sure that I get the best value out of my time.

Note: This is a long post. I write it while I experience. Write on the go.

Let explore and find the answer for the questions.

How to build a product from your laptop and deploy to cloud? How much does it cost? How to connect the dots?

Overview

I will need these tools/components complete the work

VS 2017 Community Edition + .NET Core 1.1: To code the application. But not required. Because with .NET Core you can code in notepad and it still works.

GitHub Account: I want to host my code on GitHub. Obviously, it is not a requirement. But I want to try out. Alternatively, you can host code on Visual Studio Team Service.

Visual Studio Team Service (VSTS): To host code (if not hosted on GitHub), build and release.

Azure Account: To host the web application.

We, however, can deploy directly from VS 2017 or Powershell to Azure. But I will not explore that option in the post. Because it rarely happens with real projects.

I want to setup this flow – I like to draw on paper (even it does not look good 😛 )

Asp.NET Core expected deployment flow
Asp.NET Core expected deployment flow

VS and GitHub

That should be simple. Download the GitHub Extension for Visual Studio here. Follow the instruction and you have your visual studio connected with your GitHub account. Mine is here, my country town has many coconuts.

GitHub to VSTS

Next, I want to make a build in VSTS which will build the code hosted on my GitHub account. But, first I want to introduce you the Visual Studio Team Service (VSTS).

Take a look at its pricing scheme. You will choose the Free model. With free model, you have

VSTS Free service benefits

Which will you pretty much everything you need to develop a pet project with your friends. Explore more when you have time. Here I want to pay attention to the build capacity.

VSTS free hosted pipelines
VSTS free hosted pipelines

If your build and deploy take 2 minutes, you have 120 builds per month; or 4 builds per day. That should be enough for a personal project. I suggest you create your own account if you have not had yet.

I have created a “Production” project. I was supposed to host my code in production (or something like that). But now, I will use it to take advantages of build capacity. Which means the project has everything, except code.

Add a new build definition and choose the “ASP.NET Core (PREVIEW)” template. Once created, take a deep look at the generated build definition

ASP.NET Core build definition
ASP.NET Core build definition

At the minimum, we have the process definition with 6 steps

  1. Get sources
  2. Restore
  3. Build
  4. Test
  5. Publish
  6. Publish Artifact

Get sources

To build, we have to tell the build engine where to get the source code. I want to use build code hosted on GitHub. There are 3 steps involved

  1. Connect to GitHub used a proper authentication method. I used Personal Access Token.
  2. Specify the repository to get the code, I used thaianhduc/coconut.
  3. And finally tell the branch: master
VSTS Build integrate with GitHub
VSTS Build integrate with GitHub

After setup, it should look like the above.

Because I have not had Azure Setup or Unit Test yet, I will disable some steps. They should be enabled later when I need them

VSTS disable a step
VSTS disable a step

For any step, you can click on the Control Options, and uncheck the “Enabled” checkbox.

The other steps (Restore, Build) use default settings. It will just work.

Test the Build

Should I enjoy the setup? Time to test the integration.

Pretty simple with just a single click

VSTS queue new build
VSTS queue new build

A dialog shows up. Simply click ok. We will not tweak any configuration value. Wait a few seconds then the build is triggered. You see a nice Console output. The console will tell you what is going.

Not everything is easy as it seems. I got an error message at the restore step

error: Invalid input ‘d:\a\1\s\Code\Coconut.Web\Coconut.Web.csproj’. The file type was not recognized.
Error: C:\Program Files\dotnet\dotnet.exe failed with return code: 1
Dotnet command failed with non-zero exit code on the following projects : d:\a\1\s\Code\Coconut.Web\Coconut.Web.csproj
Oops! fail to restore
Oops! fail to restore

Let find out how to fix the problem. At this point in time, I depend on Google. We all depend on Google, do we? It turns out that many people having that problem. The solution is given here in the SO. In short, I have to use the Hosted VS2017 agent (instead of just “hosted”).

I love it. Beautiful it is.

Azure Cloud

So far, I am half way to the cloud. Playing around with Azure is a bit of nervous because of Credit Card involved. I hesitated to play with it because I did not understand it.

Not anymore! Let’s go ahead and play with it (I was empowered with the course about Azure 😛 ).

All I need is a cheap app service. Maybe I can have a free account. For each app service, it is a good practice to have at least 2 slots: Staging and Production.

Login the Azure Portal and start creating a new App Service. Choose the default Web App from the gallery

Azure Web App
Azure Web App

Hit the “Create” and configure with minimum requirements.

There are a couple of concepts that I have to capture when working with Azure. I try to explain here in a way that I can understand. Hope the explanation also helps you.

First, take a look at the final result of my App Service

Azure App Service General Information
Azure App Service General Information

When visiting the Azure Portal, it looks confusing. There are so many items on the portal, many places you could click on. There are a bunch of documents out there showing you step by step how to create an App Service. I, once, read them and did not understand them. Of course, I could follow step by step; but with a blind eye.

There are 3 basic concepts we should understand: App Service, Resource Group, and App Service Plan.

Resource Group

Everything in Azure is a resource. Resources are organized in groups. By using group, we can handle many resources easily.

Resource group is a logical concept. You will not know or care where/how resources are deployed.

Imagine you practice developing a web application with Azure SQL. When you finish and do not want to keep them anymore, instead of going to each resource and delete, you could simply delete the resource group in one click.

App Service

It is a placeholder where you deploy your services. Think of App Service as your own computer without your maintenance. You do not have to install Softwares. You do not have to do anything at all.

However, you have to define a configuration applied to the service. Azure needs information to build a proper service instance. This is done at the first step. When you create a new App Service, Azure asks for a template, such as Web App, Web App + SQL Server, … By choosing a template, you define the configuration applied to the service. The beauty is that you have done with just a single click.

Each app service is given a unique URL (mine is: http://coconuttree.azurewebsites.net)

App Service Plan or Pricing Tier

Manage the cost. The service plan will tell you how much you will have to pay. You can choose the Free tier 🙂

 

So far, I have not had to pay for anything. They are all free. Clicking on the service URL to verify its existence. Well, so far it will display the default page generated by Azure.

I want to have 2 environments: Staging and Production. In Azure term, they are called development slots. Azure makes it super easy to create them. But, it seems with the free service plan, it is not allowed. I think it makes sense. You cannot ask too many things with a free service.

I will stick with the default deployment slot. The ultimate goal is to have a full cycle of development.

VSTS to Azure

From the concept level, deployment to Azure consists of 2 steps: Package the build result and Push the package to Azure. Ok! what does it means in the context of VSTS?

Go back to our VSTS build, and enable these 2 steps

VSTS Enable publish
VSTS Enable publish

By looking at each step configuration, we can guess what they do

  1. Publish: will publish (by run the publish command) the web project to a place defined by {build.artifactstagingdirectory}. I do not know where it is. I just know there is such a thing
  2. Publish Artifact: will take the output from the Publish step, create an Artifact name “drop” with type “Server”. I guess this step will take the input from Publish step, create an artifact “drop” which can be deployed to a server. Therefore, the output is a package which can be deployed to somewhere else, Azure for example.

So far, I just enable them and try to explain them base on my logical thinking of what they should be doing.

To deploy the build to Azure, I will look at the Release tab. As its name suggests, I think its job is to release a build into a production server. Let’s check it out.

Create a release

Click on create a new definition, you can choose among many options. Right there on the top, that is what I need: Azure App Service Deployment

VSTS Release to Azure App Service
VSTS Release to Azure App Service

Next step makes thing very clear for me. The release will take the output from the Build flow and deploy to Azure

VSTS Release from build output
VSTS Release from build output

Then you have to setup the connection with your Azure App Service. It is pretty straightforward.

So far so good. Let’s test things out.

Run the build, it looks ok, except

VSTS_WebConfigIssue
Publish requires a web.config file

When I take a look at the Console (just curiosity), I found out interesting things. Btw I should able to fix it easy. As the message suggests, I add a web.config file to the project.

The result looks promising. I do not understand the output log. But seem it works as expected

Publish artifact
Publish artifact

Should the Release work? Try it out.

Access the Release tab, kick off a new release, here we go, a nice dialog. I will make some guess.

Release to Azure
Release to Azure

It takes the input from the last build, obviously. So far so good. Ok kick the build.

Bingo! It works. It just works. One of the nice things is that you can see all the logs. You know exactly what was going on

Release logs
Release logs

There are so many settings in VSTS that you can tweak. You can setup continuous integration (CI) with a checkbox.

At this point, I can claim the victory. My mission has completed. It is a long post. It is time to summary what I have accomplished.

Summary

First, let talk about the cost. It costs me nothing. I have accomplished these wonderful things with zero USD, 0USD.

I code my application in my laptop with VS2017 Community Edition. It has all the features I need to build a web application.

I host my code on GitHub. If I want to make my code private, I can host it directly on VSTS.

I use VSTS to define my Continuous Integration (CI) and Continuous Delivery (CD). I really like the idea of separating the build and the release. This allows me to build many times to ensure the code does not break. However, I do not want to release every time I commit code. Separation of Concern is a powerful design concept.

I use Azure Cloud to create an App Service to host my application.

At each step, I can customize to fit my needs. All those wonderful features cost me nothing.

I am so happy to get the job done. I hope it gives you some good information, well, to start, somewhere.

ASP.NET Core Get Started

The learning journey continues with .NET Core stack, the latest framework from Microsoft. As a developer, I decided to check out ASP.NET Core.

The general path is to answer the question I asked (myself) in this post “How to take the advantages of Docker?” .NET Core seems to be a good candidate to explore.

As a habit, I immediately head to Pluralsight and check out the best Author, Scott Allen, course ASP.NET Core Fundamentals. Scott has a unique way of transferring complex stuff into your head. I highly recommend the course.

After watching the course, the biggest question I asked “What do I get? How do I start from here?” Follow step by step in the course is so simple. I will not learn much that way. Because I have experienced in code, not a starter.

How do I get the best out of the course?

Overview

I try to draw an image of the components that make up an ASP.NET Core application. Without an overall image, you will get lost in detail.

AspNetCoreComponent
ASP.NET Core Important Parts and Concepts

With a pencil, a paper, and my terrible drawing skill, I draw a picture of my understanding of ASP.NET Core pieces. Those are the fundamentals to get started with building web applications and exploring the power of ASP.NET Core.

Before explaining them, let take a look at the minimum code generated by VS2017

Empty Web project created by VS2017
Empty Web project created by VS2017

Very neat, clean! There are 2 files: Program.cs and Startup.cs.

Startup

The Startup is where developers build the application components. Take a look at my drawing, there are 3 major concepts

ConfigurationBuilder

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath);

            var configuration = builder.Build();
            var appKey = configuration["appConfig_Hello"];
        }

In the past, we have web.config. We define connection string, appSettings, …

ConfigurationBuilder allows developers to define where/how to read the configuration information. Usually, they are stored in JSON file. What it means is that the configuration builder will allow developers to wire up the dependent configuration data from static files.

ConfigureService

For any application to run, we need services. This is place we set up our dependency injection (DI)

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IMyService>();
        }

Note: You should be familiar with DI in practice.

ApplicationBuilder

The heart of the framework is the mighty ApplicationBuilder. As its name implied, it is a tool for us to build the application. It does many things. However, one of the important things is to build the Middlewares Stack.

       // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

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

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

How many middlewares do we have in the above code?

Answer: 2.

UseDeveloperExceptionPage: If there is an exception, display the exception page that developers can understand 🙂

Run: The middleware that handles all the request. It always returns “Hello Word!” text.

Middlewares are stacked. Which means that the order matters.

Some important behaviors of middlewares

  1. Order matters.
  2. One middleware can terminate the request which causes the next one is not called.
  3. There are many built-in middlewares, delivered by using NuGet packages.
  4. Most of them follow a naming convention. Usually, they start with UseXXX.

 

MVC Middleware

Let’s tweak the Run middleware a bit

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

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

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync($"You are requesting {context.Request.Path}");
            });
        }
Tweak the Run middleware
Tweak the Run middleware

In theory, we can build out web application by placing the logic inside the Run middleware. We have the power over the HttpContext. If we want to build our own MVC framework, we can do by following these high-level steps

If we want to build our own MVC framework, we can do by following these high-level steps

  1. Parse the request to extract information about Controller, Action, Parameters, …
  2. Dispatch the call to proper controller/action.
  3. Build HTML result from the controller/action result.

Or we can simply turn it on with

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseMvc();
            //app.Run(async (context) =>
            //{
            //    await context.Response.WriteAsync($"You are requesting {context.Request.Path}");
            //});
        }

All the magic is at this line app.UseMvc() (from Microsoft.AspNetCore.Mvc NuGet package). We have to remove the Run middleware call. Otherwise, it will override the result produced in the MVC framework. Order matters, remember?

Recap

I try to draw a picture that I can understand; that should be easy to explain. From there, I explain my understanding of components/concepts that build up ASP.NET Core application. This, however, is not a “how to” post. Once you know what you want to do, you can search for “how to” quite easy. There are thousands of valuable resources out there.

By redesigning ASP.NET Core in this way, it is a powerful framework to play with. Developers have so many power over what they want to put into the application. We, as developers, know exactly what are in the pipeline. Grab your head around new concepts and take advantages of them.

I use this post as a reference for my understanding; and if asked, I can reference to this post. If you are reading this post, please give me feedbacks if I misunderstood something.

For anyone that is learning anything new, I suggest you draw a simple picture of your understanding. If you cannot, it is a sign of you have not understood it.