Write a URL Shortener in 26 Lines of Code with .NET Minimal APIs
Tags: dotnet, csharp, webdev, programming
Published: 2022-01-13 13:16:45

I was looking forward to .NET minimal API framework for a very long time and now, it is finally out! Let’s dive into new version of .NET6 and answer the following questions:

1. What is .NET minimal API?
2. How to refactor existing URL shortener?
3. How to add dependency to service?
4. How to add endpoint to service?
5. Where are using statements?

### 🤔 1. Introducing .NET Minimal APIs

_”Do you need all of this stuff just to shorten URL?”_

This was a first reaction of a friend (who happens to be a Python programmer) when I showed him my [first shortner example](https://github.com/dlozina/url-shortener-service-v2). "Yes" would have been a pretty accurate answer, but not the one that I’d be happy with.

There was a lot of boilerplate code compared to other frameworks.
One benefit is that the structure is already set up — very convenient when we have larger projects to tackle. On the other hand, not ideal when I need to create a small service as part of a microservices architecture. 
Most SaaS providers are using microservice architecture for its scalability,smaller/faster deployments, and ease of understanding.

Take a look at the Flask API template:
{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=minimalApiPython.py %}

In just 5 lines of code, we have our first endpoint! Single file, no other setup needed. All we need to focus on is the feature of this new service.

Now, let’s take a look at the .NET template. Out of the box we get _Startup.cs_, _Program.cs_, _Controllers_…a lot of boilerplate code. This could be unnecessary if the goal is to write one small service as part of a SaaS product or just a prototype.  


Fortunately, .NET6 addresses this issue. Let's rewrite the previous example in **.NET6 with a new template**.

{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=minimalApiCsharp.cs %}

4 lines of code for our first endpoint and a single file. This is new .NET minimal API!

Back to my friend’s question - *“Do you need all of this stuff just to shorten URL?”*

No.
I can do better.

### ✂️ 2. Refactored URL shortener example

A while back, I wrote a post on [how to create a URL shortener in .NET5](https://dev.to/infobipdev/how-to-write-url-shortener-in-net5-weve-made-it-seem-easy-1-5c56)), but I never imagined that I'd be able to rewrite it in 26 lines of code and a single file.


**Note: we actually have two files—we will get to the bottom of that in the fifth section, bear with me.* 

Refactored code:
{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=Program.cs%}

You can find the previous URL shortener example in this [github repository](https://github.com/dlozina/url-shortener-service-v2). There is nothing minimal about the codebase.  
If we compare the old code to our minimal shortener, we will see the hidden complexity of the minimal API framework right away.

We start from scratch in the minimal API template and only introduce the dependencies we need. We can concentrate on the important stuff—the code for the requested feature.   

Let's analyse the code and see what new things come with .NET6 that you could start implementing in your services.

### ⚙️ 3. Adding Dependencies

My service needs database, so I'm adding a dependency to LiteDB.

```
dotnet add package LiteDB
```

Usually, we would go to Startup.cs and set up our dependency. Since we don’t have one, the way to go is shown below on line 2. Same code, different position.

{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=dependency.cs%}

### 🔗 4. Adding an Endpoint
All the methods we need are in the app—or should I say framework?

* **MapGet(pattern, handler)**
* **MapPost(pattern, handler)**
* **MapPut(pattern, handler)**
* **MapDelete(pattern, handler)**

Check how to implement `POST` method and `GET` method in the example below.

{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=Post.cs%}

The first parameter is route pattern, the second parameter is handler. The handler is delegate executed when endpoint is matched.

{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=record.cs %}

The `Url` object is `record`, also something new in .NET6. It could be a class as well, but I just wanted to shred couple of lines of code to get those 26 magic lines.

Data that our `POST` method (body of req) needs to contain is
defined by the `record`. (It is enough to send `longURL`, `id` will be set automatically by our `db`)

We have our database in the list of services that our app uses. The next step is to inject it into the endpoint. The delegate needs to have our database context to add data from the client to the database.

In the end, set up your service address and port.
And you are done!

```
app.Run("http://localhost:4000");
```

### 🙋 5. Where are using statements?

Global using statements is another feature I am happy with. Do you remember something like this on top of every file in your project?

```
using System;
using System.Reflection;
using System.Linq;
using System.Net.Http;
using System.Linq;
```
Implicit usings are hidden in auto generated file inside your _obj_ folder. That file declares global `using` statements behind the scenes. If you go to project folder then go _obj/Debug/net6.0_, you will find a file titled _“{ProjectName}.GlobalUsings.g.cs”_. 

Open this file, and see the content:
{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=minimalShortener.GlobalUsings.g.cs%}

Since this is an autogenerated file, we can’t edit it here. 
In our minimal shortener we have two packages (LiteDB, Hashids.net) that we depend upon, and we will actually need to place `using` statements in our _Program.cs_ to use code from packages.

Instead, let's manually create a file that will hold our global `using` statements. This way, we keep our _Program.cs_ free from all using statements.

{% gist https://gist.github.com/dlozina/166bf07736cd349941f2b78383d8609b file=GlobalUsings.cs %}

It might be overkill in this particular example, but imagine adding more dependencies. It is a good option for keeping code clean.

### 🎊 So, is it possible? Of course! 🎊

Most of the time, we don’t need all the ceremony that we got with previous .NET webapi templates. 

Now we have the option to start from scratch and add only stuff that we really need. Missing MVC Controllers? No problem.Add them later. Need Authentication? Same thing.

The template code has fewer files and a more intuitive setup for newcomers in the .NET world—this is probably one of the best benefits of this framework. I am really looking forward to seeing what future updates bring along.  

If you enjoyed following along and building your own URL shortener in .NET6, keep an eye out for this blog!
In the next article, we will place this minimal URL Shortener in Docker and explore another essential piece of the tech stack.