ProudMonkey

.NET Core On Mac - Building An ASP.NET Core App With Web API, EF, PostgreSQL And Running It On Docker

Introduction

Unlike Windows app development, building apps in Mac environment is bit different because we will be dealing with the new commands, tools, and the file structure. To put it in other words, I’m not that familiar with the MAC environment and it’s a real P.I.T.A. This article aims to guide developers like me who aren’t familiar with MAC OSX and want to jump on .NET Core, or for folks who want to try out .NET Core on MAC environment.

While there are a bunch of resources on the web that demonstrate how to build and run .NET Core apps in docker, it seems to me that there are only limited resources on doing it on MAC. This article will walk you through on building your first ASP.NET Core app with Web API, EF, PostgreSQL and running it on Docker.

Getting Started

Before we get our hands dirty, let’s go ahead and install the required tools needed for us to build and run the application. If you already have installed the prerequisites mentioned below, then you may skip it and proceed.

Prerequisites

NET Core

.NET Core gives us the dotnet command line tools for us to build and run .net core apps without any IDE. Download and follow the installation steps for .NET Core in MAC here.

Visual Studio Code

Visual Studio Code is a lightweight, yet powerful code editor which runs on MAC, Linux and Windows. We’ll be using VSCode to write our C# code and HTML markup. Download and install Visual Studio Code here.

NodeJS and NPM

We’ll be needing NodeJS because we are going to use Yeoman to scaffold ASP.NET Core Web App template and we will be using NPM to install packages. Install NodeJs and NPM, you can get the latest installer here.

Creating the .NET Core Application

Open the terminal and let’s start by installing Yeoman and Bower. Run the following command:

$ sudo npm install -g yo bower 

Once you’ve done that, run the following command to install the ASP.NET Core template generator:

$ sudo npm install -g generator-aspnet

The -g flag installs the generator globally, so that it can be used from any path.

Now, we are ready to create our ASP.NET Core application. First, we need to create a directory for our project. To do that, run following command:

$ mkdir src/dotnetcoreapp
$ cd src/dotnetcoreapp 

The command above creates the folder scr/dotnetcoreapp within my user account. Now let’s run the ASP.NET generator for yo:

$ yo aspnet

Now, you might be asked to report usage statistics to improve the tool, just key in Y/N to answer that. In my case, I’ve chosen Y (yes). After that, it should provide you with the following result:
The generator displays a list of items for us to select the project type. For this demo, we are going to select the Empty Web Application project template. Tap enter and then type-in the project name. For this case, we are going to name the project as "dotnetcorehello". Tap enter to generate the project with the default files as shown in the figure below:

As we can see, the generator creates an ASP.NET Core project. This newly created project can be loaded into Visual Studio Code or use the command line to run the application.

Restore, Build and Run the Application

To ensure that we are on the right track, we will test the app by running the project. Now change the directory of the command line to point to our newly created project. In this case, do:

$ cd dotnetcorehello

then run the following command:

$ dotnet restore

The resulting command should result to something like this:
Then we can build the application using the following command:

$ dotnet build

and then run it using the following command:

$ dotnet run

Now open your browser and then try to browse the the following URL: http://localhost:5000. When everything is good, then you should be able to see the following output:

Cool! We just had our first .NET Core application running on MAC. It’s time for us to move further and create a simple Web API that exposes some methods and explore Docker on MAC.

Installing and Running the Application on Docker

Go ahead and install Docker for MAC here.

Now, let’s try to run our .NET Core application within docker. The first thing to do is open Visual Studio Code and then install the C# Extension.

After that, open the project that we have just created earlier. You will notice that the project already contains the "Dockerfile" just like in the figure below:

The Dockerfile contains the instruction to build the docker image. For more information, see: Dockerfile Reference

Open startup.cs and under Configure() method, let’s modify the output to something like this:

app.Run(async (context) =>  
{  
        await context.Response.WriteAsync("Hello .NET Core from Docker!");  
});

To ensure that our changes will be reflected, then do a build again by running the following command:

$ dotnet build

