Architecting ASP.NET Core Applications - Third Edition

Book description

Backend design like you've never seen it before – a guide to building SOLID ASP.NET Core web apps that stand the test of time. Featuring more Minimal APIs, more testing, a new e-commerce project, and the modular monolith! Purchase of the print or Kindle book includes a free PDF eBook.

Key Features

  • Learn multiple ways to organize your application code and become a more flexible ASP.NET Core developer
  • Explore hands-on design patterns, learn architectural principles, and how to sidestep anti-patterns
  • Refactor code toward modern application design, such as feature-based vertical slice and clean architecture

Book Description

This unique ASP.NET Core book will fill in the gaps in your REST API and backend designs. Learn how to build robust, maintainable, and flexible apps using Gang of Four (GoF) design patterns and modern architectural principles. This new edition is updated for .NET 8 and focuses exclusively on the backend, with new content on REST APIs, the REPR pattern, and building modular monoliths.

You’ll start by covering foundational concepts like REST, the SOLID principles, Minimal APIs, dependency injection in .NET, and other ASP.NET Core 8 mechanisms. Then, you’ll learn to develop components using design patterns, including many from the GoF. Finally, you’ll explore organizing your application code with patterns that vary from layers to feature-oriented vertical slice designs, covering CQS and a deep dive into microservices along the way. A brand-new e-commerce project at the end of the book will tie it all together.

This how-to guide will teach you how to assemble your own APIs from building blocks, to suit whatever real-world requirements you may have.

What you will learn

  • Apply the SOLID principles for building flexible and maintainable software
  • Test your apps effectively with automated tests, including black-box testing
  • Embark on mastering ASP.NET Core dependency injection
  • Work with GoF design patterns including strategy, decorator, facade, and composite
  • Design REST APIs using Minimal APIs and ASP.NET Core MVC
  • Discover layering and the tenets of clean architecture
  • Use feature-oriented techniques as an alternative to layering
  • Explore microservices, CQS, REPR, vertical slice architecture, and many more patterns

Who this book is for

This book is for intermediate-level ASP.NET Core developers who want to improve their C# app code structure and API design skills. ASP.NET developers who want to modernize their knowledge and enhance their technical architecture skills will also like this book. It’s also a good refresher for those in software design roles with more experience looking to update their expertise. A good knowledge of C# programming and a basic understanding of web concepts is necessary to get the most out of this book, though some refreshers are included along the way.

