Update clean-architecture-dotnet.html

D David Veksler ยท 1 year ago bbbdf41ad4a8b09b55e922c9c841197d74f01371
Parent: a3a50e32e

1 file changed +195 โˆ’41

Diff

diff --git a/clean-architecture-dotnet.html b/clean-architecture-dotnet.html
index 9d2cc84..86ea5b2 100644
--- a/clean-architecture-dotnet.html
+++ b/clean-architecture-dotnet.html
@@ -1,21 +1,20 @@
 <!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, explaining its need, core principles, layers, C# examples, project structure, and best practices.." name="description"/>
+<meta content="A comprehensive cheatsheet for Clean Architecture in .NET Web API projects, explaining its need, core principles, layers, C# examples, project structure, Visual Studio setup, 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, Introduction to Clean Architecture, Best Practices" name="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, Introduction to Clean Architecture, Best Practices, Visual Studio Setup" name="keywords"/>
 <!-- Canonical URL -->
 <link href="https://cheatsheets.davidveksler.com/clean-architecture-dotnet.html" rel="canonical"/>
 <!-- Favicon -->
 <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 & Twitter) -->
 <meta content="Clean Architecture in .NET Web API: Comprehensive Cheatsheet" property="og:title"/>
-<meta content="Why use Clean Architecture? Explore its benefits, principles, layers, and implementation in .NET Web API. Includes C# examples and best practices.." property="og:description"/>
+<meta content="Why use Clean Architecture? Explore its benefits, principles, layers, implementation in .NET Web API, Visual Studio setup. Includes C# examples and best practices.." property="og:description"/>
 <meta content="website" property="og:type"/>
 <meta content="https://cheatsheets.davidveksler.com/clean-architecture-dotnet.html" property="og:url"/>
 <meta content="summary_large_image" name="twitter:card"/>
@@ -25,13 +24,13 @@
       "@context": "https://schema.org",
       "@type": "TechArticle",
       "headline": "Clean Architecture in .NET Web API: Comprehensive Cheatsheet Version ",
-      "description": "A comprehensive guide to Clean Architecture in .NET Web API, starting with why it's needed, then detailing layers, core principles, project structure, C# examples, and best practices.",
+      "description": "A comprehensive guide to Clean Architecture in .NET Web API, starting with why it's needed, then detailing layers, core principles, project structure, Visual Studio setup, C# examples, and best practices.",
       "image": "https://cheatsheets.davidveksler.com/images/clean-architecture-dotnet.png",
       "author": { "@type": "Person", "name": "David Veksler (AI Generated)" },
       "publisher": { "@type": "Organization", "name": "David Veksler Cheatsheets" },
       "datePublished": "2025-06-10",
       "dateModified": "2025-06-10",
-      "keywords": "Clean Architecture Introduction, Why Clean Architecture, .NET, Web API, ASP.NET Core, C#, Software Architecture, DDD, Best Practices"
+      "keywords": "Clean Architecture Introduction, Why Clean Architecture, .NET, Web API, ASP.NET Core, C#, Software Architecture, DDD, Best Practices, Visual Studio Setup"
     }
     </script>
 <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
@@ -117,6 +116,10 @@
         .collapse-content pre { /* ... */ }
         .collapse-content pre code { /* ... */ }
         .collapse-content pre::before { /* ... */ }
+        .collapse-content ol { padding-left: 1.5rem; }
+        .collapse-content ol li { margin-bottom: 0.75rem; }
+        .collapse-content ol ul { list-style-type: disc; margin-top: 0.5rem; }
+
 
         .term { /* ... */ }
         .term:hover { /* ... */ }
@@ -127,7 +130,7 @@
         footer a:hover { /* ... */ }
 
         @media print { /* ... (styles from previous version, no changes here) ... */ }
-    </style>
+</style>
 <style>
     :root {
         --bs-body-bg: #f8f9fa;
@@ -355,6 +358,11 @@
         font-family: 'Inter', sans-serif;
         font-weight: 500;
     }
