Creating a realworld app with C# dotnet
Tags: csharp, dotnet, realwordapp, api
Published: 2022-07-23 14:28:44

Once in a while I create a [realworld app](https://realworld.io) ([demo](https://demo.realworld.io/)) to learn a new framework or explore certain different ways of application architecture.

After experimenting with several frameworks to implement the frontend, this time I decided to create the backend. I used C# .Net for this.

My code can be found [here](https://github.com/Erikvdv/realworlddotnet)

Recent years I have been using this stack extensively and this time, next to experimenting a bit, I aimed to create a clean reference that I would be able to refer to when creating future solutions.

The key things I like about implementing a real world app are reading about best practices and implement them in an elegant way and experimenting with some concepts/libraries that might help with that.

## The solution
For the solution I opted for a fairly traditional clean architecture setup using .Net 6. 
The solution consists of the following layers:
- api (wires up the solution and defines the api endpoints)
- core (contains the core business logic)
- data (contains the interaction with the DB)
- infrastructure (generic code that potentially could be used in different solutions)

And I used the following features:
- the new WebApplication.CreateBuilder(args)
- file scoped namespaces
- global usings
- Entity Framework Core with SQLite db
- serilog for logging, integrated with application insights, including realtime monitoring
- Hellang.Middleware.ProblemDetails for consistent error output
- sonarlint for code scanning

## Justification of choices and Retrospective 
Within the remainder of this post I will reflect on the choices I made. 

### Application layering
- using distinct projects for this specific implementation is not required within this application. However, it makes it more clear where specific responsibilities should be. 

- Api Layer: I have considered using the .Net 6 minimal api's. However, I do think at this moment it is a bit too early as they are still lacking features (e.g. api grouping, model validation). I could have used something like Carter, but it relies on FluentValidation, which I always find hard to debug. I prefer something like [this](https://github.com/Erikvdv/realworlddotnet/blob/9cf6781714e8d06e5e0a10769e4af2ed9612a91f/src/Core/Dto/ArticleDto.cs#L7) that is easy to debug and understand.

- I have doubted if I should combine the Core and Data layer into a single layer. As I am using Entity Framework in the data layer, the core layer (or at least the developer) actually needs to be aware of the EF concepts. The benefit of the current split is that it is easier to validate the database interaction (as can be seen [here](https://github.com/Erikvdv/realworlddotnet/blob/main/tst/E2e.Tests/DataTests.cs)) and that the services in the core layer are easier to unit test as the repository can easily be mocked)

### Features
- I do like the the WebApplication.CreateBuilder(args) that is new in .Net 6. It is easier to just have a program.cs file where both the host, the services and request pipeline is configured, instead of having a separate Startup file as well. For bigger projects I do expect one would like to structure the program.cs file a bit more as it could become hard to navigate

- file scoped namespaces: even being small, in my view this is a huge improvement that came with .Net 6 in terms of readability. Personally I would even like to have the option to go "namespaceless" by just taking the folder structure and a rootnamespace defined in the csproj file as the namespace. 

- global usings: Don't see a lot of benefits here, while developing I manually needed to move stuff that is normally just handled by my IDE.

- serilog: I do like serilog for logging, however the integration with Application Insights is limited to log events as events or as traces, which prevents requests to be logged as requests in AI.

- Hellang.Middleware.ProblemDetails really works well for me. It makes it very easy to add a global exception handler that allows for consistent responses for all types of problems, whether they are technical or functional and works well with the .Net default ApiController problem details response for model validation. 

- sonarlint for code scanning: I do think this is beneficial mainly to keep a consistent code style in your project (together with the other config in .editorconfig)

## Conclusion
I can recommend anyone to build a realworld app. It really encourages you to dive deeper in a language/framework than what you would to in your typical todo app tutorial.
If you are more familiar with a language/framework it allows you to experiment with architectures you are less familiar with.
Besides that, when you like solving puzzles like me, your time is definitely more valuable spend than on solving Sudoku's ;).

Looking specifically at this C# .Net implementation it might help you to think about how to practically structure your application