top of page
Writer's pictureThe Tech Platform

How to write URL shortener in .NET5?



In this series we will try to show you how easy it is to write a service that shortens URLs with .NET5. On top of that, we will add an additional functionality — service will have to send an SMS when target URL is shortened and periodically send SMS reports.


Stick with me until the end and you will learn how to:

  • Create youtube like links for short URLs

  • Use embedded NoSQL database

  • Schedule web service, ex. send reports every day, week and/or month

  • Send SMS from our service

Just to give you heads up, this is by no means an extensive tutorial on how to build production grade shortening systems. For production grade systems we need to take in to account scale and load. It would be nice to have some kind of analytics, but we have to start from somewhere, right?


Software engineering nowadays can be compared to playing with LEGO bricks. All the nice bricks are out there, we need to implement them in a smart way. We don’t want to reinvent the wheel every time we start programming, so we’re going to use a couple of packages to make all this magic happen.


First, we’re going to need some SDK-s and tools:

  • For IDE we can use (https://code.visualstudio.com/)

  • We need .NET core SDK (https://dotnet.microsoft.com/download)

  • Postman (https://www.postman.com/downloads/)


Once we have .NET framework in place we will just check if everything is working for us with (type in terminal):

dotnet --version

After the test we can create our template project:

dotnet new webapi -n "Shortener.Service" -lang "C#" -au none

*parameter -au none means there is no default authentication for our webapi

With this command we get template webapi project. Now that we have all things up and running let’s start with step by step guide.


First Step: Create controller methods

Remove default web api controller and create your own. For this simple example we will have one GET and one POST method.


Let’s dig into POST method. User will provide us with URL (simple UrlDataDto object) that needs to be shortened. We will store that URL we will store in LiteDB.

[HttpPost("shorten")]
public IActionResult ShortenUrl([FromBody] UrlDataDto requestUrlDataDto)  
{  
    if (requestUrlDataDto==null)  
    return BadRequest();  
    
    if (!Uri.TryCreate(requestUrlDataDto.Url, UriKind.Absolute, out Uri result))  
    ModelState.AddModelError("URL", "URL shouldn't be empty");  
    
    if (!ModelState.IsValid)  
    return BadRequest(ModelState);  
    
    if (_controllerService.CheckIfUrlExists(requestUrlDataDto))  
    ModelState.AddModelError("Url", "Url is allready shortened");  
    
    if (!ModelState.IsValid)      
    return BadRequest(ModelState);  
    
    var responseUrlDataDto = _controllerService.AddUrlData
    (requestUrlDataDto, 
        this.Request.Scheme, 
        this.Request.Host.ToString());  
    
    return Created("shortUrl", responseUrlDataDto);  
}

GET method needs a parameter shortUrl. If we have that shortUrl in our database, method will redirect us to “long” URL if request was made by browser. Request could also be made by “thin” client like Postman, so we will make sure that we return JSON with “long” URL. (In that case we don’t want to redirect)

[HttpGet("{shortUrl}")]  
public IActionResult GetUrl(string shortUrl)  
{  
    if (String.IsNullOrEmpty(shortUrl))  
    return BadRequest();  
    
    var urlDataDto = _controllerService.GetUrlData(shortUrl);  
    
    if (urlDataDto == null)  
    return NotFound();  
    
    var userAgentBrowser = _controllerService.CheckUserAgent
            (this.Request.Headers["User-Agent"].ToString());  
    
    if (userAgentBrowser)  
    return RedirectPermanent(urlDataDto.Url);  
    return Ok(urlDataDto);  
}


Second Step: Add database

As mentioned, we need DB to store our shortened URLs. For this small service we really don’t want to install DB or do something beforehand. Goal is just to “press play” and our app is ready to go.

dotnet add package LiteDB

This will give us small NoSql database, perfect for our proof of concept.


Now we need to link our application with DB:

public void ConfigureServices(IServiceCollection services)  
{  
    // Add LiteDB  
    services.AddSingleton<ILiteDatabase, LiteDatabase>
    (_ => newLiteDatabase("shortner-service.db"));  
}


Third Step: Add services

As you can see, our controller is simple and whole business logic is in services. Let’s just check what we did in services.


First of all, let’s create service that will write data to our DB.


Add to DB:

public int AddUrl(UrlData urlData)  
{  
    var db = _context.GetCollection<UrlData>(BsonAutoId.Int32);  
    var id = db.Insert(urlData);  
    
    return id.AsInt32;  
}

Get from DB:

public UrlData GetUrl(int id)  
{  
    var db = _context.GetCollection<UrlData>();  
    var entry = db.Query()  	 
        .Where(x => x.Id.Equals(id))  	 
        .ToList().FirstOrDefault();  
    return entry;  
}


We need logic that will shorten our URL. For this we can use cool package Hashids.net and get youtube like short ids. We can chose length and “salt” for our links. Check out hashids.net for short instructions.


For example, if we sent UrlDataDto:

{
  "url": "https://www.infobip.com/docs/api"
}

We get in response nice youtube-like short links:

{
  "url": "http://localhost:8000/V1oExr"
}

Let’s add this feature:

dotnet add package Hashids.net

Method in service for encode:

public string GetShortUrl(int id)  
{  
    return _hashIds.Encode(id);  
}


As you can see, we will encode DB id and generate our short URL from that data. (We will use this service in POST method)


Method in service for decode:

public int GetId(string shortUrl)  
{  
    var decodedId = _hashIds.Decode(shortUrl);  
    return decodedId[0];  
}

Vice versa, on the other endpoint (our GET method) we will decode shortUrl to get id.


Fourth Step: Test with Postman

After dotnet build and dotnet run commands you are all set for manual test! Postman collections for you will find as part of the project, so that you can easily import.


POST:



GET:



Conclusion

In one part of this series, we have created a simple URL shortener. We’ve showed you how to save data without installing database and generate short URLs with Hashids.net.


Application passed our manual test with Postman, and we have set up stage to implement notifications in our web service.



Source: Medium - Dino Lozina


The Tech Platform

0 comments

Comments


bottom of page