+    .collapse-content ol { padding-left: 1.5rem; margin-bottom: 1rem; list-style-type: decimal; }
+    .collapse-content ol > li { margin-bottom: 0.75rem; font-size: 0.92rem; padding-left: 0.3rem; }
+    .collapse-content ol ul { list-style-type: disc; margin-top: 0.5rem; padding-left: 1.2rem; }
+    .collapse-content ol ul li { margin-bottom: 0.4rem; font-size: 0.9rem; }
+
 
     .term {
         font-weight: 600; color: var(--bs-primary);
@@ -396,6 +404,8 @@
         .collapse-content { border-top: 1px solid #eee; background-color: #fff; }
         .collapse-content pre, .collapse-content pre code, .info-card .card-body pre, .info-card .card-body pre code { background-color: #f8f9fa !important; color: #212529 !important; border: 1px solid #eee; white-space: pre-wrap; word-break: break-all; }
         .collapse-content pre::before { display: none; }
+        .collapse-content ol, .collapse-content ol ul { list-style-type: decimal !important; }
+        .collapse-content ol ul { list-style-type: disc !important; }
         .term { background-color: #e9ecef; border: 1px solid #ced4da; color: #000; padding: 0.1em 0.2em; }
         a { text-decoration: none; color: #000; }
         a[href^="http"]:after { content: " (" attr(href) ")"; font-size: 0.9em; }
@@ -435,6 +445,10 @@
 <li><strong>Independent of Database:</strong> You can swap Oracle or SQL Server, for Mongo or BigTable. Your business rules are not bound to the database.</li>
 <li><strong>Independent of External Agencies:</strong> Your business rules don't know anything about the outside world.</li>
 <li><strong>Improved Maintainability &amp; Flexibility:</strong> Changes to external concerns have minimal impact on core logic, making the system easier to evolve and adapt.</li>
+<li><strong>Promotes a development focus on core business logic</strong>, leading to more accurate implementation.</li>
+<li><strong>Helps maintain consistent coding practices</strong>, improving application stability and security.</li>
+<li><strong>Aids in quickly adding new features</strong>, APIs, and third-party components.</li>
+<li><strong>Implements abstraction effectively.</strong></li>
 </ul>
 <h6>When is Clean Architecture Most Beneficial?</h6>
 <ul>
@@ -442,6 +456,8 @@
 <li>In long-lived projects expected to undergo evolution, maintenance, and potential technology shifts over many years.</li>
 <li>When high degrees of testability and maintainability are paramount project goals.</li>
 <li>If there's a strategic need for independence from specific external frameworks or technologies, ensuring future-proofing and adaptability.</li>
+<li>When the software needs to closely follow <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></strong> principles.</li>
+<li>When there is a need for the architecture to <strong>help enforce specific development policies and standards.</strong></li>
 </ul>
 <p class="mt-3"><strong>Important Note:</strong> Clean Architecture is not a silver bullet. It introduces a degree of initial setup complexity and requires discipline. For very simple CRUD applications or short-lived projects, the overhead might not be justified. However, for complex, evolving systems, the long-term benefits in resilience, adaptability, and reduced maintenance costs often far outweigh the upfront investment.</p>
 </div>
@@ -463,6 +479,9 @@
 <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 via Interfaces</span>:</strong> Inner layers define abstractions (interfaces); outer layers provide concrete implementations. This inverts traditional control flow for dependencies.</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.">High Testability</span>:</strong> Business logic (Domain &amp; Application layers) can be unit-tested independently of UI, database, or any external service.</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.">Enhanced Maintainability &amp; Flexibility</span>:</strong> The decoupling makes the system easier to understand, modify, and evolve. Changes in one area (e.g., database technology) are less likely to ripple through the entire codebase.</li>
+<li><strong>Focus on Core Logic:</strong> Business rules and entities are modeled within the Core (Domain) project, independent of other concerns.</li>
+<li><strong>Unidirectional Dependencies:</strong> All source code dependencies must flow inwards, towards the Core project. Outer layers depend on the Core; the Core does not depend on any outer layer.</li>
+<li><strong>Interface Definition:</strong> Inner layers (Domain, Application) define interfaces, and outer layers (Infrastructure, Presentation) implement them.</li>
 </ul>
 </div>
 </div>
@@ -483,7 +502,7 @@
 </div>
 </div>
 </div>
-<!-- Layers Overview & Responsibilities (Content is the same as previous, only wrapper styles changed) -->
+<!-- Layers Overview & Responsibilities -->
 <div class="schema-container section-layers-overview">
 <h2 class="section-title"><i class="bi bi-stack"></i> Layers Overview &amp; Responsibilities</h2>
 <div class="row">
@@ -521,8 +540,10 @@ public class Product
 <li><strong><span class="term" data-bs-toggle="tooltip" title="Immutable objects representing descriptive aspects of the domain, identified by their attributes rather than an ID (e.g., Address, Money).">Value Objects</span>:</strong> Immutable objects defined by their attributes, not an ID.</li>
 <li><strong><span class="term" data-bs-toggle="tooltip" title="A cluster of domain objects (entities and value objects) that are treated as a single unit for data changes. An Aggregate Root is the main entity that controls access to the aggregate and ensures consistency.">Aggregates</span>:</strong> Clusters of domain objects ensuring consistency within a boundary, with an Aggregate Root entity.</li>
 <li><strong><span class="term" data-bs-toggle="tooltip" title="Operations that don't naturally belong to a single entity, often coordinating logic between multiple entities or aggregates.">Domain Services</span>:</strong> Business logic that doesn't naturally fit within a single entity.</li>
-<li><strong><span class="term" data-bs-toggle="tooltip" title="Abstractions for data persistence, defined in the Domain layer but implemented in the Infrastructure layer (e.g., IProductRepository). These define the contract for how domain objects are retrieved and stored.">Repository Interfaces</span>:</strong> Abstractions for data persistence operations.
-                                        <pre><code class="language-csharp">// Domain/Interfaces/IProductRepository.cs
+<li><strong>Interfaces:</strong> Abstractions defined by the Domain layer.
+    <ul>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="Abstractions for data persistence, defined in the Domain layer but implemented in the Infrastructure layer (e.g., IProductRepository). These define the contract for how domain objects are retrieved and stored.">Repository Interfaces</span>:</strong> Contracts for data persistence operations (e.g., <code>IProductRepository</code>).
+                                                <pre><code class="language-csharp">// Domain/Interfaces/IProductRepository.cs
 public interface IProductRepository
 {
     Task&lt;Product?&gt; GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
@@ -531,9 +552,16 @@ public interface IProductRepository
     Task UpdateAsync(Product product, CancellationToken cancellationToken = default);
     Task DeleteAsync(Guid id, CancellationToken cancellationToken = default);
 }</code></pre>
+        </li>
+        <li>Other domain-specific service interfaces.</li>
+    </ul>
 </li>
 <li><strong>Domain Events:</strong> Represent something significant that happened in the domain. Used for side effects and decoupling.</li>
 <li><strong>Custom Domain Exceptions:</strong> Specific exceptions to signal violations of domain rules (e.g., `InsufficientStockException`).</li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Objects that encapsulate query logic, often used with repositories to build complex queries in a reusable and type-safe manner.">Specifications</span>:</strong> (e.g., for defining complex query criteria in a reusable way).</li>
+<li><strong>Domain-Specific <span class="term" data-bs-toggle="tooltip" title="Classes or methods responsible for validating domain objects against specific business rules or ensuring pre/post conditions (invariants) are met.">Validators/Guards</span>:</strong> For validating entities against business rules and ensuring invariants.</li>
+<li><strong>Enums:</strong> Domain-specific enumerations.</li>
+<li><strong>(Event Handlers - Domain-Level, if applicable):</strong> Handlers for domain events orchestrating logic *within* the domain.</li>
 </ul>
 </div>
 </div>
@@ -551,7 +579,9 @@ public interface IProductRepository
 <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 or workflows, often corresponding to user actions or system events. Commonly implemented using the CQRS pattern.">Use Cases/Interactors/Services</span>:</strong> (often as CQRS Commands and Queries)
+<li><strong>Use Cases/Interactors:</strong>
+    <ul>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="Objects that encapsulate an operation that modifies the system's state. They are processed by Command Handlers.">Commands</span> &amp; <span class="term" data-bs-toggle="tooltip" title="Classes responsible for processing a specific Command and executing the corresponding business logic.">Command Handlers</span>:</strong> Encapsulate operations that change the system's state.
                                         <pre><code class="language-csharp">// Application/Products/Commands/CreateProductCommand.cs
 public record CreateProductCommand(string Name, decimal Price) : IRequest&lt;Guid&gt;;
 
@@ -574,12 +604,16 @@ public class CreateProductCommandHandler : IRequestHandler&lt;CreateProductComma
         return product.Id;
     }
 }</code></pre>
+        </li>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="Objects that encapsulate a request for data. They do not modify the system's state and are processed by Query Handlers.">Queries</span> &amp; <span class="term" data-bs-toggle="tooltip" title="Classes responsible for processing a specific Query and retrieving data from the persistence layer, often mapping it to DTOs.">Query Handlers</span>:</strong> Encapsulate operations that retrieve data without altering state.</li>
+    </ul>
 </li>
 <li><strong><span class="term" data-bs-toggle="tooltip" title="Simple, typically immutable, objects used to transfer data between layers, particularly between Application and Presentation. They help decouple layers and prevent leaking domain models.">Data Transfer Objects (DTOs)</span>:</strong> For transferring data between layers.</li>
 <li><strong>Interfaces for Infrastructure Services:</strong> Abstractions for infrastructure concerns (e.g., `IEmailSender`, `IDateTimeProvider`, `IFileStorage`).</li>
-<li><strong>Validation Logic:</strong> For input data (e.g., using <span class="term" data-bs-toggle="tooltip" title="A popular .NET library for creating strongly-typed validation rules, often used with commands and DTOs.">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. Often implemented with MediatR.">CQRS</span>:</strong> Separates read and write operations. <span class="term" data-bs-toggle="tooltip" title="A popular in-process messaging library in .NET that helps implement Mediator and CQRS patterns by decoupling message senders from their handlers.">MediatR</span> is a common tool for this.</li>
+<li><strong>Validation Logic:</strong> For input data (e.g., using <span class="term" data-bs-toggle="tooltip" title="A popular .NET library for creating strongly-typed validation rules, often used with commands and DTOs.">FluentValidation</span>, often as MediatR pipeline behaviors).</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. Often implemented with MediatR.">CQRS</span> Pattern Support:</strong> Tools like <span class="term" data-bs-toggle="tooltip" title="A popular in-process messaging library in .NET that helps implement Mediator and CQRS patterns by decoupling message senders from their handlers.">MediatR</span> are commonly used here to separate commands and queries.</li>
 <li><strong>Application Exceptions:</strong> For errors specific to application logic (e.g., `ValidationException`, `NotFoundException`).</li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="In MediatR, these are classes that can intercept requests (commands/queries) and responses in the pipeline, allowing for cross-cutting concerns like logging, validation, caching, etc.">Pipeline Behaviors</span> (e.g., for MediatR):</strong> For cross-cutting concerns like validation, logging, or caching applied to use cases.</li>
 </ul>
 </div>
 </div>
@@ -597,7 +631,9 @@ public class CreateProductCommandHandler : IRequestHandler&lt;CreateProductComma
 <div class="collapse collapse-content" id="detailsInfrastructureLayer">
 <h6>Key Components:</h6>
 <ul>
-<li><strong>Data Access/Persistence:</strong> Implementations of repository interfaces (e.g., using Entity Framework Core). Includes `DbContext`.
+<li><strong>Data Access/Persistence Implementations:</strong>
+    <ul>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="Concrete classes that implement the repository interfaces defined in the Domain layer, typically using an ORM like Entity Framework Core.">Repositories</span>:</strong> Concrete implementations of repository interfaces (e.g., using Entity Framework Core).
                                         <pre><code class="language-csharp">// Infrastructure/Persistence/Repositories/ProductRepository.cs
 public class ProductRepository : IProductRepository
 {
@@ -607,9 +643,10 @@ public class ProductRepository : IProductRepository
     public async Task AddAsync(Product product, CancellationToken ct) =&gt; 
         await _dbContext.Products.AddAsync(product, ct);
     // ... etc.
-}
-
-// Infrastructure/Persistence/ApplicationDbContext.cs (EF Core example)
+}</code></pre>
+        </li>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="In Entity Framework Core, this class represents a session with the database and allows querying and saving data. It's a key part of the Unit of Work pattern.">DbContext</span>:</strong> EF Core `DbContext` class for database interaction.
+                                        <pre><code class="language-csharp">// Infrastructure/Persistence/ApplicationDbContext.cs (EF Core example)
 public class ApplicationDbContext : DbContext, IUnitOfWork // Explicitly implementing IUnitOfWork
 {
     public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options) : base(options) { }
@@ -627,11 +664,23 @@ public class ApplicationDbContext : DbContext, IUnitOfWork // Explicitly impleme
         return await base.SaveChangesAsync(cancellationToken);
     }
 }</code></pre>
+        </li>
+        <li>Database migrations.</li>
+    </ul>
+</li>
+<li><strong>External Service Integrations:</strong>
+    <ul>
+        <li>Clients for payment gateways, **<span class="term" data-bs-toggle="tooltip" title="Implementations of email sending services, e.g., using SMTP or third-party email APIs like SendGrid.">email services (Emailing Implementations)</span>**, **<span class="term" data-bs-toggle="tooltip" title="Implementations for sending SMS messages, e.g., via Twilio or other providers.">SMS services</span>**, third-party APIs.</li>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="Components that interact with cloud storage services like AWS S3, Azure Blob Storage, or Google Cloud Storage for file management.">Cloud service accessors</span>** (e.g., Azure Storage, AWS S3).</li>
+        <li><strong><span class="term" data-bs-toggle="tooltip" title="HTTP clients or SDK wrappers for consuming external APIs or microservices.">API Clients</span>** for consuming other services.</li>
+    </ul>
 </li>
-<li><strong>External Service Integrations:</strong> Clients for payment gateways, email services, third-party APIs.</li>
 <li><strong>Caching Implementations:</strong> (e.g., Redis, In-Memory).</li>
-<li><strong>Identity Services:</strong> User authentication and authorization implementations.</li>
-<li><strong>File System Access, Clock Services, Logging Implementations, etc.</strong></li>
+<li><strong>Identity Service Implementations:</strong> User authentication and authorization.</li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Classes that provide access to the file system for reading or writing files.">File System Accessors/Implementations</span>.</strong></li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Concrete implementations of date/time provider interfaces, allowing for testable date/time logic.">Clock/DateTime Service Implementations</span>.</strong></li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Concrete implementations of logging interfaces, integrating with logging frameworks like Serilog or NLog.">Logging Service Implementations</span>.</strong></li>
+<li><strong>Other Infrastructure Services:</strong> (e.g., concrete implementations of any other interfaces defined by the Application layer for infrastructure concerns).</li>
 </ul>
 </div>
 </div>
@@ -677,10 +726,13 @@ public class ProductsController : ControllerBase
     }
 }</code></pre>
 </li>
