Structuring a .NET Core 9 Blazor + API Architecture for Microservices Readiness and Best Practices

Laurent Guigon 311 Reputation points
2025-09-04T10:26:11.2466667+00:00

Hello,

I am working on a wiki-style encyclopedic resource application designed to centralize and organize documentation related to the universe of my fantasy novel. This project is personal and primarily has a pedagogical purpose (training myself on modern architectures and anticipating a future move to microservices). At the same time, I want to obtain a robust and scalable foundation to avoid having to rewrite everything at each new iteration.

Some key points about my context:

  • Limited budget: my goal is to keep costs around €10/month on Azure, which excludes for now the use of multiple databases or complex container orchestration.
  • Minimal Azure infrastructure: a single App Service and a single database to host the entire solution.
  • Small team: I am the sole developer (“one-man team” approach), although I occasionally benefit from feedback or virtual assistants.
  • Time constraint: this is a long-term project, carried out in irregular phases depending on my availability.
  • Current usage: the application is almost exclusively used by myself, with possibly two or three secondary users. However, I want to anticipate scalability for broader use in the medium term.
  • History: this is the eighth version of my project, started several years ago. Each version allowed me to experiment with the evolution of .NET (the first iteration going back to .NET 3.5).
  • Main objective: to have a modular and scalable architecture, avoiding complete rewrites at every technological change.
  • Architectural vision: remain for now on an organized monolith, but ensure that the structure is “microservices ready” for a future evolution.
  • Design principles: follow DRY and SOLID best practices to obtain a healthy and maintainable foundation.

Chosen Software Architecture

The implemented architecture is based on a modular monolith. It remains simple to respect my current constraints but is designed to be able to evolve towards a distributed architecture if necessary.

Shared/Base Layer

A common project gathers:

  • Interfaces and cross-cutting abstractions (e.g., DbContext, initialization).
  • Elements related to dependency injection and utilities. This base ensures consistency and reduces redundancy between domains.

Business Domains

Each functional domain is isolated in a dedicated project:

  • Currently, only the Content domain is developed (content management, with front-office and back-office).
    • A topic has a mandatory summary and a set of chapters.
    • Each chapter contains one or more sections.
  • In the future, other domains will follow, such as Audit to log all changes.

Each domain project contains:

  • Repositories (data access)
  • Business services
  • Fluent API (DbContext and relationship configuration)

Business Models

The EF Core entities defined in the Model projects are used directly up to the Blazor front-end:

  • This choice avoids, for now, the multiplication of DTOs or ViewModels.
  • Since the entities already reflect what must be displayed, this approach keeps the project lighter and more readable.

Data Seeders

Two types of seeders are planned:

  • Actual Data Seeders (import of real data)
  • Dummy Data Seeders (generation of test data) They can be executed independently via PMC or via YAML pipelines.

Unified API

A single API gathers all the functionalities exposed by the domains:

  • It acts as a gateway between the Blazor front-end and the business logic.
  • This choice simplifies maintenance and remains compatible with a future evolution toward a microservices split.

Blazor Front-End

The front-end is developed in Blazor, which directly consumes the API:

  • This architecture allows a clear separation between logic and presentation.
  • It remains extensible: the front could be rewritten or replaced without affecting the business logic.

Global Breakdown

                              +------------------+
                              |   Front-End      |
                              |   Blazor (UI)    |
                              +------------------+
                                       |
                                       V
                              +------------------+
                              |      API         |
                              |   (unified)      |
                              +---------+--------+
                                        |
                                        V
        ---------------------------------------------------------
        |                                                       |
        V                                                       V
+---------------+                               +---------------+
|   Domain 1    |                               |   Domain 2    |
| (Services,    |                               | (Services,    |
|  Repos,       |----                       ----|  Repos,       |
|  DbContext,   |    |                      |   |  DbContext,   |
|  Fluent API)  |    |                      |   |  Fluent API)  |
+------+--------+    |                      |   +------+--------+
       |             |                      |          |
       V             |                      |          V
