Structuring a .NET Core 9 Blazor + API Architecture for Microservices Readiness, DRY/SOLID Compliance, and Secure Account Management Best Practices

Laurent Guigon 311 Reputation points
2025-08-28T08:54:10.51+00:00

Hello everyone,

I’m working on a content management application (wiki-style) developed in .NET Core 9, designed to be microservices-ready and modular enough to evolve without heavy refactoring. The app will run on Azure without containers.

🏗️ Current Architecture (simplified view)

Blazor (mode to define: Auto, WASM, or Server) → API → Domains → Shared

📂 Layer Details

  • Shared Contains all abstractions and interface contracts. → Purpose: respect DRY and SOLID principles and avoid duplication across domains.

Domains Each domain is organized into multiple projects:

.csproj for services and repositories

  `.csproj` for **models**
  
     `.csproj` for **data seeding** (executable via **PMC** and **YAML pipeline**)
     

Currently, I have a Content / ContentManagement domain. I plan to add a User Accounts domain.

🔐 User Management & Security

I plan to use Microsoft Identity (or the latest replacement in the .NET ecosystem) with:

Automatic scaffolding for authentication/user management pages (like in a Blazor project with Identity enabled from the start).

API security via JWT.

Isolation of the accounts domain similar to the content domain, keeping extensibility for distributed architecture.


🧩 Minimal Essential Code Excerpts

EncyclOniria.Shared/Contracts/IRepository.cs

namespace EncyclOniria.Shared.Contracts
{
    public interface IRepository<TEntity> where TEntity : class
    {
        Task<TEntity?> GetByIdAsync(Guid id);
        Task<IEnumerable<TEntity>> GetAllAsync();
        Task AddAsync(TEntity entity);
        void Update(TEntity entity);
        void Remove(TEntity entity);
        Task<int> SaveChangesAsync();
    }
}

EncyclOniria.Shared/Data/BaseDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace EncyclOniria.Shared.Data
{
    public abstract class BaseDbContext : DbContext
    {
        public BaseDbContext(DbContextOptions options) : base(options) { }
    }
}

EncyclOniria.Content.Data/DesignTimeContentDbContextFactory.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace EncyclOniria.Content.Data
{
    public class DesignTimeContentDbContextFactory : IDesignTimeDbContextFactory<ContentDbContext>
    {
        public ContentDbContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<ContentDbContext>();
            optionsBuilder.UseSqlServer("Data Source=:memory:"); // placeholder
            return new ContentDbContext(optionsBuilder.Options);
        }
    }
}

EncyclOniria.Content.Seeders/ISeeder.cs

namespace EncyclOniria.Content.Seeders
{
    public interface ISeeder
    {
        Task SeedAsync(CancellationToken cancellationToken = default);
        string Name { get; }
    }
}

EncyclOniria.SeederRunner/Program.cs (Console Runner)

using EncyclOniria.Content.Seeders;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        services.AddTransient<ISeeder, RealDataSeeder>();
        services.AddTransient<ISeeder, DummyDataSeeder>();
    })
    .Build();

using var scope = host.Services.CreateScope();
var seeders = scope.ServiceProvider.GetServices<ISeeder>();
foreach (var seeder in seeders)
    await seeder.SeedAsync();

❓ Questions

Architecture Validation & Microservices Readiness Is this architecture sound as-is?

If I eventually expose one API per domain, will it conform to microservices best practices?

  Any advice to stay **DRY**, **SOLID**, and ready for microservices?
  
  **User Accounts & Security** How and where should I implement user/account services?
  
     I was thinking of creating a dedicated **Accounts domain** and API for backend management.
     
        Typically in Blazor projects, Identity scaffolding is placed directly in the client. Can I still:
        
              Keep Identity scaffolding in Blazor, and
              
                    Secure APIs with JWT?
                    
                       How do you usually handle authentication/authorization in this type of setup?
                       
                          There must be an **admin interface** to manage users and roles—does this justify a dedicated microservice?
                          
                          **Blazor Mode Selection** Which Blazor model should I choose for this project?
                          
                             **Server**, **WASM**, or **Auto**?
                             
                                I want to understand the differences in practice and how to leverage either approach with API security.
                                

That’s the gist of it—any guidance, best practices, or experiences you could share would be greatly appreciated.


Si tu veux, je peux te fournir une version prête à poster sur les forums, déjà formatée avec Markdown et liens pour GitHub-style code blocks, pour que tu n’aies plus qu’à copier-coller. Veux‑tu que je fasse ça ?Parfait ! Voici une version consolidée, en anglais, avec uniquement le code strictement nécessaire pour illustrer l’architecture et les seeders, et toutes tes questions clairement listées. J’ai également ajouté la mention Azure sans conteneurs.


Structuring a .NET Core 9 Blazor API Architecture for Microservices and Secure Account Management Best Practices

Hello everyone,

I’m working on a content management application (wiki-style) developed in .NET Core 9, designed to be microservices-ready and modular enough to evolve without heavy refactoring. The app will run on Azure without containers.