-<li><strong>Middleware:</strong> For cross-cutting concerns like global error handling, authentication, request 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. This is where layers are composed.">Dependency Injection (DI) Setup</span>:</strong> Configuration of services and their dependencies (typically in `Program.cs`). This is the "Composition Root".</li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Software components that sit in the request processing pipeline, handling cross-cutting concerns like authentication, logging, or global error handling.">Middleware</span>:</strong> For cross-cutting concerns like global error handling, authentication, request 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. This is where layers are composed.">Dependency Injection (DI) Setup / Composition Root</span>:</strong> Configuration of services and their dependencies (typically in `Program.cs`). This is the "Composition Root".</li>
 <li><strong>API Models/ViewModels:</strong> Models specific to API requests/responses. Often mapped to/from Application layer DTOs.</li>
 <li><strong>API Versioning, OpenAPI/Swagger Configuration.</strong></li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Attributes or classes that can execute code before or after controller actions or during other stages of request processing, used for concerns like authorization, caching, or custom error handling.">Filters (Action Filters, Exception Filters, etc.)</span>:</strong> For cross-cutting concerns specific to API request processing.</li>
+<li><strong><span class="term" data-bs-toggle="tooltip" title="Custom components that can transform incoming request data (e.g., from query strings, route data, or request body) into complex types expected by controller actions.">Model Binders</span>:</strong> Custom logic for binding request data to models.</li>
+<li>(Other UI-specific services if not strictly a Web API, e.g., for MVC: ViewModels, Tag Helpers - though less relevant for a pure Web API cheatsheet).</li>
 </ul>
 </div>
 </div>
