ASP.NET combined with the .NET CLI is a powerful combination. In a matter of seconds the CLI can generate a templated API application. Add on top of that a new controller class and you’ve started to develop your new API. This seems simple enough, right? If you’ve been in the ASP.NET biz for a while, the answer is undoubtedly yes. As many updates over the years has greatly simplified the process of creating APIs with ASP.NET. Although, what if you have come from a Python background or a Node.js background? How would you make sense of Program.cs and Startup.cs? And, what about controllers and dependency injection and configuration and…
Sometimes, you just need a simple place to start, and with .NET 6, Minimal APIs is that simple place.

The Solution
In this tutorial, we’ll create an ASP.NET minimal API and we’ll even package the API in a docker container so that you can test this solution out on EC2 or ECS or EKS or even a home grown k8s cluster.
Prerequisites
To complete this solution, you will need the .NET CLI which is included in the .NET 6 SDK. In addition, you will need to install Docker.
Warning: some AWS services may have fees associated with them.
The Minimal API
Let’s start out by creating a directory to house the API application.
$ mkdir minimalapi
Now, let’s “cd” into that directory and create a couple files.
$ cd minimalapi
The first file we create will be the project file named MinimalApi.csproj. Once the file is created, let’s open the file and add the following contents.
<Project Sdk="Microsoft.NET.Sdk.Web"> | |
<PropertyGroup> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
</PropertyGroup> | |
</Project> |
Let’s talk about this file. First up, we are specifying .NET 6 as our framework — pretty straightforward stuff. The next line, enables implicit usings. This feature will greatly reduce the lines of boiler plate code that you need to have in your app as ASP.NET bundles commonly used namespaces into an auto-generated file that make the commonly used namespaces globally available. More on how this works later.
Let’s create the second file, Program.cs. in that file let’s add the following two lines. The first line creates a WebApplicationBuilder which allows us to instantiate a WebApplication on line two.
The next line creates an API endpoint with a path of “/greeting” that allows the HTTP verb, GET. When a client makes a get request to this endpoint, the endpoint will reply with a response of, “aws w/ .NET”
This last line simply runs the web application and listens to port 80.
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); | |
WebApplication app = builder.Build(); | |
app.MapGet("/greeting", () => "aws w/ .NET"); | |
app.Run("http://*:80"); |
That’s it. That’s all it takes to build an API in ASP.NET.
Let’s now build the app, making sure everything works.
$ dotnet build
Awesome! Everything works. Now, let’s take a quick look at the MinimalApi.GlobalUsings.g.cs file in the obj/Debug/net6.0 directory. MinimalApi.GlobalUsings.g.cs is generated by the .NET CLI at build time. This generated file contains the list of namespaces that are available globally.
// <auto-generated/> | |
global using global::Microsoft.AspNetCore.Builder; | |
global using global::Microsoft.AspNetCore.Hosting; | |
global using global::Microsoft.AspNetCore.Http; | |
global using global::Microsoft.AspNetCore.Routing; | |
global using global::Microsoft.Extensions.Configuration; | |
global using global::Microsoft.Extensions.DependencyInjection; | |
global using global::Microsoft.Extensions.Hosting; | |
global using global::Microsoft.Extensions.Logging; | |
global using global::System; | |
global using global::System.Collections.Generic; | |
global using global::System.IO; | |
global using global::System.Linq; | |
global using global::System.Net.Http; | |
global using global::System.Net.Http.Json; | |
global using global::System.Threading; | |
global using global::System.Threading.Tasks; |
Ok, back to the code. Let’s create the following Dockerfile. Essentially, this Dockerfile will instruct docker to download the appropriate SDK, publish the .NET app, copy the contents of the app to the image and then sets the entrypoint to the minimalAPI.dll.
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS sdk | |
WORKDIR /app | |
COPY ./ ./ | |
RUN dotnet publish -c Release -o out | |
FROM mcr.microsoft.com/dotnet/aspnet:6.0 | |
WORKDIR /app | |
COPY –from=sdk /app/out . | |
ENTRYPOINT ["dotnet", "MinimalApi.dll"] |
With the docker file in place, let’s create the docker image with the following command.
$ docker build -t minimalapi:1.0 .
At this point you should see the layers being constructed and then finally the image will be built.
Great! We now have a docker image for the minimal API. Let’s now run a container using the minimalapi1.0 image that we just built. We can do that, like so:
$ docker run minimalapi:1.0 -it ––name minimalapiapp ––p 5000:80
Once the container starts to run, you should see the output of the app in the terminal as we used the, “-it” flag. This is a signal we are ok to test the API. One other thing to note is that we mapped our local port 0f 5000 to the container’s internal port of 80.
Testing the ASP.NET 6 Minimal API
Let’s go over to your favorite browser and hit the greeting endpoint that we configured in Program.cs. Using the mapping that we set up above, the greeting endpoint will be hosted at, http://localhost:5000/greeting.
You should see the following response from the greeting endpoint.
aws w/ .NET
And, with that, this tutorial is complete.
Challenges
Now that you have a working solution, let’s take things a little further…
- Create a PUT endpoint.
- Create a POST endpoint.
- Upload the image to docker hub.
- Run the minimal API container on EC2, ECS, EKS or a k8s cluster.
That’s it! In this tutorial you learned how to create a minimal API in .NET 6, create an image of a .NET application and then run a .NET application in a container.
Want to know more about the tech in this article? Checkout these resources: