URL Shortener API in .NET by Utilising Minimal APIs
Prerequisites
Before we get started we will need to have at least .NET 6 installed, this can be installed on any platform (Windows, Linux, MacOs).
Once installed, feel free to download one of the many IDEs that can help you write .NET code.
Project Setup
To start with we need to create ourself a folder to create our project, I like to keep all my development work under c:\dev\
, however, if you’re not on Windows or want to place it somewhere else feel free.
So let’s create a empty folder, and navigate in to it.
mkdir c:\dev\ShortUrl
cd c:\dev\ShortUrl
Now we want to create the API foundations by using the dotnet new
command, for this project we can use the web
template which will give us a minimal ASP.NET Core API.
dotnet new web
Once run you will notice a few files have appears in the directory.
ls
Directory: C:\dev\ShortUrl
Name
----
appsettings.Development.json
appsettings.json
Program.cs
ShortUrl.csproj
appsettings.*.json
The appsettings.json
file is an application configuration file used to store configuration settings such as database connections strings, and any application scope global variables. By default appsettings.json
is loaded then appsettings.{environment_name}.json
is loaded on top. For more information about .NET Configuration please checkout one of my previous talks, Everything You Need To Know About Configuration In .NET
.
Program.cs
The Program.cs
is the entry point for the application, by default this uses Top-level statements (a new-ish C# 9 feature). This means that you can write code directly in to the file without wrapping it in any classes or methods.
ShortUrl.csproj
The *.csproj
file is the C# project file which contains information on how to build the project. This includes things like the SDK version, properties and also the required dependencies.
Running template
Now we’ve got the API template in place we can run the project.
dotnet run
Once running you’ll get some logging within the console explaining which port the API is listening on.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7077
We can also then test the Hello World
example by running a quick curl command
curl https://localhost:7077
Hello World!
If we take a look at the code inside the program.cs
we’ll see the following code
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
As you can see our app
has one GET
request mapped to the root (/
) which returns a "Hello World"
string.
Building URL Shortener API
Now everything is running and working we can start adding more endpoints to our API to flesh out our URL Shortener API.
Endpoints
The following table describes the endpoints we need to add to our API
Verb | Path | Description |
---|---|---|
POST | /slugs | Creating a short url slug |
GET | /{slug} | Redirect endpoint for slug |
POST /slug Endpoint
To start with we need an endpoint to create our slug urls for our short urls. Let’s create a model to represent our slug resource.
public record SlugResourceRepresentation(
string Slug,
Uri Url
);
Then we’ll need to map a post endpoint for /slugs
, we’ll just create a locally scoped ConcurrentDictionary
for storing our captured slugs in memory.
ConcurrentDictionary<string, SlugResourceRepresentation> slugs = new ();
app.MapPost("/slugs", (SlugResourceRepresentation resourceRepresentation) => {
if (slugs.TryAdd(resourceRepresentation.Slug, resourceRepresentation))
{
return Results.Ok(resourceRepresentation);
}
return Results.Conflict();
});
Now if we run our API again we can hit it with cURL to test out the new endpoint
curl --request POST \
--url https://localhost:7077/slugs \
--header 'content-type: application/json' \
--data '{"slug": "kevsoft","url": "https://kevsoft.net"}'
GET /{slug} Endpoint
Next we’ll map the get endpoint for /{slug}
which will do the redirect if the slug exists in our ConcurrentDictionary
.
app.MapGet("/{slug}", (string slug) => {
if (slugs.TryGetValue(slug, out var resourceRepresentation))
{
return Results.Redirect(resourceRepresentation.Url.AbsoluteUri);
}
return Results.NotFound();
});
Wrapping up
We now have a fully working URL Shortener API, it has some caveats such as once the web server gets suspended then all our slugs are lost as they’re stored in memory, it will not be able to scale, as there’s no backing data store for multiple web servers to be running. However, this gives you an starting point and an idea of what is achievable with speed with Minimal APIs within .NET