Boris Eetgerink

Hey, thanks for reading my blog. Subscribe below for future posts like this one and check my personal site in order to contact me.
March 1, 2024

Bootstrap and separation of concerns

Lately I've been learning Bootstrap and it's great to get a basic layout up and running quickly. However, it has one great drawback: a lack of separation of concerns. Most back-end solutions are either n-tier or use vertical slices. Either way, each tier or slice has one responsibility. A tier can be responsible for data persistence or...
Read more
February 8, 2024

Smart views, lessons learned

An apparently simple HTML component, for example text with an image, already has a quite a few variants: The text or the image might be optional. There might be a view where the image is extra wide compared to the text, or the text takes up the most part of the component. Combine those and you easily get four variants for one component...
Read more
January 28, 2024

Smart views and skipping layers

The past five years I've worked mainly on HTTP APIs, but since late last year I have a new job where I mainly work on Umbraco CMS implementations. A lot is the same, but there are also some big differences. Technically, one of the biggest differences is the outside boundary or interface of an HTTP API versus that of a CMS implementatio...
Read more
September 22, 2023

Storing calculation results is denormalization too

Database normalization reduces the data redundancy in a (relational) database. When properly done, there is only one source of truth. Database denormalization on the other hand duplicates data. Denormalization can be useful for performance, but makes it more difficult to keep data consistent, because there are more sources of truth. Re...
Read more
July 18, 2023

Using an options builder with Action<T>

When I started working on ConsoleExtensions, I made method overloads for every combination of parameter I found reasonable. However, that quickly got out of control. Now I'm ready to work on introducing an options builder so that eventually every feature gets one method that can be configured with an Action<T> delegate. Here's how that...
Read more
June 30, 2023

My first NuGet package

A while back I mentioned that I needed an apparently simple feature from a console application. Back then I used an old package, but I needed more features than it offered. I couldn't contact the owner of that package, so I decided to write it myself. Since a few days, I have it live on NuGet: BorisEetgerink.ConsoleExtensions. I hope y...
Read more
June 22, 2023

From 0 to 100% on a single line

Or how to display a progress indicator in a console app: // Avoid a blinking cursor. Console.CursorVisible = false; Console.WriteLine("Downloading..."); for (int i = 0; i <= 100; i++) { // Overwrite the output on the current line. Console.CursorLeft = 0; Console.Write($"Progress: {i.ToString(),3}%"); await Task.Delay(50); } // Terminat...
Read more
June 19, 2023

Recommended NuGet package: Prompt

Today I needed something apparently simple. I wanted to set a console input (ReadLine) which displays a default value. Unfortunately, .NET has no support for this out-of-the-box. After trying a few libraries I settled on Prompt. It does just what I need and not much more. There's always room for improvement and it's old, but it still w...
Read more
June 12, 2023

Levels of API granularity

When designing an HTTP API you have to decide on its level of granularity. In my experience there are three levels to choose from: The resource, aggregate and facade level. Each level determines how detailed each endpoint is and as a consequence how many endpoints there are. Besides that, each level also determines where most of the in...
Read more
June 5, 2023

An API gateway is a facade

Today I learned that an API gateway can be more than just a reverse proxy. It can also be used as a facade: it hides the numerous requests required to build a screen, whether those endpoints are all part of one monolithic REST API, or are from multiple microservices. The gateway might become a single point of failure, but it also hides...
Read more
April 28, 2023

.NET Configuration sources