🏗️ Current Architecture (simplified view)

Blazor (mode to define: Auto, WASM, or Server) → API → Domains → Shared

📂 Layer Details

Shared
Contains all abstractions and interface contracts.
→ Purpose: respect DRY and SOLID principles and avoid duplication across domains.

Domains
Each domain is organized into multiple projects:

.csproj for services and repositories

  `.csproj` for **models**
  
     `.csproj` for **data seeding** (executable via **PMC** and **YAML pipeline**)
     

Currently, I have a Content / ContentManagement domain. I plan to add a User Accounts domain.

🔐 User Management & Security

I plan to use Microsoft Identity (or the latest replacement in the .NET ecosystem) with:

Automatic scaffolding for authentication/user management pages (like in a Blazor project with Identity enabled from the start).

API security via JWT.

Isolation of the accounts domain similar to the content domain, keeping extensibility for distributed architecture.


🧩 Minimal Essential Code Excerpts

EncyclOniria.Shared/Contracts/IRepository.cs

namespace EncyclOniria.Shared.Contracts
{
    public interface IRepository<TEntity> where TEntity : class
    {
        Task<TEntity?> GetByIdAsync(Guid id);
        Task<IEnumerable<TEntity>> GetAllAsync();
        Task AddAsync(TEntity entity);
        void Update(TEntity entity);
        void Remove(TEntity entity);
        Task<int> SaveChangesAsync();
    }
}

EncyclOniria.Shared/Data/BaseDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace EncyclOniria.Shared.Data
{
    public abstract class BaseDbContext : DbContext
    {
        public BaseDbContext(DbContextOptions options) : base(options) { }
    }
}

EncyclOniria.Content.Data/DesignTimeContentDbContextFactory.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace EncyclOniria.Content.Data
{
    public class DesignTimeContentDbContextFactory : IDesignTimeDbContextFactory<ContentDbContext>
    {
        public ContentDbContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<ContentDbContext>();
            optionsBuilder.UseSqlServer("Data Source=:memory:"); // placeholder
            return new ContentDbContext(optionsBuilder.Options);
        }
    }
}

EncyclOniria.Content.Seeders/ISeeder.cs

namespace EncyclOniria.Content.Seeders
{
    public interface ISeeder
    {
        Task SeedAsync(CancellationToken cancellationToken = default);
        string Name { get; }
    }
}

EncyclOniria.SeederRunner/Program.cs (Console Runner)

using EncyclOniria.Content.Seeders;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        services.AddTransient<ISeeder, RealDataSeeder>();
        services.AddTransient<ISeeder, DummyDataSeeder>();
    })
    .Build();

using var scope = host.Services.CreateScope();
var seeders = scope.ServiceProvider.GetServices<ISeeder>();
foreach (var seeder in seeders)
    await seeder.SeedAsync();

❓ Questions

Architecture Validation & Microservices Readiness
Is this architecture sound as-is?

If I eventually expose one API per domain, will it conform to microservices best practices?

  Any advice to stay **DRY**, **SOLID**, and ready for microservices?
  
  **User Accounts & Security**  
   How and where should I implement user/account services?
  
     I was thinking of creating a dedicated **Accounts domain** and API for backend management.
     
        Typically in Blazor projects, Identity scaffolding is placed directly in the client. Can I still:
        
              Keep Identity scaffolding in Blazor, and
              
                    Secure APIs with JWT?
                    
                       How do you usually handle authentication/authorization in this type of setup?
                       
                          There must be an **admin interface** to manage users and roles—does this justify a dedicated microservice?
                          
                          **Blazor Mode Selection**  
                           Which Blazor model should I choose for this project?
                          
                             **Server**, **WASM**, or **Auto**?
                             
                                I want to understand the differences in practice and how to leverage either approach with API security.
                                

That’s the gist of it—any guidance, best practices, or experiences you could share would be greatly appreciated.


Developer technologies | .NET | Blazor
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 79,521 Reputation points Volunteer Moderator
    2025-08-28T15:54:13.1333333+00:00

    you should use the new web app project structure for Blazor apps, where there is a separate project for the Blazor code, and hosting .net 9 webapi project. the webapi project should act as a broker (gateway) to the micro services.

    modern authentication (oauth/tokens) uses the browser and javascript to get an access/refresh token. Blazor uses jsinterop and MSAL library for this. the microservice broker can use the token to validate the user. typically the broker would use its own token to access the microservices. as authentication requires redirecting the browser to the authentication server, the Blazor app will be unloaded and reloaded during authentication.

    if you are using microservices, only the microservice should have database access. each microservice should be its own domain. also microservices should have dedicated databases and not share. the microservices should have independent releases. its not uncommon, to have separate git repos per service, this keeps the service a blackbox.

    only the microservices should know about data repositories and should not expose data entity objects. the microservice. the micros service should use OpenApi or gRPC.

    0 comments No comments

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.