Now let’s take a look at how to build and run the docker image. Open the terminal and then make sure that the directory is pointing to the root where your project.json is located. Once you’re set, run the following command below:

$ docker build -t dockerdotnetcore .

If the build is successful, you should be presented with something like this:

Cool, let’s verify if the image was created successfully within our Docker machine by running the following command:

$ docker images 

As you can see, our newly created image named "dockerdotnetcore" was listed. Awesome, now we are ready to run the application. Type the following command.

$ docker run -d -p 5000:5000 dockerdotnetcore

Running the command above will result in something like this.

To see all the running images, run the following command.

$ docker ps

Let’s run off to the browser and append port 5000 to our local IP. The output should result to something like this.

Awesome! we now have a .NET Core running on Docker. Our next step is to integrate EF Core, PostgreSQL and create a basic Web API methods that will serve some data.

Integrating EF Core and PostgreSQL

Entity Framework Core now supports a variety of database providers. In this particular demo, we will take a look at how to integrate PostgreSQL in our .NET Core application.The easiest way to install Postgres is using Homebrew which should be included upon installing the .NET Core SDK. Now run the following command to download and install PostreSQL:

$ brew install postgresql

If the installation went well, then the database manager should be installed. Now, let's launch the PostgreSQL service container by running the following command:

$ docker run -d --name pg-db -e POSTGRES_PASSWORD=supersecret postgres

The -d option runs a container in the background and prints the container ID. The --name assigns a name to the container, in this case we named our container as "pg-db". The -e allow us to set the environment variables, which in this case, we’ve set a password to "supersecret" for our Postgres image using the POSTGRES_PASSWORD variable.

Running the command above will expose the postgres port 5432 which allow a standard container to be available to the linked containers. The initdb will also be generated with default user and database.

Again, to verify that our PostgresSQL Docker container is up and running do:

$ docker ps

To test the connection, you can do:

$ docker run -it --rm --link pg-db:postgres postgres psql -h postgres -U postgres

Integrating Entity Framework Core and MVC

It’s time for us to integrate EF and its dependencies so we can run migrations against the database. Migration enables us to create our models in our code (Code-First approach), and create the database base from our model. Open project.json and then add the following references within the dependencies node:

"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.0",  
"Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",  
"Microsoft.AspNetCore.Mvc": "1.0.1",  
"Microsoft.AspNetCore.Routing": "1.0.1"

then add the following reference under the tools node:

"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"

Make sure to save the file, or simply type the command dotnet restore from the terminal to restore the packages and tools that we’ve added.

Creating the Entity Model

Create the following class within your application:

namespace dotnetcorehello  
{  
    public class Band{  
        public int Id { get; set; }  
        public string Name { get; set; }  
        public string Genre { get; set; }  
    }  
}

and then create another class for our DbContext:

using Microsoft.EntityFrameworkCore;  

namespace dotnetcorehello  
{  
    public class BandDbContext : DbContext    
    {  
        public BandDbContext(DbContextOptions<BandDbContext> options)  
            : base(options)  
        { }  

        public DbSet<Band> Bands { get; set; }  
    }  
} 

The Band class serves as our model that houses some properties. This model is just a simple POCO object. The BandDbContext typically used to customize the model and to expose DbSet<T>’s which are used to query the database.

Configuring the ConnectionString

Now that we have our model and DB context ready, the next thing that we are going to do is to setup the connection string for us to be able to run a migration against our database. Add the following configuration within your appsettings.json file:

"DbContextSettings" :{  
    "ConnectionString": "User ID=postgres;Password=supersecret;Server=postgres;Port=5432;Database=POSTGRES_USER;Integrated Security=true;Pooling=true;"  
}

Configuring Services

We need to inject our BandDbContext and enable MVC service. Open Startup.cs file and append the following code below within the ConfigureServices() method:

public void ConfigureServices(IServiceCollection services)  
{  
             services.AddMvc():  

             var connectionString = Configuration["DbContextSettings:ConnectionString"];  
             services.AddDbContext<BandDbContext>(opts => opts.UseNpgsql(connectionString));  
}