My knowledge of application configuration goes way back to .NET full framework's web.config transformations. I write this short post to see how flexible the appsettings.json files are in combination with application secrets. Let's say I have the following options file: public class ExternalServiceOptions { public const string ExternalS...
Read more
March 25, 2023

Using dotnet watch from a Docker container

Run this command from the directory of the web application. I don't recommend it as daily development workflow, as the container adds quite some performance overhead, but it's great if you need to check how something works when running in a container. docker run -it --rm --mount type=bind,src="$(pwd)",target=/app -p 5000:5000 -e "some_...
Read more
March 23, 2023

Setting the environment of a .NET Docker container

A .NET (web) app has a configuration file for each environment (appsettings.EnvironmentName.json). The application determines which environment it runs in through the ASPNETCORE_ENVIRONMENT, the DOTNET_ENVIRONMENT environment variable or through other means. Because of that, one build/publish of an application is able to run in every e...
Read more
March 18, 2023

Getting started with .NET and Docker on Azure

Set up a web app Create a solution and add a Razor web application. I choose Razor for this example, as it easily demonstrates if everything works as expected. mkdir HelloDocker cd HelloDocker dotnet new sln --name HelloDocker dotnet new webapp --name HelloDocker.Web dotnet sln add HelloDocker.Web cd HelloDocker.Web dotnet user-secrets...
Read more
March 9, 2023

C#: Random vs. RandomNumberGenerator

Recently I was looking into shuffling a deck of cards and how to implement that in C#. It turns out that shuffling itself is not that hard, but verifying that a deck is shuffled correctly is a lot harder! I won't go into that here. Anyway, shuffling needs a random number generator. I'm familiar with System.Random, but it turns out that...
Read more
February 22, 2023

RESTful SPA = Hypermedia Driven Application

When I coined the term RESTful SPA and started doing more research on how to implement it I came across the book Hypermedia Systems, written by the creators of htmx. In it, they describe the RESTful SPA, but name it a Hypermedia Driven Application (HDA). I now think that's how the RESTful SPA should be named. There are two reasons why ...
Read more
February 20, 2023

htmx: a RESTful SPA companion

In my article about a RESTful SPA I listed a few requirements: 1. It should work with rendered HTML instead of JSON. 2. It should intercept links and form submissions. 3. It should update sections of the page based on the response from the server. 4. It should update the browser URL and navigation history. 5. It should update the brows...
Read more
February 16, 2023

How to loosely couple an API

If an API is tightly coupled to its clients (an app and/or SPA for example) or its database, releases often have to be orchestrated carefully in order not to break the application as a whole. Fortunately, there are a few methods to loosen that coupling so all components can be updated independently and more frequently, eliminating the ...
Read more
December 20, 2022

Simplify to become a more productive developer

It's easy to complicate things, but it's a lot harder to keep it simple... • Do you really need Angular or React or is a RESTful SPA good enough? Do you really need a SPA at all? • Do you really need MVC or is MVVM good enough? • Do you really need real time updates or is an update on a page refresh good enough? Then drop the web socke...
Read more
December 9, 2022

A RESTful SPA

I'm going out on a limb here, but I'm going to say it anyway: most Single Page Applications aren't RESTful. They have API contracts and know of the URL templates the server uses. When deep linking they don't need to explore the resources of the server, but can jump right in. That's convenient, but that kind of tight coupling means the ...
Read more
November 30, 2022

The power of media types

For my research into REST I wanted to dive a little deeper into media types, but others have already done so years ago. It's great to read old blog posts and see they're still relevant today. So credit where credit is due, these are must-read posts about media types: • RESTful resources are not typed (original/archive) • The role of me...
Read more
November 18, 2022

REST in 14 bullet points

Roy Fielding's dissertation on REST is very abstract. With these bullet points, I hope to make REST a bit more accessible and invite you to explore further. • REST is protocol independent, but is most often used over the HTTP protocol. • REST is not tied to a specific media type (JSON for example), but it does require a media type with...
Read more
November 18, 2022

REST and Hypermedia as the engine of application state

My previous post REST for object oriented software developers only scratched the surface of REST. It was meant as an introduction on how to think about the states and state transitions of resources. This post is more of a deep dive into REST and HATEOAS. But before we get there, we have to start with media types (formerly known as MIME...
Read more
November 4, 2022

REST for object oriented software developers

When designing an HTTP API, it is tempting to look at the common HTTP methods GET, PUT, POST and DELETE as CRUD operations with JSON objects that closely match database tables. In this post I'll show why that approach breaks encapsulation and how applying object oriented design practices improves the API and makes applying REST easier....
Read more
October 2, 2022

.NET 7 generic math and rounding integer divisions

.NET has the well known feature/bug that dividing two integers returns a rounded integer instead of a double. I'm interested in how that rounding is handled in .NET 7's new generic math. Traditional implementation Dividing two integers returns a rounded integer. Rounding is done towards zero, effectively chopping off the decimal places...
Read more
September 26, 2022

I love the composition of the C# Open XML SDK

Recently I had to generate an export with some basic data. Unfortunately, CSV was not an option, a proper Excel file was required. There are quite a few options for generating Excel files, but most are wrappers around the Open XML SDK, and I don't really like that. You invest in a specific library and eventually it just misses that one...
Read more