@@ -688,38 +740,40 @@ public class ProductsController : ControllerBase
 </div>
 </div>
 </div>
-<!-- Project Structure Example -->
+<!-- Project Structure Example & Visual Studio Setup -->
 <div class="schema-container section-project-structure">
-<h2 class="section-title"><i class="bi bi-diagram-3-fill"></i> Project Structure Example</h2>
+<h2 class="section-title"><i class="bi bi-diagram-3-fill"></i> Project Structure & Visual Studio Setup</h2>
 <div class="info-card card-project-structure">
-<div class="card-header"><i class="bi bi-folder2-open"></i> Solution Structure</div>
+<div class="card-header"><i class="bi bi-folder2-open"></i> Typical Solution Structure</div>
 <div class="card-body">
 <p>A common way to organize projects in a .NET solution reflecting Clean Architecture:</p>
 <pre><code class="language-text">
-Solution.sln
+YourProjectSolution.sln
 โ”œโ”€โ”€ src
-โ”‚   โ”œโ”€โ”€ Domain/ (Core.csproj - .NET Class Library)
+โ”‚   โ”œโ”€โ”€ YourProject.Domain.csproj (.NET Class Library)
 โ”‚   โ”‚   โ”œโ”€โ”€ Entities/
 โ”‚   โ”‚   โ”œโ”€โ”€ Aggregates/
 โ”‚   โ”‚   โ”œโ”€โ”€ Enums/
 โ”‚   โ”‚   โ”œโ”€โ”€ Events/
 โ”‚   โ”‚   โ”œโ”€โ”€ Exceptions/
 โ”‚   โ”‚   โ”œโ”€โ”€ Interfaces/ (e.g., IProductRepository.cs)