+---------------+    |                      |   +---------------+
|   Model 1     |    |                      |   |   Model 2     |
| (EF Entities) |    |                      |   | (EF Entities) |
+---------------+    |                      |   +---------------+
                     |                      |
                     \___________ __________/
                                 |
                                 V
                  +-----------------------------+
                  |      Shared / Base Layer    |
                  | (Interfaces, abstractions   |
                  |  DbContext, DI, utilities)  |
                  +-----------------------------+

Questions and Validation Points

Choice of Blazor mode

  • For now, Blazor Server seems the most suitable choice (cf. Patrick God’s resources on YouTube).
  • Question: to what extent will it be possible to migrate later to Blazor Auto (Server + WASM)?
  • What constraints should I anticipate today to keep this option open?

Security and Account Management

  • I want to use Identity with individual accounts.
  • With the architecture separating the front (Blazor) and the back (API), I wonder where to place the security logic.
  • Current assumption: authentication via JWT, with validation on the API side.
  • Questions:
    1. Should I create an Accounts domain with specific controllers to manage users and roles?
    2. Or should I keep the Identity implementation on the Blazor side, and only expose an API for administration (locking, role assignment, etc.)?

Relevance of the Current Architecture

  • I chose a modular monolith with separate projects per domain.
  • Objectives:
    1. Pedagogical (learning a “microservices ready” approach)
    2. Practical (being able to replace the front without rewriting everything)
  • Question: is this choice relevant, or is it disproportionate (over-engineered) for my context?

Direct Use of Entities

  • My business entities directly reflect what must be displayed.
  • I therefore do without DTOs or ViewModels.
  • Question: is this acceptable in a project of this type, or should I plan for a DTO layer from the start?

Thanks

Thank you in advance for the time you will take to read this detailed version and share your feedback. Your advice is very valuable for validating my choices and progressing in this project.

Developer technologies | .NET | Blazor
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 80,091 Reputation points Volunteer Moderator
    2025-09-04T16:30:02.1366667+00:00

    Blazor Rendering Mode

    Blazor WASM can not access any server resources directly, like call a database. If you want to be able to migrate from server to WASM, then have a separate UI website, and a separate Webapi website. You will not have to rewrite the calls to the API.

    it is generally best practice to do this split. the webapi project does not need to be exposed to the public and reduces the attack vector.

    Security Implementation

    if you use Individual accounts, there is no builtin JWT support as it is razor page cookie authentication. also only Blazor server is supported out of the box. You can use a custom openid server like Identity Server (https://duendesoftware.com/products/identityserver/) which you can integrate with individual identity. You can also roll you own, but unless you r really good understanding of the security issues you should buy the solution.

    if you stand front-end UI to back-end WebApi you will need to decide how user credentials are passed, and how the backend validates calls from the front end.

    Project Structure vs. Modularity

    if you code as a monolith single deployed application, extra care will need to be taken to be sure lower code objects do not leak, and of course you will be using direct calls instead of webapi to call the service layers.

    your best bet you be to create injectable interface to call the api. then in the future you can rewrite the a webapi implementation.

    you should create an abstract api project to be injected. it should have its own namespace. it should have no references to the lower api services, but rather define its own request response objects. If you define the domain entities here rather than formal request / response objects, don’t include the db context, that only belongs in the service layer. Also no entity method can reference a service layer api or object. This is why it can not have a reference to any service layer. A service layer can reference the api project.

    Of then you create a call interface variant of the api project. this will have a reference to api interfaces and lower service layers.


  2. Bruce (SqlWork.com) 80,091 Reputation points Volunteer Moderator
    2025-09-05T16:34:19.11+00:00

    as you are using a single website hosting your application, you want layers.

    • UI layer project - Blazor app code
    • API layer interface project - used by the UI layer to talk to the business layer. the layer should be injected into the blazor app code via services. This project will define messages passed between the UI and API and also interface methods. The UI should only call methods defined in this layer, never any lower layer or reference a class in a lower layer.
    • API layer implementation project - this is an implementation of the API layer that directly calls the service layers. In the future you can implement a version that calls a webapi. you should have a build step that copies this library and dependencies to the blazor app project. and use Activator.CreateInstance() when defining the service instance
    • server layer projects. this is where your domain services and repositories are defined. It's important that the UI layer can not directly access the service layers or repositories.

    while you can find online examples to roll you own JWT support, they generally are POC's and not very secure. You will need to study JWT security and verify the code is secure.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.