Table of contents

  1. Preface
    1. Who this book is for
    2. What this book covers
    3. To get the most out of this book
    4. Get in touch
  2. Section 1: Principles and Methodologies
  3. Introduction
    1. What is a design pattern?
    2. Anti-patterns and code smells
      1. Anti-patterns
        1. Anti-pattern: God class
      2. Code smells
        1. Code smell: Control Freak
        2. Code smell: long methods
    3. Understanding the web: request/response
    4. Getting started with .NET
      1. .NET SDK versus runtime
      2. .NET 5+ versus .NET Standard
      3. The command-line interface versus Visual Studio Code versus Visual Studio
        1. An overview of project templates
        2. Running and building your program
      4. Technical requirements
    5. Summary
    6. Questions
    7. Further reading
    8. Answers
  4. Automated Testing
    1. An overview of automated testing
      1. Unit testing
      2. Integration testing
      3. End-to-end testing
      4. Other types of tests
      5. Finding the right balance
      6. Enhancing code quality
        1. Improving quality with refactoring
        2. Managing technical debt
    2. Testing approaches
      1. TDD
      2. ATDD
      3. BDD
    3. Testing techniques
      1. White-box testing
      2. Black-box testing
      3. Gray-box testing
      4. White-box vs. black-box vs. gray-box testing
      5. Conclusion
    4. Test case creation
      1. Equivalence partitioning
      2. Boundary value analysis
      3. Decision table testing
      4. State transition testing
      5. Use case testing
    5. Introducing the xUnit framework
      1. How to create an xUnit test project
      2. Key xUnit features
        1. FactAttribute
        2. Assertions
        3. TheoryAttribute
        4. Fixture
    6. Arrange, Act, Assert
    7. Organizing your tests
      1. Unit tests
        1. Namespaces
        2. Test class names
        3. Test code inside the test class
      2. Integration tests
    8. Writing ASP.NET Core integration tests
      1. Classic web application
      2. Minimal hosting
        1. Workaround
        2. Alternative to using fixtures
        3. Creating a reusable test application
    9. Important testing principles
    10. Summary
    11. Questions
    12. Further reading
    13. Answers
  5. Architectural Principles
    1. Separation of concerns (SoC)
    2. Don’t repeat yourself (DRY)
    3. Keep it simple, stupid (KISS)
    4. You Aren’t Gonna Need It (YAGNI)
    5. The SOLID principles
      1. Single responsibility principle (SRP)
        1. Project – Single Responsibility
      2. Open/closed principle (OCP)
        1. Project – Open Close
      3. Liskov substitution principle (LSP)
        1. The LSP explained
        2. Covariance and contravariance
        3. Project – Liskov Substitution
        4. Conclusion
      4. Interface segregation principle (ISP)
        1. What is an interface?
        2. Project – Interface Segregation
        3. Conclusion
      5. Dependency inversion principle (DIP)
        1. Direct dependency
        2. Inverted dependency
        3. Direct subsystems dependency
        4. Inverted subsystems dependency
        5. Project – Dependency inversion
        6. Conclusion
    6. Summary
    7. Questions
    8. Further reading
    9. Answers
  6. REST APIs
    1. REST and HTTP
      1. HTTP methods
      2. HTTP status codes
      3. HTTP headers
      4. Versioning
        1. Default versioning strategy
        2. Versioning strategy
      5. Wrapping up
    2. The Data Transfer Object (DTO) pattern
      1. Goal
      2. Design
      3. Conceptual examples
        1. Registering for an activity
        2. Fetching activity registration details
      4. Conclusion
    3. API contracts
      1. Code-first API contract
        1. The first endpoint
        2. The second endpoint
      2. Wrapping up
    4. Summary
    5. Questions
    6. Further reading
    7. Answers
  7. Section 2: Designing with ASP.NET Core
  8. Minimal APIs
    1. Top-level statements
    2. Minimal hosting
    3. Minimal APIs
      1. Mapping a route to a delegate
      2. Configuring endpoints
        1. Inputs
        2. Outputs
        3. Metadata
        4. Configuring JSON serialization
      3. Leveraging endpoint filters
      4. Leveraging the endpoint filter factory
      5. Organizing endpoints
        1. MapGroup
        2. Creating a custom Map extension method
        3. Class libraries
    4. Using Minimal APIs with Data Transfer Objects
      1. Goal
      2. Design
      3. Project – Minimal API
        1. Raw CRUD endpoints
        2. DTO-enabled endpoints
      4. Conclusion
    5. Summary
    6. Questions
    7. Further reading
    8. Answers
  9. Model-View-Controller
    1. The MVC design pattern
      1. Goal
      2. Design
      3. Anatomy of ASP.NET Core web APIs
        1. The entry point
        2. Directory structure
        3. Controller
        4. Returning values
        5. Attribute routing
      4. Conclusion
    2. Using MVC with DTOs
      1. Goal
      2. Design
      3. Project – MVC API
        1. Raw CRUD controller
        2. DTO controller
      4. Conclusion
    3. Summary
    4. Questions
    5. Further reading
    6. Answers
  10. Strategy, Abstract Factory, and Singleton Design Patterns
    1. The Strategy design pattern
      1. Goal
      2. Design
      3. Project – Strategy
      4. Conclusion
    2. The Abstract Factory design pattern
      1. Goal
      2. Design
      3. Project – Abstract Factory
      4. Project – the mid-range vehicle factory
      5. Impacts of the Abstract Factory
      6. Conclusion
    3. The Singleton design pattern
      1. Goal
      2. Design
      3. An alternative (better) way
      4. Code smell – Ambient Context
      5. Conclusion
    4. Summary
    5. Questions
    6. Answers
  11. Dependency Injection
    1. What is dependency injection?
      1. The composition root
      2. Striving for adaptability
      3. Understanding the use of the IoC container
      4. The role of an IoC container
      5. Code smell – Control Freak
        1. Stable dependencies
        2. Volatile dependencies
        3. Conclusion
      6. Object lifetime
        1. What’s an object’s lifetime?
        2. .NET object lifetime
      7. Registering our dependencies
      8. Registering your features elegantly
        1. Project – Registering the demo feature
      9. Using external IoC containers
    2. Revisiting the Strategy pattern
      1. Constructor injection
      2. Property injection
      3. Method injection
      4. Project – Strategy
        1. Shared building blocks
        2. Control Freak controllers
        3. Injecting an implementation in the controllers
        4. Injecting an abstraction in the controller
        5. Constructing the InjectAbstractionLocationsController
      5. Conclusion
    3. Revisiting the Singleton pattern
      1. Project – Application state
        1. First implementation
        2. Second implementation
        3. Using the implementations
      2. Project – Wishlist
      3. Conclusion
    4. Understanding guard clauses
    5. Understanding the Service Locator pattern
      1. Project – ServiceLocator
        1. Implementing method injection
        2. Implementing constructor injection
        3. Implementing a minimal API
      2. Conclusion
    6. Revisiting the Factory pattern
      1. Project – Factory
    7. Summary
    8. Questions
    9. Further reading
    10. Answers
  12. Application Configuration and the Options Pattern
    1. Loading the configuration
    2. Learning the options interfaces
      1. IOptionsMonitor<TOptions>
      2. IOptionsFactory<TOptions>
      3. IOptionsSnapshot<TOptions>
      4. IOptions<TOptions>
    3. Exploring common usage scenarios
      1. Manual configuration
      2. Using the settings file
      3. Injecting options
      4. Named options
        1. IOptionsFactory<MyOptions>
        2. IOptionsMonitor<MyOptions>
        3. IOptionsSnapshot<MyOptions>
      5. Bind options to an existing object
      6. Reloading options at runtime
    4. Learning options configuration
      1. Creating the program
      2. Configuring the options
      3. Implementing a configurator object
      4. Adding post-configuration
      5. Using multiple configurator objects
      6. Exploring other configuration possibilities
    5. Validating our options objects
      1. Eager validation
      2. Data annotations
      3. Validation types
    6. Validating options using FluentValidation
    7. Injecting options objects directly
    8. Centralizing the configuration for easier management
    9. Using the configuration-binding source generator
    10. Using the options validation source generator
    11. Using the ValidateOptionsResultBuilder class
    12. Wrapping up
    13. Summary
    14. Questions
    15. Further reading
    16. Answers
  13. Logging Patterns
    1. What is logging?
    2. Writing logs
    3. Log levels
    4. Logging providers
    5. Configuring logging
    6. Structured logging
    7. Summary
    8. Questions
    9. Further reading
    10. Answers
  14. Section 3: Component Patterns
  15. Structural Patterns
    1. The Decorator design pattern
      1. Goal
      2. Design
      3. Project – Adding behaviors
        1. DecoratorA
        2. DecoratorB
      4. Project – Decorator using Scrutor
      5. Conclusion
    2. The Composite design pattern
      1. Goal
      2. Design
      3. Project – BookStore
      4. Conclusion
    3. The Adapter design pattern
      1. Goal
      2. Design
      3. Project – Greeter
      4. Conclusion
    4. The Façade design pattern
      1. Goal
      2. Design
      3. Project – The façades
        1. Opaque façade
        2. Transparent façade
        3. The program
        4. Flexibility in action
        5. Alternative façade patterns
      4. Conclusion
    5. Summary
    6. Questions
    7. Further reading
    8. Answers
  16. Behavioral Patterns
    1. The Template Method pattern
      1. Goal
      2. Design
      3. Project – Building a search machine
        1. Unit tests
      4. Conclusion
    2. The Chain of Responsibility pattern
      1. Goal
      2. Design
      3. Project – Message interpreter
      4. Conclusion
    3. Mixing the Template Method and Chain of Responsibility patterns
      1. Project – Improved message interpreter
      2. Project – A final, finer-grained design
      3. Conclusion
    4. Summary
    5. Questions
    6. Answers
  17. Operation Result Pattern
    1. The Operation Result pattern
      1. Goal
      2. Design
      3. Project – Implementing different Operation Result patterns
        1. The Program.cs file
        2. The simplest form of the Operation Result pattern
        3. A single error message
        4. Adding a return value
        5. Multiple error messages
        6. Adding message severity
        7. Sub-classes and factories
      4. Project – Registration Application
      5. Advantages and disadvantages
        1. Advantages
        2. Disadvantages
      6. Conclusion
    2. Summary
    3. Questions
    4. Further reading
    5. Answers
  18. Section 4: Application Patterns
    1. Anti-pattern – Big Ball of Mud
  19. Layering and Clean Architecture
    1. Introducing layering
      1. Classic layering model
      2. Splitting the layers
      3. Layers versus tiers versus assemblies
        1. What is a tier?
        2. What is a layer?
        3. What is an assembly?
    2. Responsibilities of the common layers
      1. Presentation
      2. Domain
        1. Rich domain model
        2. Anemic domain model
        3. The Service layer
      3. Data
        1. Overview of the Repository pattern
        2. Overview of the Unit of Work pattern
    3. Abstract layers
    4. Sharing the model
    5. Clean Architecture
    6. Implementing layering in real life
      1. To be or not to be a purist?
      2. Building a façade over a database
    7. Summary
    8. Questions
    9. Further reading
    10. Answers
  20. Object Mappers
    1. The Object Mapper pattern
      1. Goal
      2. Design
      3. Project – Mapper
      4. Conclusion
    2. Code smell – too many dependencies
      1. Overview of the Aggregate Services pattern
    3. Implementing a mapping façade
    4. Implementing a mapping service
    5. Exploring AutoMapper
      1. Project – AutoMapper
    6. Exploring Mapperly
      1. Project – Mapperly
    7. Summary
    8. Questions
    9. Further reading
    10. Answers
  21. Mediator and CQS Patterns
    1. A high-level overview of Vertical Slice Architecture
    2. The Mediator pattern
      1. Goal
      2. Design
      3. Project – Mediator (IMediator)
      4. Project – Mediator (IChatRoom)
      5. Conclusion
    3. The CQS pattern
      1. Goal
      2. Design
      3. Project – CQS
      4. Conclusion
    4. Code smell – Marker Interfaces
      1. Metadata
      2. Dependency identifier
    5. Using MediatR as a mediator
      1. Project – Clean Architecture with MediatR
    6. Summary
    7. Questions
    8. Further reading
    9. Answers
  22. Getting Started with Vertical Slice Architecture
    1. Vertical Slice Architecture
      1. What are the advantages and disadvantages?
        1. Advantages
        2. Disadvantages
        3. Downsides or upsides?
      2. Project – Vertical Slice Architecture
        1. Project organization
        2. Exploring a feature
        3. Testing
      3. Continuing your journey – a few tips and tricks
      4. Agile and DevOps synergy
      5. Conclusion
    2. Summary
    3. Questions
    4. Further reading
    5. Answers
  23. Request-EndPoint-Response (REPR)
    1. The Request-EndPoint-Response (REPR) pattern
      1. Goal
      2. Design
      3. Project – SimpleEndpoint
        1. Feature: ShuffleText
        2. Feature: RandomNumber
        3. Feature: UpperCase
      4. Conclusion
    2. An e-commerce application—a slice of the real-world
      1. Assembling our stack
      2. Dissecting the code structure
      3. Exploring the shopping basket
        1. AddItem feature
      4. Managing exception handling
        1. Creating an exception handler middleware
        2. Exception handling using ExceptionMapper
        3. Leveraging exceptions to propagate errors
      5. Gray-box testing
        1. AddItemTest
    3. Summary
    4. Questions
    5. Further reading
    6. Answers
  24. Introduction to Microservices Architecture
    1. What are microservices?
      1. Cohesive unit of business
      2. Ownership of data
      3. Microservice independence
    2. An introduction to Event-Driven Architecture
      1. Types of events
        1. Domain events
        2. Integration events
        3. Application events
        4. Enterprise events
        5. Getting started with message queues
        6. Overview of the Publish-Subscribe pattern
      2. Message brokers
      3. Overview of the Event Sourcing pattern
        1. Example
        2. Conclusion
      4. Introducing Gateway patterns
      5. Overview of the Gateway Routing pattern
      6. Overview of the Gateway Aggregation pattern
      7. Overview of the Backend for Frontend pattern
      8. Mixing and matching gateways
      9. Conclusion
    3. Project – BFF
      1. Layering APIs
        1. Advantages of a layered API design
        2. Disadvantages of a layered API design
      2. Running the microservices
        1. Manually starting the projects
        2. Using Docker Compose to run the projects
        3. Briefly testing the services
      3. Creating typed HTTP clients using Refit
      4. Creating a service that serves the current customer
      5. Features
        1. Fetching the catalog
        2. Fetching the shopping cart
        3. Managing the shopping cart
      6. Conclusion
    4. Revisiting the CQRS pattern
      1. Advantages and potential risks
        1. Benefits of the CQRS pattern
        2. Potential risks of using the CQRS pattern
      2. Conclusion
    5. Overview of the Microservice Adapter pattern
      1. Adapting an existing system to another
      2. Decommissioning a legacy application
      3. Adapting an event broker to another
      4. Conclusion
    6. Summary
    7. Questions
    8. Further reading
    9. Answers
  25. Modular Monolith
    1. What is a Modular Monolith?
      1. What are traditional monoliths?
      2. What are microservices?
      3. Advantages of Modular Monoliths
      4. Key components of a Modular Monolith
    2. Implementing a Modular Monolith
      1. Planning the project
        1. Analyzing the domain
        2. Identifying the modules
        3. Identifying the interactions between modules
      2. Defining our stack
        1. The module structure
        2. The URI space
        3. The data space
        4. The message broker
    3. Project – Modular Monolith
      1. Sending events from the catalog module
      2. Consuming the events from the basket module
      3. Inside the aggregator
      4. Exploring the REST API HttpClient
      5. Sending HTTP requests to the API
      6. Validating the existence of a product
    4. Transitioning to microservices
    5. Challenges and pitfalls
    6. Summary
    7. Questions
    8. Further reading
    9. Answers
    10. An end is simply a new beginning
  26. Other Books You May Enjoy
  27. Index

Product information

  • Title: Architecting ASP.NET Core Applications - Third Edition
  • Author(s): Carl-Hugo Marcotte
  • Release date: March 2024
  • Publisher(s): Packt Publishing
  • ISBN: 9781805123385