+โ”‚   โ”‚   โ”œโ”€โ”€ Specifications/
+โ”‚   โ”‚   โ”œโ”€โ”€ Validators/Guards/
 โ”‚   โ”‚   โ””โ”€โ”€ ValueObjects/
 โ”‚   โ”‚
-โ”‚   โ”œโ”€โ”€ Application/ (Application.csproj - .NET Class Library)
+โ”‚   โ”œโ”€โ”€ YourProject.Application.csproj (.NET Class Library)
 โ”‚   โ”‚   โ”œโ”€โ”€ Features/ (Organized by feature, e.g., Products, Orders)
 โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Products/
 โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Commands/
 โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Queries/
 โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ DTOs/
 โ”‚   โ”‚   โ”œโ”€โ”€ Common/
-โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Interfaces/ (e.g., IEmailSender.cs)
-โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Behaviors/ (MediatR pipeline behaviors for validation, logging)
+โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Interfaces/ (e.g., IEmailSender.cs, IDateTimeProvider.cs)
+โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Behaviors/ (MediatR pipeline behaviors)
 โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ Mappings/ (AutoMapper profiles if used)
 โ”‚   โ”‚   โ””โ”€โ”€ Exceptions/
 โ”‚   โ”‚
-โ”‚   โ”œโ”€โ”€ Infrastructure/ (Infrastructure.csproj - .NET Class Library)
+โ”‚   โ”œโ”€โ”€ YourProject.Infrastructure.csproj (.NET Class Library)
 โ”‚   โ”‚   โ”œโ”€โ”€ Persistence/
 โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ DataContext/ (e.g., ApplicationDbContext.cs)
 โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Repositories/ (e.g., ProductRepository.cs)
