ASP.NET Core Web API with EF Core into a MSSQL Linux Docker– Developer Path 2


Précis

In the previous post we accomplished the same goal of what this post will achieve however we will actually build out the entire process from beginning to end. When it comes to codebase, I will refer quite a bit to my Github repo as to save time and keep this post cleaner, where necessary I will take some screenshots or code snippets where it adds good visual value.  This post will begin with the creation of the ASPNetCore App created against a base ASPNet Core image in Docker Hub, it will build the solution locally, and finally show how to get that solution hosted on a cloud provider, as in my case Microsoft Azure.

I should also mention that I will be doing this from a Mac and I will be using Visual Studio for Mac 2017 Enterprise (I could have also used VSCode) as well as iTerm (Command Line Tool for Terminal … think PowerShell if you are a strictly Windows person) to issue commands in Docker. To view my work I will be using Chrome as my browser or Postman. 

If you are planning on doing this on Windows, not a problem. You can achieve everything I have done using Visual Studio, or VSCode for your IDE, you can use PowerShell to communicate with Docker and you can certainly use Chrome as your browser, or Fiddler or Postman.

Now you will need to have Docker installed on your Mac or Windows machine and for guidance on this you can go to this link.  FYI, Docker Compose is installed by default when you install Docker on a Mac or Windows, but on a Linux server, you must install it separately (GOTCHA: more to come on this if you want to install the latest version of Docker Compose on Ubuntu Linux 16.04). Here are the steps to getting this to work on your environment.

Coding the ASP.Net Solution

In this section we will begin the coding for the ASP.Net Web API solution, and we will conclude when we have it scaffold and ready to take Docker specific code which will be the inclusion of the following:

  • Adding a DockerFile
  • Adding a Docker-Compose.yml
  • Adding a Shell Script that will ensure that the Docker Container based on the MSSQL_Linux image is started and ready for Entity Framework
  • Updating the Connection String to allow the Web API to communicate with the database

The rest of this section will be basic stuff you can do in a Web.API solution regardless if you were going to be using Docker or not, so this should be pretty straight forward. 

Creating your ASP.Net Core Web API Solution and Project

First things first, create a directory somewhere to house your code. Ensure you are in that directory and issue the following command

docker run -v ${PWD}:/app --workdir /app microsoft/aspnetcore-build:lts dotnet new webapi

So lets look at what we have here, this command does the following:

  • We will be using the aspnetcore-build base image to create a ASPNet Core Web API project under an “app” directory both on your machine and eventually on the Linux host machine as in my case it is running on Virtual Box as a Linux VM. This is automatic when you install Docker (see below)
    image
  • After you execute that command you should see a few things.. one
    image
  • and two, you will have a folder now with the following content
    image
  • and if you open up this project in Visual Studio [note it will create an app.sln file for a new solution, if you do this in VSCode, it will not create this file] you should see
    image

From here you have the basic scaffolding of a ASP.Net Core Web Api and if you were to run this now and hit the Values Controller endpoint, it work work. But we have more work to do, in our use case, since we will be communicating with SQL Server and using Entity Framework Core, its time we add that package through Nuget.

image

and then accept the license agreement and finally you should have EF installed, a visual inspection under the Nuget folder should yield
image

The next things we need to do are pretty much Web.API stuff, so I am going to move pretty quickly here, and pointing to my Github repo when I need to call out certain files and the contents therein.

Creating your Model Class

So… our Web API will need something to connect to and this all starts with the Model Class that will represent the data that we are exposing. In our use case, we will be creating a Web.API to take, update, add, and review Speaker Evaluations for sessions that are delivered. As a speaker, I love getting feedback and I always wanted to build an app to collect it where it is not done by the conference organization. The model for this SpeakerEval is located here
image

Creating the Database Context

Now that we have the model created we can add a Database Context that will be used to set up the “Code First” approach that will eventually create a Database Table in the MSSQL_Linux Docker container, below is what the finished file looks like and can be accessed on github here
image

A few things to point out

  • Make sure to add a Using reference to EntityFrameworkCore
  • In line 9 we are adding DBSet which is what will create the Database table based on the “SpeakerEval” model previously created. Note we are pluralizing the actual table that will be created in the database to “SpeakerEvaluations”
  • In line 13 we are using Database.EnsureCreated to ‘ensure’ that the ‘database’ will be created

Create the Database Seeder

Now that we have the context set up we are going to create a new class called EvalDataContextExtensions and the purpose of that class is to check to see if the Database already exists in the MSSQL_Linux Container [line 13] does that conditional check and returns out of the call if it evaluates to True, if it evaluates to false, it seeds the database from line 18 onwards.

image

This file above ensures that when the Web.API is launched for the first time, there is data waiting and calls made to the HTTP GET/ Read method will return something and you know you solution is working.

Create your Default Connection and Access to the Database

The next thing we will do is create the connection string that will permit this Web.API solution to communicate with the underlying database. This could have been accomplished a few ways, I went with coding it in the Startup.cs file but I could have just as easily put it in application.json and used Configuration Manager to get to it. See below

