Part 1 — C# Rest API: A simple service build to run in Docker (Linux) with EF and Nancy FX
Part 1: Dockerized REST API in C# .NET (this part)
How did I come about to try this out? TLDR: This implementation came out of a conversation about modernizing a .NET shop to make use of modern micro-service paradigms. ;)
Recently I moved the NYC from Seattle and although I love both cities it’s definitely been a different experience meeting people. While talking to Bryce (Another person I’ve had the privilege to work with in Seattle) about the ups and downs for building a network in NYC, he introduced me to Jonathan who’s working in midtown for a financial company (wait… NYC has finance? ;), who knew!). We started chatting about life and pretty soon were geeking about various tech stacks and whatever might be hip these days. At a certain point we got on the topic of .NET shops. Which honestly aren’t exactly known to be cutting edge. But these days Microsoft has been tweeting in my ears again on cool stuff they’ve been promoting. They are pretty far behind in the open source community and related practices. However their efforts are definitely in the right direction. For example I was surprised to see that for the most part everything in these posts works the same in Windows, Linux, and macOS. After a wonderful chat about people stuck in their ways and how you could bring modern style development and ops to people that are used to a stack that doesn’t really promote that, I wondered if it would be possible to get a quick micro style service running on docker in AWS/Azure/GCP on linux written in C#. (It definitely morphed into more hence the followup posts) The following is that story!
What are we Building?
For this example we’re going to build an internal application registry. The idea is that we’ll have a simple C# REST service where we can store and retrieve information about the organizations available web apps. Things like it’s name, description, url, etc. Then we’ll have a gRPC service that has information about the state of the service (things like online, offline, etc). On top of that we’ll have a graphql service that links the two pieces, and finally a react.js client that consumes that graphql service.
Getting Started — What’s the tech involved (check out the code here)
- C# (mono or dotnet)
- Grab you favorite IDE (I’m using Rider)
- Rancher (out of scope, and out of scope but part of our CI/CD story)
- Drone (out of scope but part of our CI/CD story)
- AWS/Azure (out of scope ;))
Mono vs. dotnet - checkout the answer on stackoverflow
What frameworks are we going to use
- .NET core 2.0
- Nancy fx
- Entity Framework
Create a .NET core project — first commit in the project should Give you an idea of what that looks like :)
Now let’s start by getting Nancy Fx going. Here you should use Nuget
> dotnet add package Nancy -v 2.0.0-clienteastwood > dotnet add package Nancy.Authentication.Stateless -v 2.0.0-clienteastwood > dotnet add package Nancy.Hosting.Self -v 2.0.0-clienteastwood
— Checkpoint 1 (Basic service running)
Modify your Program.cs file to look like the one at this checkpoint. One thing to point out is that I’m doing a “Thread.Sleep(Timeout.Infinite);” at line 28. This may seem weird at first since most of the examples have a waiting for key press to kill the service. However this is going to make it so that we can start the service in a Docker container later.
Note: If you’re on windows and don’t have admin rights by default. First poor you… I do feel your pain! Second you’ll need to run something like the following with Administrator privilege:
> netsh http add urlacl url=http://+:8888/ user=Everyone
— Checkpoint 2 (Creating your endpoint)
Now looking at this checkpoint we’ll find two new files. models/Applications.cs which is just a POCO (Plain old C# object) and modules/Applications.cs which will contain our routes for Nancy FX. Running this locally we essentially have http://baseurl:8888/v1/applications as our first route!
— Checkpoint 3 (Adding data source via code first in Entity Framework)
Now from this checkpoint you see the following needs to happen.
1. More Nuget
> dotnet add package Microsoft.EntityFrameworkCore -v 2.0.0 > dotnet add package Microsoft.EntityFrameworkCore.SqlServer -v 2.0.0 > dotnet add package Microsoft.EntityFrameworkCore.Tools -v 2.0.0
2. contexts/AppDbContext contains the connection information as well as what DbSets (models bound to the database) are available. You may notice that I’m using environment variables to load the host, user and password. I’m doing that so I can later configure it inside a container.
3. models/Application.cs now has annotations for the tables name and the data types
4. modules/Applications.cs now has the database context injected, has well as the full CRUD endpoints.
5. This is a weird piece but do use the code to table generation you’ll need to add the DotNetCliToolReference like the following code chunk. This will let you run “dotnet ef” commands :)
6. At this point you should now be able to create your database using:
> dotnet ef migrations add initial (this will create a Migrations folder) > dotnet ef database update
— Checkpoint 4 (Lets add some performance metrics)
Now looking at this checkpoint you’ll see helpers/MiddlewareWrapper.cs has an intercept and we’re using it in modules/Applications.cs to get timing information on our requests.
— Checkpoint 5 (Let’s build and Docker this thing up)
Looking at this checkpoint you’ll see that running the following commands will build you’re service
dotnet publish -c Release -r linux-x64 -o out docker build -t sample-dotnet-rest . docker run sample-dotnet-rest (you'll need the host, username and password as environment variables)
Congrats you now have a simple C# cross platform REST service using Entity Framework with code first running in docker!
With the LIFFFT/Pelo.tech @pelotechnology crew, we’re on the next versions of dev concepts which allow for complete self-hosted apps, deployments which are based on high-availability, high-scalability, and simple blue/green style deployments. Hit me up if you’re interested in more info about it!
Joachim Hill-Grannec @lindyblues is a Partner at http://www.pelo.tech, a group that helps organizations improve their dev practices and culture. These days you’ll also find him traveling around the world dancing at West Coast Swing events.