@@ -728,19 +782,89 @@ Solution.sln
 โ”‚   โ”‚   โ”œโ”€โ”€ Services/ (e.g., EmailSender.cs, DateTimeProvider.cs)
 โ”‚   โ”‚   โ””โ”€โ”€ Identity/
 โ”‚   โ”‚
-โ”‚   โ””โ”€โ”€ Presentation/ (WebApi.csproj - ASP.NET Core Web API Project)
+โ”‚   โ””โ”€โ”€ YourProject.WebApi.csproj (ASP.NET Core Web API Project)
 โ”‚       โ”œโ”€โ”€ Controllers/
 โ”‚       โ”œโ”€โ”€ Middleware/
+โ”‚       โ”œโ”€โ”€ Filters/
 โ”‚       โ”œโ”€โ”€ Extensions/ (Service registration extensions)
 โ”‚       โ”œโ”€โ”€ appsettings.json
-โ”‚       โ””โ”€โ”€ Program.cs
+โ”‚       โ””โ”€โ”€ Program.cs (Composition Root)
 โ”‚
 โ””โ”€โ”€ tests
-    โ”œโ”€โ”€ Domain.UnitTests/
-    โ”œโ”€โ”€ Application.UnitTests/
-    โ”œโ”€โ”€ Infrastructure.IntegrationTests/ (May require test databases/services)
-    โ””โ”€โ”€ Presentation.IntegrationTests/ (API endpoint tests)
+    โ”œโ”€โ”€ YourProject.Domain.UnitTests.csproj
+    โ”œโ”€โ”€ YourProject.Application.UnitTests.csproj
+    โ”œโ”€โ”€ YourProject.Infrastructure.IntegrationTests.csproj
+    โ””โ”€โ”€ YourProject.Presentation.IntegrationTests.csproj
                     </code></pre>
