Create clean-architecture-dotnet-cheatsheet.html

D David Veksler ยท 1 year ago d0d5ab434b90ab4ada7e4fb25a7c5ef67e7e8b51
Parent: 5dbfddd19

1 file changed +590 โˆ’0

Diff

diff --git a/clean-architecture-dotnet-cheatsheet.html b/clean-architecture-dotnet-cheatsheet.html
new file mode 100644
index 0000000..3bd33de
--- /dev/null
+++ b/clean-architecture-dotnet-cheatsheet.html
@@ -0,0 +1,590 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <meta content="width=device-width, initial-scale=1.0" name="viewport" />
+    <title>Clean Architecture in .NET Web API: Comprehensive Cheatsheet</title>
+    <!-- SEO Meta Description -->
+    <meta content="A comprehensive cheatsheet for Clean Architecture in .NET Web API projects, covering core principles, layers (Domain, Application, Infrastructure, Presentation), project structure, C# examples, and best practices." name="description" />
+    <!-- Keywords -->
+    <meta content="Clean Architecture, .NET, Web API, ASP.NET Core, Software Architecture, Domain-Driven Design, DDD, C#, Microservices, Software Design Patterns, .NET Cheatsheet, Developer Guide" name="keywords" />
+    <!-- Canonical URL -->
+    <link href="https://cheatsheets.davidveksler.com/clean-architecture-dotnet-cheatsheet.html" rel="canonical" />
+    <!-- Favicon (using an appropriate emoji for architecture/layers) -->
+    <link href="data:image/svg+xml,&lt;svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22&gt;&lt;text y=%22.9em%22 font-size=%2290%22&gt;๐Ÿงฑ&lt;/text&gt;&lt;/svg&gt;" rel="icon"/>
+    <!-- Social Media Metadata (Open Graph) -->
+    <meta content="Clean Architecture in .NET Web API: Comprehensive Cheatsheet" property="og:title"/>
+    <meta content="Explore Clean Architecture for .NET Web API with layers, principles, C# examples, project structure, and best practices. Ideal for .NET developers and architects." property="og:description"/>
+    <meta content="website" property="og:type"/>
+    <meta content="https://cheatsheets.davidveksler.com/clean-architecture-dotnet-cheatsheet.html" property="og:url"/>
+    <meta content="https://cheatsheets.davidveksler.com/images/clean-architecture-dotnet-cheatsheet.png" property="og:image"/>
+    <meta content="Visual diagram illustrating the layers of Clean Architecture in a .NET context." property="og:image:alt"/>
+    <!-- Twitter Card Metadata -->
+    <meta content="summary_large_image" name="twitter:card"/>
+    <meta content="Clean Architecture in .NET Web API: Comprehensive Cheatsheet" name="twitter:title"/>
+    <meta content="Your go-to guide for implementing Clean Architecture in .NET Web API projects. Covers layers, code examples, best practices, and more." name="twitter:description"/>
+    <meta content="https://cheatsheets.davidveksler.com/images/clean-architecture-dotnet-cheatsheet.png" name="twitter:image"/>
+    <meta content="Illustration of Clean Architecture layers in .NET." name="twitter:image:alt"/>
+    <!-- Structured Data (JSON-LD) -->
+    <script type="application/ld+json">
+    {
+      "@context": "https://schema.org",
+      "@type": "TechArticle",
+      "headline": "Clean Architecture in .NET Web API: Comprehensive Cheatsheet",
+      "description": "A comprehensive guide to Clean Architecture in .NET Web API, detailing layers, core principles, project structure, C# examples, and best practices for developers and architects.",
+      "image": "https://cheatsheets.davidveksler.com/images/clean-architecture-dotnet-cheatsheet.png",
+      "author": {
+        "@type": "Person",
+        "name": "David Veksler (AI Generated)"
+      },
+      "publisher": {
+        "@type": "Organization",
+        "name": "David Veksler Cheatsheets",
+        "logo": {
+          "@type": "ImageObject",
+          "url": "https://cheatsheets.davidveksler.com/images/logo-placeholder.png"
+        }
+      },
+      "datePublished": "2025-06-06",
+      "dateModified": "2025-06-06",
+      "keywords": "Clean Architecture, .NET, Web API, ASP.NET Core, C#, Software Architecture, DDD, Software Design Patterns"
+    }
+    </script>
+    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
+    <link href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" rel="stylesheet"/>
+    <style>
+        :root {
+            --bs-body-bg: #f4f6f8; /* Light gray background */
+            --bs-primary: #0D47A1; /* Deep Blue for primary accent */
+            --bs-primary-dark: #002171;
+            --bs-primary-light: #5472d3;
+            --card-border-color: #d1d9e0;
+            --card-shadow-color: rgba(0, 0, 0, 0.07);
+            --text-color-main: #212529;
+            --text-color-secondary: #495057;
+            --text-color-highlight: var(--bs-primary-dark);
+            --blueprint-grid-color: rgba(13, 71, 161, 0.05);
+
+            /* Category Colors */
+            --color-core-principles: #0D47A1; /* Primary Blue */
+            --color-layers-overview: #004D40; /* Dark Teal */
+            --color-domain-layer: #1E8449;    /* Green */
+            --color-application-layer: #6A1B9A;/* Purple */
+            --color-infrastructure-layer: #A15C0D;/* Orange/Brown */
+            --color-presentation-layer: #00838F; /* Teal/Cyan */
+            --color-project-structure: #455A64; /* Blue Grey */
+            --color-best-practices: #37474F; /* Dark Slate Grey */
+
+            --current-category-color: var(--bs-primary); /* Default */
+        }
+
+        body {
+            background-color: var(--bs-body-bg);
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+            color: var(--text-color-main);
+        }
+
+        .page-header {
+            background: linear-gradient(135deg, #e3f2fd, #bbdefb); /* Light blue gradient */
+            padding: 2.5rem 1.5rem;
+            text-align: center;
+            border-bottom: 2px solid var(--bs-primary-light);
+            margin-bottom: 2rem;
+        }
+        .page-header h1 {
+            color: var(--bs-primary-dark);
+            font-weight: 600;
+            font-size: 2.5rem;
+        }
+        .page-header h1 .bi { font-size: 0.9em; vertical-align: -0.05em; margin-right: 0.4em;}
+        .page-header .lead { color: #343a40; font-size: 1.1rem; max-width: 900px; margin: auto; }
+
+        .schema-container {
+            background-color: rgba(255, 255, 255, 0.85);
+            border: 1px solid var(--card-border-color);
+            border-left: 5px solid var(--current-category-color);
+            border-radius: 8px;
+            padding: 1.5rem;
+            margin-bottom: 2.5rem;
+            box-shadow: 0 4px 12px var(--card-shadow-color);
+        }
+
+        .section-title {
+            color: var(--current-category-color);
+            margin-bottom: 1.5rem;
+            font-weight: 600;
+            font-size: 1.75rem;
+            border-bottom: 2px solid var(--current-category-color);
+            padding-bottom: 0.5rem;
+            display: flex;
+            align-items: center;
+        }
+        .section-title .bi { margin-right: 0.75rem; font-size: 1.5em; }
+
+        /* Applying category colors */
+        .section-core-principles { --current-category-color: var(--color-core-principles); }
+        .section-layers-overview { --current-category-color: var(--color-layers-overview); }
+        .section-project-structure { --current-category-color: var(--color-project-structure); }
+        .section-best-practices { --current-category-color: var(--color-best-practices); }
+
+        .info-card {
+            background: #fff;
+            border: 1px solid var(--card-border-color);
+            border-left: 4px solid var(--current-category-color); /* Uses card's specific color */
+            border-radius: 6px;
+            box-shadow: 0 3px 8px var(--card-shadow-color);
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            margin-bottom: 1.5rem;
+        }
+
+        .info-card .card-header {
+            color: #fff; background-color: var(--current-category-color); /* Uses card's specific color */
+            font-size: 1.2rem; text-align: center; margin: 0; padding: 0.8rem 0.6rem;
+            font-weight: 600; display: flex; justify-content: center; align-items: center;
+            gap: .6rem;
+            border-bottom: 1px solid var(--card-border-color);
+            border-radius: 5px 5px 0 0;
+        }
+        .info-card .card-header .bi { font-size: 1.3em; opacity: 0.9; }
+        .info-card .card-body { padding: 1.25rem; flex-grow: 1; }
+        .info-card h5 { font-weight: 600; color: var(--text-color-highlight); margin-bottom: 0.75rem; }
+        .info-card p, .info-card ul, .info-card dl { font-size: 0.95rem; color: var(--text-color-secondary); line-height: 1.6; }
+        .info-card ul { padding-left: 1.25rem; }
+        .info-card li { margin-bottom: 0.5rem; }
+        .info-card dl dt { font-weight: 600; color: var(--text-color-main); margin-top: 0.5rem; }
+        .info-card dl dd { margin-left: 1rem; margin-bottom: 0.5rem; }
+
+
+        /* Card-specific colors */
+        .card-core-philosophy { --current-category-color: var(--color-core-principles); }
+        .card-when-to-use { --current-category-color: var(--color-core-principles); }
+        .card-domain-layer { --current-category-color: var(--color-domain-layer); }
+        .card-application-layer { --current-category-color: var(--color-application-layer); }
+        .card-infrastructure-layer { --current-category-color: var(--color-infrastructure-layer); }
+        .card-presentation-layer { --current-category-color: var(--color-presentation-layer); }
+        .card-project-structure { --current-category-color: var(--color-project-structure); }
+        .card-best-practices { --current-category-color: var(--color-best-practices); }
+
+
+        .details-toggle {
+            font-size: 0.9rem;
+            padding: 0.4rem 0.8rem; color: var(--bs-primary);
+            border: 1px solid var(--bs-primary); background-color: transparent;
+            transition: background-color 0.2s ease, color 0.2s ease;
+            display: inline-flex; align-items: center; gap: 0.3em;
+            border-radius: 4px; margin-top: 1rem;
+        }
+        .details-toggle:hover { background-color: var(--bs-primary); color: white; }
+        .details-toggle .bi { transition: transform 0.2s ease-in-out; }
+        .details-toggle[aria-expanded="true"] .bi { transform: rotate(180deg); }
+
+        .collapse-content {
+            font-size: 0.9rem;
+            border-top: 1px solid #e0e0e0;
+            padding-top: 1rem; margin-top: 1rem;
+            background-color: #fdfdff; /* Slightly off-white for contrast */
+            padding: 1rem; border-radius: 4px;
+        }
+        .collapse-content h6 { font-weight: 600; color: var(--text-color-highlight); margin-top: 0.8rem; margin-bottom: 0.4rem; font-size: 1rem; }
+        .collapse-content ul { padding-left: 1.2rem; margin-bottom: 0.8rem; }
+        .collapse-content li { margin-bottom: 0.4rem; font-size: 0.9rem; }
+        .collapse-content code {
+            font-size: 0.85em;
+            color: #c7254e; /* Bootstrap's code color */
+            background-color: #f9f2f4; /* Bootstrap's code background */
+            padding: 0.2em 0.4em;
+            border-radius: 3px;
+            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+        }
+        .collapse-content pre {
+            background-color: #282c34; /* Dark background for code blocks */
+            color: #abb2bf; /* Light text color for dark background */
+            padding: 1em;
+            border-radius: 6px;
+            overflow-x: auto;
+            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+            font-size: 0.875em;
+            line-height: 1.45;
+        }
+        .collapse-content pre code {
+            background-color: transparent;
+            color: inherit;
+            padding: 0;
+            border-radius: 0;
+        }
+
+        .term {
+            font-weight: 600; color: var(--bs-primary-dark);
+            background-color: var(--bs-primary-light);
+            padding: 0.15em 0.4em; border-radius: 4px; cursor: help;
+            border: 1px solid var(--bs-primary);
+        }
+        a { color: var(--bs-primary); text-decoration: none; }
+        a:hover { color: var(--bs-primary-dark); text-decoration: underline; }
+
+        footer {
+            text-align: center;
+            padding: 2rem 0;
+            margin-top: 2rem;
+            background-color: #e9ecef;
+            color: var(--text-color-secondary);
+            font-size: 0.9rem;
+            border-top: 1px solid var(--card-border-color);
+        }
+        footer a { color: var(--bs-primary); }
+        footer a:hover { color: var(--bs-primary-dark); }
+
+        @media print {
+            body { font-size: 10pt; background-color: #fff; }
+            .page-header, footer, .details-toggle { display: none; }
+            .schema-container { border: 1px solid #ccc; box-shadow: none; margin-bottom: 1.5rem; padding: 1rem; border-left-width: 3px; }
+            .section-title { font-size: 1.4rem; margin-bottom: 1rem; color: #000 !important; border-bottom-color: #000 !important;}
+            .info-card { box-shadow: none; border: 1px solid #ddd; border-left-width: 3px; margin-bottom: 1rem; page-break-inside: avoid; }
+            .info-card .card-header { background-color: #eee !important; color: #000 !important; font-size: 1.1rem; }
+            .collapse.show { display: block !important; } /* Ensure collapsed content is visible */
+            .collapse-content { border-top: 1px solid #eee; background-color: #fff; }
+            pre, pre code { background-color: #f8f9fa !important; color: #212529 !important; border: 1px solid #eee; white-space: pre-wrap; word-break: break-all; }
+            .term { background-color: #e9ecef; border: 1px solid #ced4da; color: #000; }
+            a { text-decoration: none; color: #000; }
+            a[href^="http"]:after { content: " (" attr(href) ")"; font-size: 0.9em; }
+        }
+    </style>
+</head>
+<body>
+    <header class="page-header">
+        <h1><i class="bi bi-diagram-3-fill"></i> Clean Architecture in .NET Web API</h1>
+        <p class="lead">A comprehensive cheatsheet covering core principles, layer responsibilities, project structure, C# examples, and best practices for building robust and maintainable .NET Web APIs using Clean Architecture.</p>
+        <p class="text-muted small">Last Updated: <span id="lastUpdatedDate">June 6, 2025</span></p>
+    </header>
+
+    <main class="container">
+        <!-- Core Philosophy & When to Use -->
+        <div class="schema-container section-core-principles">
+            <h2 class="section-title"><i class="bi bi-journal-richtext"></i> Core Concepts</h2>
+            <div class="row">
+                <div class="col-lg-6">
+                    <div class="info-card card-core-philosophy">
+                        <div class="card-header"><i class="bi bi-key-fill"></i> Core Philosophy</div>
+                        <div class="card-body">
+                            <ul>
+                                <li><strong><span class="term" data-bs-toggle="tooltip" title="Source code dependencies must only point inwards. Inner layers (e.g., Domain) should not know anything about outer layers (e.g., Infrastructure, Presentation).">The Dependency Rule</span>:</strong> The cornerstone. Promotes independence of core business logic.</li>
+                                <li><strong><span class="term" data-bs-toggle="tooltip" title="Inner layers define interfaces that outer layers implement. This allows specific implementations (e.g., database type) to change without affecting core logic.">Abstraction</span>:</strong> Inner layers define interfaces, outer layers implement them.</li>
+                                <li><strong><span class="term" data-bs-toggle="tooltip" title="Business rules can be tested in isolation, without dependencies on UI, databases, or external services, leading to more reliable and faster tests.">Testability</span>:</strong> Business logic can be tested in isolation.</li>
+                                <li><strong><span class="term" data-bs-toggle="tooltip" title="Changes in one part of the system have minimal impact on other parts, making the system easier to evolve.">Maintainability & Flexibility</span>:</strong> Easier to evolve the system with minimal impact across layers.</li>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-lg-6">
+                    <div class="info-card card-when-to-use">
+                        <div class="card-header"><i class="bi bi-question-circle-fill"></i> When to Use Clean Architecture</div>
+                        <div class="card-body">
+                             <ul>
+                                <li><strong>Complex Business Logic:</strong> When core rules are intricate and form the primary value.</li>
+                                <li><strong>Long-Term Projects:</strong> For applications expected to evolve and be maintained.</li>
+                                <li><strong><span class="term" data-bs-toggle="tooltip" title="An approach to software development that centers the development on programming a domain model that has a rich understanding of the processes and rules of a domain.">Domain-Driven Design (DDD)</span> Alignment:</strong> When focusing on the domain model.</li>
+                                <li><strong>High Testability Requirements:</strong> When isolated testing of business logic is crucial.</li>
+                                <li><strong>Technology Independence:</strong> To defer or easily change decisions about frameworks, databases, or UI.</li>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- Layers Overview & Responsibilities -->
+        <div class="schema-container section-layers-overview">
+            <h2 class="section-title"><i class="bi bi-stack"></i> Layers Overview & Responsibilities</h2>
+            <div class="row">
+                <!-- Domain Layer -->
+                <div class="col-md-6 col-lg-6">
+                    <div class="info-card card-domain-layer">
+                        <div class="card-header"><i class="bi bi-shield-shaded"></i> Domain Layer (Core)</div>
+                        <div class="card-body">
+                            <p><strong>Purpose:</strong> Contains enterprise-wide business logic and types. Innermost layer with no dependencies on other solution layers.</p>
+                            <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#detailsDomainLayer" aria-expanded="false" aria-controls="detailsDomainLayer">
+                                Key Components <i class="bi bi-chevron-down"></i>
+                            </button>
+                            <div class="collapse collapse-content" id="detailsDomainLayer">
+                                <h6>Key Components:</h6>
+                                <ul>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Core business objects with an identity, encapsulating business logic and data (e.g., Order, Product).">Entities</span>:</strong> Core business objects with identity and logic.
+                                        <pre><code class="language-csharp">// Domain/Entities/Product.cs
+public class Product
+{
+    public Guid Id { get; private set; }
+    public string Name { get; private set; }
+    public decimal Price { get; private set; }
+
+    // Constructor and methods with business logic...
+    public Product(Guid id, string name, decimal price) { /* ... validation ... */ }
+    public void UpdatePrice(decimal newPrice) { /* ... logic ... */ }
+}</code></pre>
+                                    </li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Immutable objects representing descriptive aspects of the domain (e.g., Address, Money), identified by their attributes.">Value Objects</span>:</strong> Immutable descriptive aspects (e.g., Address).</li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="A cluster of domain objects (entities, value objects) treated as a single unit, with an aggregate root entity.">Aggregates</span>:</strong> Clusters of domain objects treated as a unit.</li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Operations that don't naturally belong to a single entity, often involving multiple entities.">Domain Services</span>:</strong> Logic not fitting a single entity.</li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Abstractions for data persistence, defined in Domain but implemented in Infrastructure (e.g., IProductRepository).">Repository Interfaces</span>:</strong> Data access abstractions.
+                                        <pre><code class="language-csharp">// Domain/Interfaces/IProductRepository.cs
+public interface IProductRepository
+{
+    Task&lt;Product?&gt; GetByIdAsync(Guid id);
+    Task AddAsync(Product product);
+    // ... other methods
+}</code></pre>
+                                    </li>
+                                    <li><strong>Domain Events:</strong> Represent significant occurrences.</li>
+                                    <li><strong>Custom Domain Exceptions:</strong> Signal domain rule violations.</li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- Application Layer -->
+                <div class="col-md-6 col-lg-6">
+                    <div class="info-card card-application-layer">
+                        <div class="card-header"><i class="bi bi-arrows-move"></i> Application Layer</div>
+                        <div class="card-body">
+                            <p><strong>Purpose:</strong> Contains application-specific business logic. Orchestrates use cases, interacting with Domain and Infrastructure (via interfaces).</p>
+                             <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#detailsApplicationLayer" aria-expanded="false" aria-controls="detailsApplicationLayer">
+                                Key Components <i class="bi bi-chevron-down"></i>
+                            </button>
+                            <div class="collapse collapse-content" id="detailsApplicationLayer">
+                                <h6>Key Components:</h6>
+                                <ul>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Classes that implement specific application operations, often as CQRS Commands and Queries (e.g., CreateProductCommandHandler).">Use Cases/Interactors/Services</span>:</strong> Application operations.
+                                        <pre><code class="language-csharp">// Application/Products/Commands/CreateProductCommand.cs
+public record CreateProductCommand(string Name, decimal Price) : IRequest&lt;Guid&gt;;
+
+// Application/Products/Handlers/CreateProductCommandHandler.cs
+public class CreateProductCommandHandler : IRequestHandler&lt;CreateProductCommand, Guid&gt;
+{
+    private readonly IProductRepository _productRepository;
+    // ...
+    public async Task&lt;Guid&gt; Handle(CreateProductCommand request, CancellationToken ct)
+    {
+        var product = new Product(Guid.NewGuid(), request.Name, request.Price);
+        await _productRepository.AddAsync(product);
+        // await _unitOfWork.SaveChangesAsync(ct);
+        return product.Id;
+    }
+}</code></pre>
+                                    </li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Simple objects used to transfer data between layers, especially Application and Presentation. Avoid exposing domain entities directly.">Data Transfer Objects (DTOs)</span>:</strong> Data carriers between layers.</li>
+                                    <li><strong>Interfaces for Infrastructure Services:</strong> Abstractions for external concerns (e.g., `IEmailSender`).</li>
+                                    <li><strong>Validation Logic:</strong> Input data validation (e.g., using <span class="term" data-bs-toggle="tooltip" title="A popular .NET library for creating strongly-typed validation rules.">FluentValidation</span>).</li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="Command Query Responsibility Segregation: A pattern that separates read (Query) and update (Command) operations for a data store.">CQRS</span>:</strong> Separates read and write operations. Often uses <span class="term" data-bs-toggle="tooltip" title="A popular in-process messaging library in .NET that helps implement Mediator and CQRS patterns.">MediatR</span>.</li>
+                                    <li><strong>Application Exceptions:</strong> For application-specific errors.</li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- Infrastructure Layer -->
+                <div class="col-md-6 col-lg-6">
+                    <div class="info-card card-infrastructure-layer">
+                        <div class="card-header"><i class="bi bi-hdd-network-fill"></i> Infrastructure Layer</div>
+                        <div class="card-body">
+                            <p><strong>Purpose:</strong> Handles all external concerns and technical details (databases, file systems, external APIs). Implements interfaces from Application/Domain.</p>
+                            <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#detailsInfrastructureLayer" aria-expanded="false" aria-controls="detailsInfrastructureLayer">
+                                Key Components <i class="bi bi-chevron-down"></i>
+                            </button>
+                            <div class="collapse collapse-content" id="detailsInfrastructureLayer">
+                                <h6>Key Components:</h6>
+                                <ul>
+                                    <li><strong>Data Access/Persistence:</strong> Repository implementations (e.g., using EF Core). Includes `DbContext`.
+                                        <pre><code class="language-csharp">// Infrastructure/Persistence/Repositories/ProductRepository.cs
+public class ProductRepository : IProductRepository
+{
+    private readonly ApplicationDbContext _dbContext;
+    public ProductRepository(ApplicationDbContext dbContext) {/*...*/}
+    public async Task AddAsync(Product product) {/*...*/}
+    // ... other implementations
+}</code></pre>
+                                    </li>
+                                    <li><strong>External Service Integrations:</strong> Clients for APIs, payment gateways, email.</li>
+                                    <li><strong>Caching Implementations:</strong> (e.g., Redis).</li>
+                                    <li><strong>Identity Services:</strong> Authentication/Authorization implementations.</li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- Presentation Layer -->
+                <div class="col-md-6 col-lg-6">
+                    <div class="info-card card-presentation-layer">
+                        <div class="card-header"><i class="bi bi-display-fill"></i> Presentation Layer (Web API)</div>
+                        <div class="card-body">
+                            <p><strong>Purpose:</strong> Handles user interaction (HTTP requests/responses for an API). Translates input to Application layer and presents results.</p>
+                            <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#detailsPresentationLayer" aria-expanded="false" aria-controls="detailsPresentationLayer">
+                                Key Components <i class="bi bi-chevron-down"></i>
+                            </button>
+                            <div class="collapse collapse-content" id="detailsPresentationLayer">
+                                <h6>Key Components:</h6>
+                                <ul>
+                                    <li><strong>Controllers/API Endpoints:</strong> Receive HTTP requests, delegate to Application layer.
+                                        <pre><code class="language-csharp">// Presentation/Controllers/ProductsController.cs
+[ApiController]
+[Route("api/[controller]")]
+public class ProductsController : ControllerBase
+{
+    private readonly ISender _mediator; // MediatR
+    public ProductsController(ISender mediator) {/*...*/}
+
+    [HttpPost]
+    public async Task&lt;IActionResult&gt; CreateProduct([FromBody] CreateProductCommand command)
+    {
+        var productId = await _mediator.Send(command);
+        return CreatedAtAction(nameof(GetProductById), new { id = productId }, new { id = productId });
+    }
+    // ... other endpoints
+}</code></pre>
+                                    </li>
+                                    <li><strong>Middleware:</strong> Global error handling, authentication, logging.</li>
+                                    <li><strong><span class="term" data-bs-toggle="tooltip" title="The central place in an application where dependencies are registered and configured, typically in Program.cs or Startup.cs.">Dependency Injection (DI) Setup</span>:</strong> Configuration of services (<span class="term" data-bs-toggle="tooltip" title="The single place in an application where all components are wired together.">Composition Root</span>).</li>
+                                    <li><strong>API Models/ViewModels:</strong> Models for API requests/responses.</li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- Project Structure Example -->
+        <div class="schema-container section-project-structure">
+            <h2 class="section-title"><i class="bi bi-folder2-open"></i> Project Structure Example</h2>
+            <div class="info-card card-project-structure">
+                <div class="card-header"><i class="bi bi-diagram-2"></i> Solution Structure</div>
+                <div class="card-body">
+                    <pre><code class="language-text">
+Solution.sln
+โ”œโ”€โ”€ src
+โ”‚   โ”œโ”€โ”€ Domain/ (Core.csproj - .NET Class Library)
+โ”‚   โ”‚   โ”œโ”€โ”€ Entities/
+โ”‚   โ”‚   โ”œโ”€โ”€ Interfaces/ (e.g., IRepository.cs)
+โ”‚   โ”‚   โ””โ”€โ”€ ... (ValueObjects, Enums, Exceptions, Events)
+โ”‚   โ”‚
+โ”‚   โ”œโ”€โ”€ Application/ (Application.csproj - .NET Class Library)
+โ”‚   โ”‚   โ”œโ”€โ”€ Features/ (e.g., Products, Orders)
+โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Products/
+โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Commands/
+โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Queries/
+โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ DTOs/
+โ”‚   โ”‚   โ”œโ”€โ”€ Common/
+โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Interfaces/ (e.g., IEmailSender.cs)
+โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ ... (Mappings, Behaviors)
+โ”‚   โ”‚
+โ”‚   โ”œโ”€โ”€ Infrastructure/ (Infrastructure.csproj - .NET Class Library)
+โ”‚   โ”‚   โ”œโ”€โ”€ Persistence/
+โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ DataContext/ (e.g., ApplicationDbContext.cs)
+โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ Repositories/ (e.g., ProductRepository.cs)
+โ”‚   โ”‚   โ”œโ”€โ”€ Services/ (e.g., EmailSender.cs)
+โ”‚   โ”‚
+โ”‚   โ””โ”€โ”€ Presentation/ (WebApi.csproj - ASP.NET Core Web API Project)
+โ”‚       โ”œโ”€โ”€ Controllers/
+โ”‚       โ”œโ”€โ”€ Middleware/
+โ”‚       โ””โ”€โ”€ Program.cs (DI Setup)
+โ”‚
+โ””โ”€โ”€ tests
+    โ”œโ”€โ”€ Domain.UnitTests/
+    โ”œโ”€โ”€ Application.UnitTests/
+    โ””โ”€โ”€ ... (Infrastructure.IntegrationTests, Presentation.IntegrationTests)
+                    </code></pre>
+                </div>
+            </div>
+        </div>
+
+        <!-- Best Practices & Considerations -->
+        <div class="schema-container section-best-practices">
+            <h2 class="section-title"><i class="bi bi-check2-circle"></i> Best Practices & Considerations</h2>
+            <div class="info-card card-best-practices">
+                 <div class="card-header"><i class="bi bi-lightbulb-fill"></i> Key Practices</div>
+                <div class="card-body">
+                    <ul>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A design pattern where objects receive their dependencies from an external source rather than creating them internally. Crucial for Clean Architecture.">Dependency Injection (DI)</span>:</strong> Absolutely crucial. Register dependencies in Presentation layer's `Program.cs`.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A popular library for in-process messaging that helps implement CQRS and Mediator patterns, decoupling senders from handlers.">MediatR</span>:</strong> Widely used for CQRS in Application layer.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A .NET library for creating strongly-typed validation rules, often used in Application layer for command/query validation.">FluentValidation</span>:</strong> Robust validation in Application layer.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A library for object-to-object mapping, useful for converting between Entities, DTOs, and API Models.">AutoMapper</span> (or similar):</strong> For mapping between Entities, DTOs, API Models.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A pattern that groups multiple repository operations into a single transaction, often implemented within the DbContext in the Infrastructure layer.">Unit of Work (UoW) Pattern</span>:</strong> Often in Infrastructure (e.g., `DbContext`). `IUnitOfWork` interface in Application.</li>
+                        <li><strong>Error Handling:</strong> Global error handling middleware in Presentation. Custom exceptions in Domain/Application.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A pattern in .NET for managing strongly-typed configuration settings, typically loaded from appsettings.json or environment variables.">Configuration (Options Pattern)</span>:</strong> Manage configuration via `IOptions<T>`.</li>
+                        <li><strong>Async/Await:</strong> Use thoroughly for I/O-bound operations.</li>
+                        <li><strong><span class="term" data-bs-toggle="tooltip" title="A design principle stating that a class should have only one reason to change, meaning it should have only one job or responsibility.">Single Responsibility Principle (SRP)</span>:</strong> Apply to classes and methods.</li>
+                        <li><strong>Lean Controllers:</strong> Controllers should be thin, delegating to Application layer.</li>
+                        <li><strong>Avoid Leaking Abstractions:</strong> Don't expose `IQueryable` from repositories to outer layers.</li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+    </main>
+
+    <footer>
+        <p>&copy; <span id="currentYear"></span> David Veksler Cheatsheets. Content primarily AI-generated for illustrative purposes.</p>
+        <div>
+            <a class="mx-2" href="https://www.linkedin.com/in/davidveksler/" target="_blank" title="David Veksler on LinkedIn">
+                <i class="bi bi-linkedin"></i> LinkedIn
+            </a>
+            <a class="mx-2" href="https://cheatsheets.davidveksler.com/" title="Browse All Cheatsheets">
+                <i class="bi bi-collection"></i> All Cheatsheets
+            </a>
+        </div>
+    </footer>
+
+    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
+    <script>
+        document.addEventListener('DOMContentLoaded', function () {
+            // Set current year in footer
+            const currentYearSpan = document.getElementById('currentYear');
+            if (currentYearSpan) {
+                currentYearSpan.textContent = new Date().getFullYear();
+            }
+            // Set last updated date
+            const lastUpdatedDateSpan = document.getElementById('lastUpdatedDate');
+             if (lastUpdatedDateSpan) {
+                // Format today's date as Month Day, Year
+                const today = new Date();
+                const options = { year: 'numeric', month: 'long', day: 'numeric' };
+                lastUpdatedDateSpan.textContent = today.toLocaleDateString('en-US', options);
+            }
+
+
+            // Initialize tooltips
+            var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
+            var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
+                return new bootstrap.Tooltip(tooltipTriggerEl, {
+                    boundary: document.body, // Attempt to make tooltips less likely to be cut off
+                    html: true // Allow HTML in tooltips if needed
+                });
+            });
+
+            // Handle collapse icon changes
+            const collapseElements = document.querySelectorAll('.collapse');
+            collapseElements.forEach(collapseEl => {
+                const button = document.querySelector(`.details-toggle[data-bs-target="#${collapseEl.id}"]`);
+                if (button) {
+                    const iconEl = button.querySelector('.bi');
+                    const updateIconState = () => {
+                        if (collapseEl.classList.contains('show')) {
+                            iconEl.classList.remove('bi-chevron-down');
+                            iconEl.classList.add('bi-chevron-up');
+                        } else {
+                            iconEl.classList.remove('bi-chevron-up');
+                            iconEl.classList.add('bi-chevron-down');
+                        }
+                    };
+                    updateIconState(); // Initial state
+                    collapseEl.addEventListener('show.bs.collapse', updateIconState);
+                    collapseEl.addEventListener('hide.bs.collapse', updateIconState);
+                }
+            });
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file