Clean Architecture with .NET....2
Design scalable .NET applications by using Clean Architecture principles and proven patterns....2
Clean Architecture with .NET....3
Foreword....6
Contributors....8
About the authors....8
About the reviewers....9
Table of Contents....10
Preface....28
Who this book is for....29
What this book covers....29
To get the most out of this book....31
Download the example code files....31
Download the color images....31
Conventions used....32
Get in touch....32
Free benefits with your book....33
How to unlock....35
Share your thoughts....35
Part 1....36
Introduction and Overview of Clean Architecture....36
1....38
Understanding the Limitations of Tightly Coupled Architectures....38
Technical requirements....38
Recognizing tightly coupled architectures....39
Hard-Coded Dependencies and Environment Assumptions....39
Logging, Global State, and Cross-Cutting Concerns....40
Hard-Coded Configuration and File Parsing....42
Direct Data Access and Security Risks....42
Inconsistent Logging and Lack of Observability....44
Business Logic in the Wrong Layer....45
Direct External Service Calls and HTTP Dependencies....47
Tightly Coupled Payment Processing....51
Database Writes and Repeated Security Risks....53
Why these patterns break down over time....55
Summary....55
Subscribe to Deep Engineering....57
2....58
Introduction to Clean Architecture....58
A brief history of clean architecture....58
Key principles of clean architecture....61
The dependency rule....61
Following the separation of concerns....62
Adhering to the single responsibility principle....62
Learning the main components of clean architecture....63
Entities and aggregates....63
Use cases....64
Interfaces....64
Controllers, pages, and endpoints....65
Gateways....65
Presenters....65
Knowing when not to use clean architecture....65
What clean architecture is not....65
Using the right architecture for the application....66
Very small applications....66
Proofs of concept and demos....66
CRUD-heavy applications....66
Real-time low-latency systems....67
Summary....67
Get this book's PDF version and more....68
Part 2....70
Design and Implementation of Clean Architecture....70
3....72
Adapting Clean Architecture to .NET....72
Technical requirements....73
Creating a new Blazor Server application....73
Creating project directories....74
Creating the web application....74
Setting up the project structure....75
Creating the Core project....76
Creating the Infrastructure project....77
Refining the Core layer....78
Application layer responsibilities....79
Domain layer responsibilities....80
Splitting the Core project....80
Rich versus anemic domains....82
Rich domain....82
Anemic domain....83
Managing cross-cutting concerns in the Common layer....85
Cross-cutting layer examples....85
Presentation layer example....86
Application layer example....87
Infrastructure layer example....88
Representing the Common layer as a .NET class library....89
Avoiding the dumping ground....90
Best practices for managing shared code....91
Common project real-world example....91
Configuring projects for Clean Architecture....94
Enforcing layer boundaries through project references....95
Configuring project references....96
Avoiding circular dependencies between layers....97
Managing third-party dependencies through abstractions....99
Defining abstractions....99
Depending upon abstractions....100
Avoiding dependencies to external libraries in the Application layer....101
Bridging the gap between layers through mapping....101
Exploring mapping between layers....102
Mapping with AutoMapper....103
Other mapping libraries and options....108
Summary....108
Subscribe to Deep Engineering....109
4....110
Designing a Clean Architecture Application....110
Technical requirements....110
Understanding the problem domain....111
Analyzing requirements....111
Deciphering the digital vision....111
What does the system need to do:....112
Who will use it:....112
Under what conditions:....112
How should it look and feel:....113
How secure should it be:....113
Identifying use cases....113
Mapping user stories to use cases – defining system functionality....114
Use case 1 – Add Item to Cart....114
Designing with use case diagrams....115
Mapping use cases across the application's layer....116
Designing the application architecture....119
When Clean Architecture isn't the right fit....119
Clean Architecture's sweet spot – complex, evolving systems....120
Why Clean Architecture is the right choice for Project Odyssey....121
Monolith versus microservices....121
The modular monolith....123
The power of Clean Architecture – building once, presenting diversely....123
Scaling without microservices....124
Applying DDD....124
Understanding the basics of DDD....125
Adapting DDD in a Clean Architecture application....125
Benefits of DDD in Project Odyssey....125
Defining entities and interfaces....126
Entities – mapping the real-world....126
Interfaces – defining contracts....128
Implementing the code....129
Beginning a use case implementation....129
Step 1 – Creating the domain entities....130
Step 2 – Creating the use case interface....133
Step 3 – Creating the repository interfaces....133
Step 4 – Creating the use case classes....133
Step 5 – Implementing the use case....134
Testing the use case logic using xUnit and NSubstitute....136
Testing the domain logic....139
Summary....142
Get this book's PDF version and more....143
5....144
Implementing the Core Layer....144
Technical requirements....144
Why application-first is critical in Clean Architecture....144
A real-world example: Integrating with a payment gateway....145
Implementing the use cases....146
Implementing the Remove Item from Cart use case....148
Step 1 – Create domain entities....148
Step 2 – Create a use-case interface....148
Step 3 – Create a use-case implementation....149
Implementing the Calculate Cart Total use case....150
Step 1 – Create domain entities....150
Step 2 – Create a use-case interface....150
Step 3 – Create a use-case implementation....150
Implementing the Process Payment use case....152
Step 1 – Create domain entities....152
Step 2 – Create a use-case interface....155
Step 3 – Create a use-case implementation....157
Implementing the Manage Product Inventory use case....160
Step 1 – Create domain entities....160
Step 2 – Create a use-case interface....160
Step 3 – Create a use-case implementation....162
Implementing the Access Customer Carts and Order Histories use case....163
Step 1 – Create domain entities....163
Step 2 – Create a use-case interface....163
Step 3 – Create a use-case implementation....164
Testing the Core layer using xUnit and NSubstitute....165
Structuring unit tests with Arrange, Act, Assert....166
Testing the Remove Item from Cart use case....166
Testing the Calculate Cart Total use case....168
Testing the Process Payment use case....169
Testing the Manage Product Inventory use case....171
Testing the Access Customer Data use case....172
Summary....175
Subscribe to Deep Engineering....176
6....178
Implementing the Infrastructure Layer....178
Technical requirements....179
Implementing services and HTTP clients....179
The payment gateway and external APIs....180
The payment gateway service....181
The external payment gateway API....182
Why Refit....183
Why HttpClientFactory (and how Refit uses it)....183
Alternatives to Refit....184
Stand-in payment service....185
Defining the payment gateway contract....185
DI in .NET....187
DI in our application....188
The options pattern in .NET....190
The options pattern in our application....191
Using User Secrets for local development....197
Enabling User Secrets for local development....198
Using Visual Studio....198
Using the .NET CLI....198
Testing the Infrastructure layer....199
Setting up shared resources....199
FluentAssertions....200
AutoFixture....200
The unit tests....201
The payment gateway tests....201
The integration tests....201
The payment gateway API tests....202
The test setup....202
The test scenarios....202
Summary....203
Get this book's PDF version and more....204
7....206
Implementing the Persistence Layer....206
Technical requirements....207
The Persistence layer in Clean Architecture....207
Project structure options....208
Adopting a code-first mindset....208
Code-first in practice....208
The database as an implementation detail....209
Flexibility and testability....209
Code-first does not mean no SQL....209
Using EF Core....210
Creating entities....210
Why persistence entities are separate from domain entities....210
Understanding navigation properties....212
The Nav prefix convention....212
Supporting fluent configuration....213
The role of DbContext in EF Core....214
Preparing the infrastructure project....214
Defining the CoreDbContext class....215
DbSet properties....215
Applying entity configurations....216
Configuring the Order entity....216
Defining the primary key....216
Configuring relationships....217
Applying property constraints....217
Configuring owned entities....218
Exploring the remaining configurations....219
Implementing repositories....219
DbContext lifetime and why we use a factory....219
OrderRepository as the primary example....220
Repository construction and dependencies....220
Creating a new order....221
Updating an existing order....222
Querying and returning domain entities....223
Key takeaways....223
Mapping between persistence and domain models....223
Mapping at the persistence boundary....224
The infrastructure mapping profile....224
Centralizing mapping logic....224
Mapping is a boundary, not a shortcut....225
Registering and configuring SQL Server....226
Registering AutoMapper profiles....227
Configuring SQL Server and the DbContext factory....227
Hosting and configuring SQL Server in Azure....228
Creating an Azure SQL database....229
Example Azure SQL resource configuration....229
SQL authentication credentials....230
Keeping costs low....230
Creating an Azure SQL database (Quickstart)....231
Retrieving the connection string....232
idx_7f4d5201idx_d2a54950idx_eaab2d9cidx_220fa1aeidx_77997047idx_ad0f64ecidx_bc11b058Connecting to the SQL Server from Visual Studio....233
Testing the Persistence layer....235
Mapping tests....236
Testing the real mapping configuration....236
Application mapping tests....236
Infrastructure mapping tests....237
What these tests are verifying....237
Why these tests matter....238
Leveraging Docker, Testcontainers, and Respawn for integration testing....238
Using xUnit test collections for shared infrastructure....239
The TestInitializer class....239
Sharing the setup with xUnit collections....240
Why this approach works well....240
DbContext tests....241
What these tests validate....241
What these tests do not prove....242
Why this approach is still valuable....242
Repository tests....243
What repository tests focus on....243
Seeding data intentionally....243
Why these tests matter....244
Running the tests against the Azure SQL server....244
Summary....245
Subscribe to Deep Engineering....247
8....248
Implementing the Presentation layer with Identity....248
Technical requirements....249
Initializing the Presentation layer....249
The Presentation layer as a composition boundary....250
Introducing a service composition root....251
Refactoring Program.cs to delegate composition....252
Making configuration explicit....253
Delegating service composition....254
Initializing the database....255
Integrating MudBlazor for a modern UI....256
Why MudBlazor for this project....256
Registering MudBlazor services....256
Configuring MudBlazor styles and layout integration....257
Aligning your project with Project Odyssey....258
CSS isolation, bundling, and SASS....259
Optional: dark and light theme support....259
Updating navigation and pages....259
Introducing identity at the Presentation boundary....262
Authentication versus application identity....262
Keeping the core identity-agnostic....262
What to expect next....263
Implementing user authentication with Microsoft Entra External ID....263
Overview of the Integration....263
Guided External ID setup....264
Phase 1: Create an External ID tenant....264
Pricing....264
Key configuration points....264
Microsoft documentation....265
Checkpoint: You're done when....265
Phase 2: Register the application....265
Key configuration points....265
Microsoft documentation....266
Checkpoint: You're done when....266
Phase 3: Configure token claims and permissions....266
Key configuration points....267
Microsoft documentation....267
Checkpoint: You're done when....268
Phase 4: Create a sign-up and sign-in user flow....268
Key configuration points....268
Microsoft documentation....268
Checkpoint: You're done when....268
Phase 5: Create and store a client secret....269
Key configuration points....269
Microsoft documentation....269
Checkpoint: You're done when....269
Final setup summary....269
Configuring authentication in Blazor Server....270
Adding package references....270
Registering authentication services....271
Enabling authentication middleware....271
Application configuration....273
Base configuration (appsettings.json)....273
Development overrides (appsettings.Development.json)....274
Storing the client secret securely....275
Making authentication state available to the UI....275
Wiring authentication into the Presentation layer....275
Presenting authentication state in the UI....276
Creating the LoginDisplay UI component....276
Connecting authentication state to application data....277
Initializing user context....278
Translating identity claims....278
Ensuring an application user exists....279
Translating claims with extension methods....279
Surfacing authentication in the application layout....280
Verifying the authentication flow....281
Summary....282
Get this book's PDF version and more....283
9....284
Building Secure, Testable UI Components for Use Cases....284
Technical requirements....285
Implementing core use case flows in the UI....285
The Product Catalog page....285
Key concepts and features....285
Loading state....285
Product display....286
Pagination....287
State change notifications....288
State change services in Blazor....288
Understanding what this event does and does not do....289
Why not use EventCallback here?....290
Lifecycle considerations....290
Architectural alignment....290
Adding image support to products....290
The Shopping Cart page with custom components....292
Key concepts and features....292
Custom components....292
Organizing components by namespace....294
State change subscriptions....294
Shopping cart icon....295
The Checkout page....298
Key concepts and features....298
NavigationManager....298
MudForm vs. EditForm....299
The Order Confirmation page....302
The Order History page....303
The Administration page....304
The Customer Service page....304
Securing the UI with authorization policies and custom handlers....305
Creating the authentication service....305
Implementing role-based authorization using policies....306
Registering authorization policies and services....307
Securing the UI....309
Enabling route-level authorization....309
Protecting application pages....310
Applying role-based policies....311
Securing UI elements conditionally....311
A clear and intentional security model....312
Testing the Presentation layer with bUnit....313
Startup tests....313
Using IClassFixture....314
Controlling the environment explicitly....314
Verifying the application starts....314
Shopping cart icon tests....315
Summary....317
Subscribe to Deep Engineering....318
Part 3....320
Advanced Topics in Clean Architecture....320
10....322
Improving Clean Architecture in .NET with Structured Service Composition....322
Technical requirements....324
When composition lives in Program.cs....324
Introducing structural boundaries....325
Formalizing the composition boundary....327
Implementing the service composition structure....329
Refactoring the Infrastructure layer....329
Enabling logging for pipeline execution....331
Adding Serilog as a cross-cutting concern....332
Implementing the pipeline logger....333
Refactoring the Presentation layer....334
Updating the tests....336
Reusing the composition pipeline in a console application....338
Setting up the console application....338
Proving the multi-host model....340
Running the console application....341
Summary....342
Get this book's PDF version and more....343
11....344
Securing a Clean Architecture Application....344
Technical requirements....344
Learning from real-world threats....345
Enforcing MFA with Entra ID....345
Securing secrets with Azure Key Vault....348
The risks of hardcoding secrets in your application....349
Creating the Azure Key Vault resource....349
Granting yourself access to manage secrets....350
Integrating Azure Key Vault into your application....351
Configuring Azure Key Vault in the application....351
Adding Key Vault support in the Presentation layer....352
Understanding token credential choices....355
Authenticating with Azure Key Vault in Visual Studio....355
Testing Azure Key Vault integration....356
Adding secrets to Azure Key Vault....356
Best practice: invalidating exposed secrets....358
CLI alternative (optional for advanced users)....358
Setting up a test configuration for Key Vault integration....359
Understanding what the tests validate....360
Running the tests....361
Structured logging and obfuscation with Serilog....361
Why protecting logs matters: a real-world example....362
Implementing structured logging with Serilog....363
Installing required dependencies....363
Optional: OpenTelemetry for advanced users....364
Adding Serilog to the Presentation layer....364
Configuring Serilog for the host....364
Enabling Serilog as the logging provider....365
Enabling sensitive data masking....366
Adding logging configuration to appsettings.json....366
Defining default log levels....366
Customizing log levels for development....367
Injecting Serilog and observing masked logs....368
Injecting the logger into a component....368
Running the application and inspecting logs....369
Understanding environment-based masking....369
When should logs be scrubbed?....370
Logging for security and fraud detection....370
Legal and compliance considerations....370
Limitations of automated scrubbing....371
Best practices for log scrubbing....371
Summary....371
Subscribe to Deep Engineering....373
12....374
Reducing Boilerplate in Clean Architecture Applications....374
Technical requirements....375
The cost of boilerplate in Clean Architecture....376
Convenience vs. consistency....376
The role of the application layer....376
Routing all behavior through the application layer....377
The tension: When consistency introduces friction....379
Introducing MediatR and input validation....379
Introducing MediatR to the application layer....380
Installing MediatR....381
Key concepts to understand....381
Migrating the ProcessPayment use case....382
Modifying the input class....382
Updating the use case handler....382
Removing the old interface....382
Navigating MediatR-driven applications....383
Introducing FluentValidation for input validation....383
Installing FluentValidation for application request validation....384
Creating a validator for ProcessPaymentInput....384
Registering MediatR, FluentValidation, and pipeline behaviors....386
Replacing the existing use case registration....386
Introducing validation using MediatR pipeline behaviors....387
Validating the request pipeline....388
Hands-on practice....389
Applying CQRS across handlers and repositories....390
Understanding CQRS in clean architecture....391
Updating request and handler names to reflect intent....392
Preserving use case focus (even without the word)....392
Refactoring ProcessPayment for CQRS naming....393
Splitting repositories: commands vs. queries....394
How to split the repositories....394
Hands-on practice....396
Introducing generics and its limitations....397
Why generics matter (and why we're ready for them)....398
Adopting EntityAxis for generic CRUD operations....399
Project preparation: installing EntityAxis....399
Understanding the Core of EntityAxis: IEntityId....400
Understanding Generic Command and Query Services....401
Setting Up EntityAxis for a Domain Entity....403
Connecting Domain Repositories to EntityAxis Command and Query Services....404
Retrieving an Order by ID with MediatR....407
Benefits of Using Generics in Clean Architecture....407
When Generics Are Not Enough....408
Recognizing When to Extend or Exit the Generic Pipeline....408
Hands-On Practice: Applying What You've Learned....409
Optional Checklist: Aligning Project Odyssey with EntityAxis....409
Summary....410
Get this book's PDF version and more....411
13....412
Deploying a Clean Architecture Application in Azure....412
Technical requirements....413
Provisioning the Azure Web App environment....413
Creating the Azure Key Vault for the dev environment....413
Creating the Azure Web App....414
Web App configuration checklist....414
Creating the resource....415
Managing free-tier resources....415
Enabling managed identity....416
Granting Key Vault access via role assignment....416
Preparing for deployment....417
Configuring application settings....417
Storing secrets in key vault....418
Preparing the database....419
Setting environment variables....421
Enabling publishing and downloading the publish profile....422
Updating authentication redirect URI....422
Publishing the Blazor application to Azure....423
Import profile and publish from Visual Studio....423
Starting the application....425
Post-deployment validations....425
Getting your application production-ready....426
Environment isolation and security....427
Scalability, observability, and automation....427
Usability and maintainability in the UI....427
Production-readiness checklist....428
Summary....428
Subscribe to Deep Engineering....429
Part 4....430
Additional Topics and Resources....430
14....432
Managing and Evolving a Clean Architecture Application....432
Technical requirements....433
Monitoring with health checks and local observability....433
Expose system health with built-in checks....433
Add health check support to the Infrastructure layer....434
Inspect logs, traces, and metrics with OTEL and Aspire....436
Installing the required packages....437
Configuring OTEL....438
Viewing telemetry with the Aspire dashboard....441
Capturing MediatR metrics and logs....441
Forward telemetry to Azure for production monitoring....442
Creating an Application Insights resource....442
Link Application Insights to your web app....443
Configuring Serilog to export logs to Azure....443
Deploying and monitoring....444
Extending the application with Azure functions....445
Scale features without adding complexity....446
Add azure functions as a new front end....447
Creating the azure function project....447
Introduce a shared presentation class library....448
Installing required NuGet packages....449
Add configuration files....450
Service composition....451
Wire up the function to execute application logic....452
Running and validating functions locally....453
Sustaining clean architecture as you scale....454
When clean architecture starts to slip....454
Bypassing the use case....454
Leaky core....455
Infrastructure knows too much....456
Treat use cases as your growth surface....457
Staying consistent as the team grows....459
Reaffirm the "Why" behind your architecture....459
Using automation to catch boundary violations early....459
Codify your standards with architecture decision records....460
Be consistent–not rigid....460
Protect architecture from burnout....460
Summary....461
Get this book's PDF version and more....462
15....464
Conclusion....464
Revisiting the journey....464
Key principles to carry forward....465
Future exploration and real-world applications....466
Final thoughts from the authors....467
Resources and further reading....468
Clean Architecture useful tools....469
Clean Architecture solution templates....469
Clean Architecture examples....470
Clean Architecture (and related) courses....470
Clean Architecture books....471
Clean Architecture online content....471
Summary....472
Subscribe to Deep Engineering....472
16....474
Unlock Your Exclusive Benefits....474
Unlock this Book's Free Benefits in 3 Easy Steps....475
Step 1....475
Step 2....475
Step 3....476
Need Help....476
Why subscribe?....478
Other Books You May Enjoy....479
Packt is searching for authors like you....481
Share your thoughts....481
Index....482
Learn Clean Architecture as a set of organizing principles, not just code templates. This book shows how to design scalable, testable .NET apps using modern patterns, DDD, CQRS, and secure Azure integration.
Free with your book: DRM-free PDF version + access to Packt's next-gen Reader*
Learn how to apply Clean Architecture in real-world .NET applications with Azure in this guide. Designed around an e-commerce project - Project Odyssey, you’ll design and build every architectural layer, from core domain logic and application orchestration to infrastructure and presentation.
This book equips you to apply DDD, CQRS, MediatR, and dependency injection, enabling loosely coupled, testable systems. You’ll build reusable and modular code structures that scale with your application’s complexity and learn how to persist data using EF Core with a code-first approach, managing schema evolution with migrations while keeping infrastructure concerns isolated from your domain logic. Learn how to develop secure systems by integrating Azure External ID, Azure Key Vault, and application-level authentication and authorization.
Gain practical experience with Blazor Server, Razor components, and MudBlazor UI, all integrated within a layered architecture. Learn to enforce business logic boundaries, reduce boilerplate with generic request handlers, and use real-world use cases like payment processing and shopping cart management.
Whether you're new to Clean Architecture or scaling up enterprise solutions, this book provides the patterns, tools, and mindset to succeed.
*Email sign-up and proof of purchase required
.NET developers, software engineers, and solution architects who want to build applications that are easier to understand, test, and evolve over time. This book is a good fit if you’re already familiar with C# and .NET, and want a clearer, more practical way to structure real-world applications using Clean Architecture. Basic knowledge of web development and Azure will help you follow along.