+<button aria-controls="detailsVsSetup" aria-expanded="false" class="btn btn-sm details-toggle" data-bs-target="#detailsVsSetup" data-bs-toggle="collapse" type="button">
+                                Visual Studio Setup Guide <i class="bi bi-chevron-down"></i>
+</button>
+<div class="collapse collapse-content" id="detailsVsSetup">
+<h6>Setting up the Projects in Visual Studio:</h6>
+<ol>
+    <li><strong>Create the Solution and Presentation Layer (Web API):</strong>
+        <ul>
+            <li>Open Visual Studio.</li>
+            <li>Select "Create a new project".</li>
+            <li>Choose the "ASP.NET Core Web API" template. Click Next.</li>
+            <li>Name your project (e.g., `YourProject.WebApi`) and solution (e.g., `YourProjectSolution`). Click Next.</li>
+            <li>Choose your desired .NET framework version. Configure other settings as needed. Click Create.</li>
+            <li>This project will serve as your <strong>Presentation Layer</strong>.</li>
+        </ul>
+    </li>
+    <li><strong>Add the Domain Layer:</strong>
+        <ul>
+            <li>In Solution Explorer, right-click on the Solution (`YourProjectSolution`).</li>
+            <li>Select Add &gt; New Project...</li>
+            <li>Choose the "Class Library" template. Click Next.</li>
+            <li>Name the project `YourProject.Domain`. Click Next.</li>
+            <li>Choose the same .NET framework version as your Web API project. Click Create.</li>
+            <li>Delete the default `Class1.cs` file.</li>
+            <li>Create folders like `Entities`, `Interfaces`, `ValueObjects`, etc., as shown in the structure above.</li>
+            <li><em>Important:</em> The Domain project should NOT have project references to any other layer project in this solution.</li>
+        </ul>
+    </li>
+    <li><strong>Add the Application Layer:</strong>
+        <ul>
+            <li>Right-click on the Solution &gt; Add &gt; New Project...</li>
+            <li>Choose "Class Library". Name it `YourProject.Application`.</li>
+            <li>Ensure the .NET framework version matches. Click Create.</li>
+            <li>Delete `Class1.cs`.</li>
+            <li>Create folders like `Features`, `Common/Interfaces`, `DTOs`, etc.</li>
+            <li><strong>Add Project Reference:</strong> Right-click on the `YourProject.Application` project &gt; Add &gt; Project Reference... &gt; Check `YourProject.Domain` &gt; OK.</li>
+        </ul>
+    </li>
+    <li><strong>Add the Infrastructure Layer:</strong>
+        <ul>
+            <li>Right-click on the Solution &gt; Add &gt; New Project...</li>
+            <li>Choose "Class Library". Name it `YourProject.Infrastructure`.</li>
+            <li>Ensure the .NET framework version matches. Click Create.</li>
+            <li>Delete `Class1.cs`.</li>
+            <li>Create folders like `Persistence/DataContext`, `Repositories`, `Services`, etc.</li>
+            <li><strong>Add Project Reference:</strong> Right-click on the `YourProject.Infrastructure` project &gt; Add &gt; Project Reference... &gt; Check `YourProject.Application` &gt; OK. (The Infrastructure layer implements interfaces defined in Application and Domain).</li>
+            <li>Install necessary NuGet packages here (e.g., `Microsoft.EntityFrameworkCore`, database providers, SDKs).</li>
+        </ul>
+    </li>
+    <li><strong>Configure Presentation Layer Dependencies:</strong>
+        <ul>
+            <li>The `YourProject.WebApi` (Presentation) project orchestrates the application.</li>
+            <li><strong>Add Project References:</strong> Right-click on the `YourProject.WebApi` project &gt; Add &gt; Project Reference... &gt; Check `YourProject.Application` and `YourProject.Infrastructure` &gt; OK.</li>
+            <li>This allows the Web API to send commands/queries to the Application layer and to register services (dependency injection) from the Infrastructure layer in `Program.cs`.</li>
+        </ul>
+    </li>
+    <li><strong>Set Startup Project:</strong>
+        <ul>
+            <li>Right-click on the `YourProject.WebApi` project in Solution Explorer and select "Set as Startup Project".</li>
+        </ul>
+    </li>
+</ol>
+<p class="mt-3"><strong>Dependency Flow Reminder:</strong><br/>
+<code>Presentation (WebApi)</code> โ†’ references <code>Application</code> &amp; <code>Infrastructure</code><br/>
+<code>Infrastructure</code> โ†’ references <code>Application</code> (to implement its interfaces and use its DTOs/Domain types)<br/>
+<code>Application</code> โ†’ references <code>Domain</code><br/>
+<code>Domain</code> โ†’ references (No other project dependencies within the solution)
+</p>
+</div>
 </div>
 </div>
 </div>