image

So, a few things are happening here:

  • Line 36 we are defining the Connection String, the “db” you see in the ‘Server=’ needs to be mapped to exactly what you have in the “Docker-Compose.yml” file, which is where you define the ‘Services’ that Docker will be creating for you [Services is analogous to Containers]. the rest is pretty standard stuff, just want to also point out that the Database name “FabsEvals” does not exist on first run so you will see some failures when Docker is provisioning the solution but that is where the “EntryPoint.sh” script comes in and it loops till EntityFramework has done its job
  • In line 40 through 43 this is where we will register our DI into the Services Container pipeline so we can have access to it in our application. Here is a great article that explains Dependency Injection in ASPNet.Core and why it is a best practice to do it this way.
  • You will notice that we are adding “ApplicationDbContext evalDataContext” into the constructor in line 51 and in 58 we are calling the seed, this is the dependency injection at work.

Creating the Endpoints, Repository and Controllers

Now that we have wired up out Database now its time to actually get the Controllers working.  First we need to identify and set up the endpoints we will use in this Web.API and if you recall we said we will be doing full CRUD

Endpoints

HTTP Verb URL Controller Method Comment

GET

api/SpeakerEval/ Get() Get all people in the database

GET

api/SpeakerEval/3 Get(int id) Get SpeakerEval with id = 3 from the
database

POST

api/SpeakerEval Post(SpeakerEval model) Create a new Speaker Eval in the database

PUT

api/SpeakerEval/3 Put(int id, SpeakerEval model) Updates an existing SpeakerEval in the
database

DELETE

api/SpeakerEval/3 Delete(int id) Delete SpeakerEval with id 3 in the
database

Repository

Now that we have defined what we want as our endpoints the next step is to create a repository for our Controllers to access them from. In our case we will be creating an Interface and Service Class to implement that interface. The interface is called iSpeakerEvalRepository
image

and as you can see it has a few operations in keeping with our CRUD methods defined in our endpoints. Next we will create a service class to implement the interface, it is called SpeakerEvalsRepository 
image
This Repository is the primary vehicle for the Controller to communicate with, and in turn this Repository uses the DataContext to access the Database Server, so let us now look at the last piece of the puzzle.

Creating the Controller

So now we at the final component to get the Web.API finalized, when we are done wit this we will square away the Docker components. So, in the Controllers folder lets create a Controller for the SpeakerEval Model aptly named SpeakerEvalController

image

This controller executes against the repository previously created

Wiring up for Docker

So at this point we basically have all the necessary components in place for a working Web.API application, however for us to make this work in a Docker environment we will need to create a few more files

  • Dockerfile (required)
  • Entrypoint.sh (optional but in our case necessary for how I want to set up the order of operations for seeding the database and Web.API connection)
  • Docker-Compose.yml (required)

So, we will need to create a new file that does not have an extension i.e. its just called Dokerfile and it is case sensitive
image

Lets deconstruct this file:

Line 1: we are telling Docker that we will be basing this solution and running it on this Image of ASP.NET Core build.  If this image is already on your environment, it will just use it, if it is not, it will download it from DockerHub.

Line 2 through 6: we are basically doing a map the volume with the generated code, restore the dependencies, build the project and expose port 80. We will discuss Line 7 and 8 below when we get into the construct of the entrypoint.sh file
image

in this file we are making sure that the database restores after it starts up, and then will run the web api application. We are also doing a loop to add some time for the SQL Server database image to start up. Next and finally we are going to create a Docker-Compose.yml file which is how we tie together both images to create containers that ultimately will communicate with each other over a common network (called a bridge in docker) to make the solution work. There is a key difference in my previous post where I said that you can just spin up a working solution v/s this one where you are actually building your OWN solution.

image
Developer Version of the Docker Compose YML file

image
Easy Path of of just spinning up a working solution based on MY Custom Image in my Docker Hub Profile

What you will notice is that in the first image in line 4 we are calling the “build” command and the dot (.) is telling us we are in the current working directory to find the app.csproj file to build against. In the second file you will see line 4 is preplaced with my custom image so you don’t NEED the Web.API solution because my custom image has my solution bolted on using the Layered File System of Docker. Note also that on line 7 and 8 we are setting up the dependency of the Web.API solution to the base image Database that is on Docker Hub (unless you already have it locally on your system) NB. we done do alter that image with the exception that we are using EF Core to create a database and seed it with data initially thereafter we have a working database and tables.

Test your Solution out Locally on your Docker Environment

That is it! we just need to build this solution in Docker and then tell it to stand UP.

First you will issue the command

$ docker-compose build

and then this command

$ docker-compose up

once you have done that then you are basically back at Step #5 on the Easy Path Blog post.

Summary

So, now that we seen both ways of getting to the same goal. this concludes working locally, next post I will go into how to get this solution in a Cloud provider, in my case Microsoft Azure. To go back to the series beginning see here. Thank you


Leave a comment

Your email address will not be published. Required fields are marked *

2 thoughts on “ASP.NET Core Web API with EF Core into a MSSQL Linux Docker– Developer Path