Finally, we need to update the Configure() method so it would look like this:

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

            app.UseMvc();  

            // Create database on startup  
            using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())  
            {  
                serviceScope.ServiceProvider.GetService<ArticleDbContext>().Database.Migrate();  
            }  
}

EF Core does not do the migration automatically, that’s why we need the pieces of configuration above for us to use Code-First migrations. The Database.Migrate() method piece is responsible for two things: (1) The creation of database in PostgreSQL if it does not exist yet. (2) Migrating the database schemas to the latest version.

Generate Migrations

As you may have already guessed, we will be using EF Core tools to scaffold our migration and of course updating the database. We’ll be using the command line (dotnet CLI) to run our migrations.

Though the migration process will build your app first, we can also build the app ahead just to ensure that our application doesn’t have errors by running the following command:

$ dotnet build 

When successful, run the following command to generate migrations:

$ dotnet ef migrations add InitialMigration

The ef migration add is the command to add migrations. When the migration is successful, you should be able to see a new folder named "Migrations" that contains the migration files.

The files generated above will be used to create the database on initial run.

Creating the Web API

Okay, it’s time for us to create a simple Web API methods to work with simple GET and POST requests. Add a new class and copy the following code:

using System.Collections.Generic;  
using Microsoft.AspNetCore.Mvc;  
using System.Linq;  

namespace dotnetcorehello.Controllers  
{  
    [Route("api/[controller]")]  
    public class BandController : Controller  
    {  
        private readonly BandDbContext _context;  
        public BandController(BandDbContext context)  
        {  
            _context = context;  
        }  

        // GET: api/band  
        public IEnumerable<Band> Get()  
        {  
            return _context.Bands.ToList();  
        }  

        // GET api/band/5  
        [HttpGet("{id}")]  
        public Band Get(int id)  
        {  
            return _context.Bands.FirstOrDefault(x => x.Id == id);  
        }  

        // POST api/band  
        [HttpPost]  
        public IActionResult Post([FromBody]Band value)  
        {  
            _context.Bands.Add(value);  
            _context.SaveChanges();  
            return StatusCode(201, value);  
        }  
    }  
}

Nothing really fancy there, the code above just contains a few basic methods that communicates to our PostgreSQL database. Notice that we’ve injected an instance of our BandDbContext in the Controller’s constructor, so we can interact with our database, and use the it for querying the database.

Running the Application on Docker

At this point, we are ready to deploy the application on Docker. First let’s build the app by running the following command:

$ docker build -t dockerdotnetcore .

The command above will generate a new instance of image within our docker machine. You can check the list of image by running docker images in the command line.

Now, run the following command to ensure that our PostgreSQL database image is up and running:

$ docker ps 

Now, let’s run our .NET Core application and link the database that we’ve created using the following command:

$ docker run -d -p 5000:5000 --link pg-db:postgres dockerdotnetcore

Testing the Application

Here are some of the screenshots for the test that I’ve made, using Postman.

POST: http:<Your IP>:5000/api/band

GET: http:<Your IP>:5000/api/band

GET: http:<Your IP>:5000/api/band/<id>

That's it! I hope you will find this article useful.

Summary

In this article, we’ve learned the basics on setting up .NET Core on MAC environment and learned how to create a simple ASP.NET Core application with Web API, EF, PostgreSQL and running it on Docker.

References

https://docs.docker.com/docker-for-mac/
https://docs.docker.com/docker-for-mac/docker-toolbox/
https://getcarina.com/docs/tutorials/run-docker-image/
https://hub.docker.com/r/proudmonkey30/netcoredemo/
https://medium.com/trafi-tech-beat/running-net-core-on-docker-c438889eb5a#.8a9aini0b
https://hahoangv.wordpress.com/2016/08/05/docker-for-net-developers-net-core-ef-core-and-postresql-in-docker/
http://blog.thoward37.me/articles/where-are-docker-images-stored/
https://docs.docker.com/engine/examples/postgresql_service/
http://andrewlock.net/adding-ef-core-to-a-project-on-os-x/
Docker Commands: https://docs.docker.com/engine/reference/commandline/run/