@@ -794,9 +918,36 @@ Solution.sln
             }
             const lastUpdatedDateSpan = document.getElementById('lastUpdatedDate');
              if (lastUpdatedDateSpan) {
-                const today = new Date();
+                const today = new Date(); // Will reflect the current date on load
+                const jsonLdScript = document.querySelector('script[type="application/ld+json"]');
+                let datePublished = "2025-06-10"; // Default fallback from original script
+                if (jsonLdScript) {
+                    try {
+                        const jsonData = JSON.parse(jsonLdScript.textContent);
+                        datePublished = jsonData.datePublished || jsonData.dateModified || datePublished;
+                    } catch (e) {
+                        console.error("Error parsing JSON-LD: ", e);
+                    }
+                }
+                // For display, always show today's date as "Last Updated"
                 const options = { year: 'numeric', month: 'long', day: 'numeric' };
                 lastUpdatedDateSpan.textContent = today.toLocaleDateString('en-US', options);
+
+                // Update JSON-LD dateModified to today
+                if (jsonLdScript) {
+                    try {
+                        const jsonData = JSON.parse(jsonLdScript.textContent);
+                        const isoDate = today.toISOString().split('T')[0];
+                        jsonData.dateModified = isoDate;
+                        // If datePublished is in the future based on original script, set it to today as well
+                        if (new Date(jsonData.datePublished) > today) {
+                             jsonData.datePublished = isoDate;
+                        }
+                        jsonLdScript.textContent = JSON.stringify(jsonData, null, 2);
+                    } catch (e) {
+                        console.error("Error updating JSON-LD: ", e);
+                    }
+                }
             }
 
             var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
@@ -819,14 +970,17 @@ Solution.sln
                         if (collapseEl.classList.contains('show')) {
                             iconEl.classList.remove('bi-chevron-down');
                             iconEl.classList.add('bi-chevron-up');
+                            button.setAttribute('aria-expanded', 'true');
                         } else {
                             iconEl.classList.remove('bi-chevron-up');
                             iconEl.classList.add('bi-chevron-down');
+                            button.setAttribute('aria-expanded', 'false');
                         }
                     };
-                    updateIconState();
-                    collapseEl.addEventListener('show.bs.collapse', updateIconState);
-                    collapseEl.addEventListener('hide.bs.collapse', updateIconState);
+                    // Initial state based on class, then event listeners
+                    updateIconState(); 
+                    collapseEl.addEventListener('shown.bs.collapse', updateIconState);
+                    collapseEl.addEventListener('hidden.bs.collapse', updateIconState);
                 }
             });