{"id":79903,"date":"2026-06-19T11:40:18","date_gmt":"2026-06-19T06:10:18","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=79903"},"modified":"2026-06-19T12:05:27","modified_gmt":"2026-06-19T06:35:27","slug":"learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/","title":{"rendered":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect"},"content":{"rendered":"<h2>The Problem Story<\/h2>\n<p>Picture this. It is a Tuesday afternoon. Your product manager says: <em>&#8220;We just need to add an email field. Should be quick, right?&#8221;<\/em><\/p>\n<p>You open the codebase. The <code>User<\/code> entity imports <code>SqlConnection<\/code>. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else.<\/p>\n<p>You add the field. The ORM breaks. You fix the ORM, and three unrelated features stop working. Four hours for a twenty-minute task.<\/p>\n<blockquote><p><strong>&#8220;What if your business logic never had to care what database you used, what UI framework you picked, or what cloud you deployed to?&#8221;<\/strong><\/p><\/blockquote>\n<p>That is Onion Architecture \u2014 your business rules at the centre, infrastructure as swappable details at the edge.<\/p>\n<h2>Why Traditional Layered Architecture Fails<\/h2>\n<p>Most developers start with the classic three-tier model: <strong>UI \u2192 Business Logic \u2192 Data Layer<\/strong>. On small projects, it works. On large ones, it becomes a trap in four specific ways:<\/p>\n<ul>\n<li><strong>Tight Coupling<\/strong> \u2014 Business logic directly instantiates database classes. Swap the ORM, and every service class needs surgery.<\/li>\n<li><strong>Difficult Testing<\/strong> \u2014 To test one business rule, you need a real database running. Not because the rule touches it, but because the class containing it does.<\/li>\n<li><strong>Slow Feature Changes<\/strong> \u2014 Adding a feature in the business layer requires understanding the data layer. Teams constantly step on each other.<\/li>\n<li><strong>High Maintenance Cost<\/strong> \u2014 After 18 months, no one wants to touch the code. This is the layered architecture death spiral.<\/li>\n<\/ul>\n<pre>\/\/ The classic anti-pattern: business logic importing infrastructure\r\npublic class OrderService\r\n{\r\n    public void PlaceOrder(Order order)\r\n    {\r\n        using var connection = new SqlConnection(\"Server=...\");\r\n        \/\/ business rules mixed with database calls\r\n    }\r\n}<\/pre>\n<p><!-- INSERT IMAGE: Fig 1 \u2014 Traditional 3-Layer Architecture --><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-79897\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-1_HighRes-1024x356.jpg\" alt=\"Fig 1\" width=\"691\" height=\"240\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-1024x356.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-300x104.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-768x267.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-1536x534.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-2048x712.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-1_HighRes-624x217.jpg 624w\" sizes=\"auto, (max-width: 691px) 100vw, 691px\" \/><\/p>\n<h2><\/h2>\n<h2>The Core Insight: Inward Dependency Rule<\/h2>\n<p>Jeffrey Palermo introduced Onion Architecture in 2008. The single governing rule: <strong>dependencies always point inward.<\/strong><\/p>\n<p>Inner layers know nothing about outer layers. Outer layers adapt to inner layers \u2014 never the reverse.<\/p>\n<p>Think of a company. The CEO (Domain) sets the rules. Management (Application) executes them. Operations (Infrastructure) handles the tools. Front-of-house (Presentation) faces the world. When a new CRM is adopted, the CEO&#8217;s strategy does not change.<\/p>\n<div id=\"attachment_79898\" style=\"width: 704px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79898\" class=\" wp-image-79898\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-2_HighRes-1024x178.jpg\" alt=\"Fig 2\" width=\"694\" height=\"121\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-1024x178.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-300x52.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-768x134.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-1536x267.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-2048x356.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-2_HighRes-624x109.jpg 624w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><p id=\"caption-attachment-79898\" class=\"wp-caption-text\">Fig 2<\/p><\/div>\n<p><!-- INSERT IMAGE: Fig 2 \u2014 Dependency Direction --><\/p>\n<p>This works via the <strong>Dependency Inversion Principle<\/strong>: the Application layer defines an interface (<code>IOrderRepository<\/code>), and Infrastructure implements it. The interface lives in the inner layer. The implementation lives in the outer layer.<\/p>\n<p>&nbsp;<\/p>\n<h2>The Four Layers Explained for Everyone<\/h2>\n<p>Using a restaurant analogy: Domain = recipe book, Application = kitchen manager, Infrastructure = ingredients supplier, Presentation = waiter.<\/p>\n<h3>Domain Layer (Innermost)<\/h3>\n<p>The heart of your application: entities, value objects, domain events, pure business rules. No NuGet packages. No framework references.<\/p>\n<ul>\n<li><strong>Lives here:<\/strong> Entities, Value Objects, Domain Events, Business Rules<\/li>\n<li><strong>Never here:<\/strong> Entity Framework, HttpClient, SqlConnection<\/li>\n<\/ul>\n<h3>Application Layer<\/h3>\n<p>The use-case layer. Orchestrates the domain. Contains use cases, service interfaces, and DTOs.<\/p>\n<ul>\n<li><strong>Lives here:<\/strong> Use Cases, IRepository interfaces, DTOs, Application Services<\/li>\n<li><strong>Never here:<\/strong> EF DbContext, HTTP Controllers<\/li>\n<\/ul>\n<h3>Infrastructure Layer<\/h3>\n<p>The plumbing. Implements the interfaces defined in Application. Databases, email, file system, APIs. Completely swappable.<\/p>\n<ul>\n<li><strong>Lives here:<\/strong> SqlOrderRepository, AppDbContext, SmtpEmailService, S3FileStorage<\/li>\n<li><strong>Never here:<\/strong> Business rules<\/li>\n<\/ul>\n<h3>Presentation Layer (Outermost)<\/h3>\n<p>The entry point. Controllers, Minimal API, gRPC, Worker Services. Takes the order, passes it in, returns results. Never contains business logic.<\/p>\n<h2>The 7 Key Principles Beyond the Definition<\/h2>\n<ol>\n<li><strong>Domain-Centric Design<\/strong> \u2014 Business rules first. Database shaped to match the domain, not vice versa.<\/li>\n<li><strong>Dependency Inward Rule<\/strong> \u2014 A <code>using<\/code> statement in Domain pointing to Infrastructure is a violation.<\/li>\n<li><strong>Separation of Concerns<\/strong> \u2014 Each layer, one job. Application orchestrates; it does not calculate.<\/li>\n<li><strong>Infrastructure as External Detail<\/strong> \u2014 Application defines <code>IOrderRepository<\/code>; Infrastructure delivers <code>SqlOrderRepository<\/code>.<\/li>\n<li><strong>Testability<\/strong> \u2014 Use cases testable with nothing but mocks. No database, no HTTP, no test containers.<\/li>\n<li><strong>Maintainability<\/strong> \u2014 Swapping ORM from EF Core to Dapper: one-project change. Application and Domain untouched.<\/li>\n<li><strong>Independent Domain Layer<\/strong> \u2014 Open your domain entity. Any <code>[Key]<\/code> or EF attribute? Remove them.<\/li>\n<\/ol>\n<h3>Self-Assessment Checklist<\/h3>\n<ul>\n<li>Domain entities have zero infrastructure using statements<\/li>\n<li>All interfaces live in the Application layer<\/li>\n<li>Infrastructure references Application \u2014 not the reverse<\/li>\n<li>Domain has no third-party NuGet dependencies<\/li>\n<li>Business rules testable without a database<\/li>\n<li>Swapping the ORM only affects Infrastructure<\/li>\n<li>Presentation calls Application services, never Infrastructure directly<\/li>\n<\/ul>\n<h2>Visualising Onion Architecture<\/h2>\n<p>Fig 3: The Onion rings annotated with real class examples \u2014 Domain at centre, through Application, Infrastructure, to Presentation.<\/p>\n<p><!-- INSERT IMAGE: Fig 3 \u2014 Concentric Rings --><\/p>\n<div id=\"attachment_79899\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79899\" class=\"size-large wp-image-79899\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-3_HighRes-1024x639.jpg\" alt=\"Fig 3\" width=\"625\" height=\"390\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-1024x639.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-300x187.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-768x479.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-1536x958.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-2048x1278.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-3_HighRes-624x389.jpg 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-79899\" class=\"wp-caption-text\">Fig 3<\/p><\/div>\n<p><!-- INSERT IMAGE: Fig 4 \u2014 Request Flow --><\/p>\n<p><em>Fig 4: A single HTTP POST flowing through all four layers: Controller \u2192 UseCase \u2192 Domain \u2192 Repository \u2192 SQL Server \u2192 201 response.<\/em><\/p>\n<p><!-- INSERT IMAGE: Fig 5 \u2014 .NET Solution Structure --><\/p>\n<div id=\"attachment_79896\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79896\" class=\"size-large wp-image-79896\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig_4_HighRes-1024x223.jpg\" alt=\"Fig 4\" width=\"625\" height=\"136\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-1024x223.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-300x65.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-768x167.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-1536x334.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-2048x445.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig_4_HighRes-624x136.jpg 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-79896\" class=\"wp-caption-text\">Fig 4<\/p><\/div>\n<p><em>Fig 5: Recommended .NET solution structure \u2014 each layer as a separate project for enforced dependency rules.<\/em><\/p>\n<div id=\"attachment_79900\" style=\"width: 687px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79900\" class=\" wp-image-79900\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-5_HighRes-1024x452.jpg\" alt=\"Fig 5\" width=\"677\" height=\"299\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-1024x452.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-300x132.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-768x339.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-1536x678.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-2048x904.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-5_HighRes-624x275.jpg 624w\" sizes=\"auto, (max-width: 677px) 100vw, 677px\" \/><p id=\"caption-attachment-79900\" class=\"wp-caption-text\">Fig 5<\/p><\/div>\n<h2>Implementing It: From Concept to Code<\/h2>\n<h3>Step 1 \u2014 Domain Entity<\/h3>\n<pre>public class Order\r\n{\r\n    public Guid Id { get; private set; }\r\n    public decimal TotalAmount { get; private set; }\r\n\r\n    private Order() { }\r\n\r\n    public static Order Create(Guid customerId, decimal amount)\r\n    {\r\n        if (amount &lt;= 0) throw new DomainException(\"Amount must be positive.\");\r\n        return new Order { Id = Guid.NewGuid(), TotalAmount = amount };\r\n    }\r\n}<\/pre>\n<h3>Step 2 \u2014 Use Case in Application Layer<\/h3>\n<pre>public class PlaceOrderUseCase\r\n{\r\n    private readonly IOrderRepository _orders;\r\n    private readonly IEmailService _email;\r\n   public async Task&lt;Guid&gt; ExecuteAsync(CreateOrderDto dto)\r\n    {\r\n        var order = Order.Create(dto.CustomerId, dto.Amount);\r\n        await _orders.AddAsync(order);\r\n        await _orders.SaveChangesAsync();\r\n        await _email.SendOrderConfirmationAsync(dto.CustomerEmail, order.Id);\r\n        return order.Id;\r\n    }\r\n}<\/pre>\n<h3>Step 3 \u2014 Controller in Presentation<\/h3>\n<pre>[HttpPost]\r\npublic async Task&lt;IActionResult&gt; Create(CreateOrderDto dto)\r\n{\r\n    var orderId = await _placeOrder.ExecuteAsync(dto);\r\n    return CreatedAtAction(nameof(Create), new { id = orderId }, orderId);\r\n}<\/pre>\n<h3>Step 4 \u2014 DI Wiring (Program.cs)<\/h3>\n<pre>builder.Services.AddScoped&lt;IOrderRepository, SqlOrderRepository&gt;();\r\nbuilder.Services.AddScoped&lt;IEmailService, SmtpEmailService&gt;();\r\nbuilder.Services.AddScoped&lt;PlaceOrderUseCase&gt;();<\/pre>\n<h2>Real-World Use Cases<\/h2>\n<blockquote><p><strong>&#8220;Your business logic should outlive your framework. Onion Architecture is the insurance policy.&#8221;<\/strong><\/p><\/blockquote>\n<h3>E-Commerce<\/h3>\n<p>Discount rules, inventory, order lifecycle independent of storefront or database. Migrate from SQL Server to Cosmos DB \u2014 Domain and Application untouched.<\/p>\n<h3>Banking \/ FinTech<\/h3>\n<p>Compliance rules testable, auditable, independent of vendor SDKs. Business rules live once in the domain \u2014 regardless of web, mobile, API, or batch delivery.<\/p>\n<h3>Multi-Channel Delivery<\/h3>\n<p><!-- INSERT IMAGE: Fig 6 \u2014 Multi-Channel Delivery --><\/p>\n<p>Same Domain and Application layers powering Web API, background worker, CLI tool, and gRPC service. Only Presentation changes per channel.<\/p>\n<div id=\"attachment_79901\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79901\" class=\"size-large wp-image-79901\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-6_HighRes-1024x350.jpg\" alt=\"Fig 6\" width=\"625\" height=\"214\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-1024x350.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-300x103.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-768x263.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-1536x525.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-2048x700.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-6_HighRes-624x213.jpg 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-79901\" class=\"wp-caption-text\">Fig 6<\/p><\/div>\n<h3>Legacy Migration<\/h3>\n<p>Use the strangler fig pattern \u2014 wrap legacy code with clean interfaces, replace internals gradually. No big-bang rewrite required.<\/p>\n<h2>Onion vs Clean Architecture: The Honest Comparison<\/h2>\n<p><strong>Clean Architecture<\/strong> (Uncle Bob, 2012): conceptual principles \u2014 Entities, Use Cases, Interface Adapters, Frameworks.<\/p>\n<p><strong>Onion Architecture<\/strong> (Palermo, 2008): structural implementation \u2014 Domain, Application, Infrastructure, Presentation with inward dependency rule.<\/p>\n<table>\n<tbody>\n<tr>\n<th>Dimension<\/th>\n<th>Onion Architecture<\/th>\n<th>Clean Architecture<\/th>\n<\/tr>\n<tr>\n<td>Nature<\/td>\n<td>Structural<\/td>\n<td>Conceptual<\/td>\n<\/tr>\n<tr>\n<td>Focus<\/td>\n<td>Domain-centric<\/td>\n<td>Use-case-driven<\/td>\n<\/tr>\n<tr>\n<td>Dependency Rule<\/td>\n<td>Inward<\/td>\n<td>Inward (same)<\/td>\n<\/tr>\n<tr>\n<td>Flexibility<\/td>\n<td>Flexible naming<\/td>\n<td>Prescriptive naming<\/td>\n<\/tr>\n<tr>\n<td>Coexist?<\/td>\n<td colspan=\"2\">Yes \u2014 many teams blend both successfully<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Myth-buster:<\/strong> They are not the same thing. Onion is structural; Clean is philosophical. A well-implemented Onion Architecture satisfies most Clean Architecture principles automatically.<\/p>\n<h2>Things I Wish I Knew Before Implementing Onion Architecture<\/h2>\n<h3>Anti-Pattern 1 \u2014 Infrastructure Leaking into Domain<\/h3>\n<p><code>[Table]<\/code>, <code>[Column]<\/code>, or EF navigation properties on domain entities. Technically compiles. Architecturally fatal.<\/p>\n<pre>\/\/ WRONG\r\n[Table(\"orders\")] public class Order { [Key] public Guid Id { get; set; } }\r\n\r\n\/\/ RIGHT \u2014 EF mapping in Infrastructure, domain stays clean\r\npublic class Order { public Guid Id { get; private set; } }<\/pre>\n<h3>Anti-Pattern 2 \u2014 Anemic Domain Model<\/h3>\n<p>Entities with only getters and setters. Business rules pushed into services. Domain is hollow. Onion without a rich domain is just folder organisation.<\/p>\n<h3>Anti-Pattern 3 \u2014 Service Layer Overload<\/h3>\n<p>Use cases should be small: <code>PlaceOrderUseCase<\/code>, <code>CancelOrderUseCase<\/code>. An 800-line <code>OrderService<\/code> has too many jobs.<\/p>\n<h3>Anti-Pattern 4 \u2014 Interface for Everything<\/h3>\n<p>Interfaces earn their place when they enable mocking or multiple implementations. If a class will only ever have one implementation, the interface is noise.<\/p>\n<h3>Anti-Pattern 5 \u2014 Onion in Name Only<\/h3>\n<p>Check your <code>.csproj<\/code> files: Domain \u2192 nothing, Application \u2192 Domain only, Infrastructure \u2192 Application, API \u2192 Infrastructure + Application. Any other reference is a violation.<\/p>\n<h2>Testing Strategy in Onion Architecture<\/h2>\n<div id=\"attachment_79902\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-79902\" class=\"size-large wp-image-79902\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-7_HighRes-1024x479.jpg\" alt=\"Fig 7\" width=\"625\" height=\"292\" srcset=\"https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-1024x479.jpg 1024w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-300x140.jpg 300w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-768x359.jpg 768w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-1536x718.jpg 1536w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-2048x957.jpg 2048w, https:\/\/www.tothenew.com\/blog\/wp-content\/uploads\/2026\/05\/Fig-7_HighRes-624x292.jpg 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-79902\" class=\"wp-caption-text\">Fig 7<\/p><\/div>\n<p><!-- INSERT IMAGE: Fig 7 \u2014 Testing Pyramid --><\/p>\n<ul>\n<li><strong>Domain layer:<\/strong> Pure unit tests \u2014 no mocks needed, business rules in complete isolation<\/li>\n<li><strong>Application layer:<\/strong> Unit tests with mocked repositories \u2014 no database, no HTTP<\/li>\n<li><strong>Infrastructure layer:<\/strong> Integration tests with real DB (test containers)<\/li>\n<li><strong>Presentation layer:<\/strong> End-to-end \/ contract tests<\/li>\n<\/ul>\n<pre>\/\/ No SQL Server started. Pure business logic test.\r\n[Fact]\r\npublic async Task Execute_NegativeAmount_ThrowsDomainException()\r\n{\r\n    var useCase = new PlaceOrderUseCase(_orderRepo.Object, _email.Object);\r\n    var dto = new CreateOrderDto { Amount = -50m };\r\n    await Assert.ThrowsAsync&lt;DomainException&gt;(() =&gt; useCase.ExecuteAsync(dto));\r\n}<\/pre>\n<h3>Architecture Tests<\/h3>\n<pre>[Fact]\r\npublic void Domain_Should_Not_Reference_Infrastructure()\r\n{\r\n    var result = Types.InAssembly(typeof(Order).Assembly)\r\n        .ShouldNot().HaveDependencyOn(\"YourApp.Infrastructure\").GetResult();\r\n    result.IsSuccessful.Should().BeTrue();\r\n}<\/pre>\n<h2>The Architect&#8217;s Mental Model<\/h2>\n<p>We traced the full journey: tight coupling pain \u2192 inward dependency insight \u2192 four layers \u2192 seven principles \u2192 implementation \u2192 use cases \u2192 comparison \u2192 anti-patterns \u2192 testing.<\/p>\n<blockquote><p><strong>&#8220;Your domain should be able to run its tests with zero infrastructure. If it cannot, your architecture has a leak.&#8221;<\/strong><\/p><\/blockquote>\n<h3>Further Reading<\/h3>\n<ul>\n<li>Jeffrey Palermo&#8217;s original 2008 blog post on Onion Architecture<\/li>\n<li><em>Clean Architecture<\/em> \u2014 Robert C. Martin (2017)<\/li>\n<li><em>Domain-Driven Design<\/em> \u2014 Eric Evans<\/li>\n<li><em>Patterns of Enterprise Application Architecture<\/em> \u2014 Martin Fowler<\/li>\n<\/ul>\n<hr \/>\n<p><strong>Which layer do you think most teams get wrong first, and why?<\/strong> Share your experience in the comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &#8220;We just need to add an email field. Should be quick, right?&#8221; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add [&hellip;]<\/p>\n","protected":false},"author":2282,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":101,"footnotes":""},"categories":[5867],"tags":[2930,6490,6734,8604,7248,8603],"class_list":["post-79903","post","type-post","status-publish","format-standard","hentry","category-net","tag-architecture","tag-ddd","tag-dotnet","tag-onionarchitecture","tag-softwaredesign","tag-solid"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &quot;We just need to add an email field. Should be quick, right?&quot; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Ashish V. Spencer\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"TO THE NEW BLOG\" \/>\n\t\t<meta property=\"og:type\" content=\"blog\" \/>\n\t\t<meta property=\"og:title\" content=\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog\" \/>\n\t\t<meta property=\"og:description\" content=\"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &quot;We just need to add an email field. Should be quick, right?&quot; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:site\" content=\"@tothenew\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog\" \/>\n\t\t<meta name=\"twitter:description\" content=\"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &quot;We just need to add an email field. Should be quick, right?&quot; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#article\",\"name\":\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog\",\"headline\":\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect\",\"author\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/author\\\/ashish-spencer\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/wp-ttn-blog\\\/uploads\\\/2026\\\/05\\\/Fig-1_HighRes-1024x356.jpg\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#articleImage\"},\"datePublished\":\"2026-06-19T11:40:18+05:30\",\"dateModified\":\"2026-06-19T12:05:27+05:30\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#webpage\"},\"articleSection\":\".NET, architecture, ddd, dotnet, OnionArchitecture, SoftwareDesign, Solid\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.tothenew.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/category\\\/net\\\/#listItem\",\"name\":\".NET\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/category\\\/net\\\/#listItem\",\"position\":2,\"name\":\".NET\",\"item\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/category\\\/net\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#listItem\",\"name\":\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#listItem\",\"position\":3,\"name\":\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/category\\\/net\\\/#listItem\",\"name\":\".NET\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/#organization\",\"name\":\"TO THE NEW Blog\",\"url\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/author\\\/ashish-spencer\\\/#author\",\"url\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/author\\\/ashish-spencer\\\/\",\"name\":\"Ashish V. Spencer\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#authorImage\",\"url\":\"https:\\\/\\\/newersworld-sf-static.tothenew.net\\\/prod\\\/profilePicFolder\\\/4f53f295-a525-479e-89a9-4376cf7c1b33_7760-Ashish-V.-Spencer-PROFILEPICTURE.jpeg\",\"width\":96,\"height\":96,\"caption\":\"Ashish V. Spencer\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#webpage\",\"url\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/\",\"name\":\"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog\",\"description\":\"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: \\\"We just need to add an email field. Should be quick, right?\\\" You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/author\\\/ashish-spencer\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/author\\\/ashish-spencer\\\/#author\"},\"datePublished\":\"2026-06-19T11:40:18+05:30\",\"dateModified\":\"2026-06-19T12:05:27+05:30\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/\",\"name\":\"TO THE NEW Blog\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.tothenew.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog","description":"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: \"We just need to add an email field. Should be quick, right?\" You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add","canonical_url":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#article","name":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog","headline":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect","author":{"@id":"https:\/\/www.tothenew.com\/blog\/author\/ashish-spencer\/#author"},"publisher":{"@id":"https:\/\/www.tothenew.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/05\/Fig-1_HighRes-1024x356.jpg","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#articleImage"},"datePublished":"2026-06-19T11:40:18+05:30","dateModified":"2026-06-19T12:05:27+05:30","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#webpage"},"isPartOf":{"@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#webpage"},"articleSection":".NET, architecture, ddd, dotnet, OnionArchitecture, SoftwareDesign, Solid"},{"@type":"BreadcrumbList","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.tothenew.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog\/category\/net\/#listItem","name":".NET"}},{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog\/category\/net\/#listItem","position":2,"name":".NET","item":"https:\/\/www.tothenew.com\/blog\/category\/net\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#listItem","name":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#listItem","position":3,"name":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect","previousItem":{"@type":"ListItem","@id":"https:\/\/www.tothenew.com\/blog\/category\/net\/#listItem","name":".NET"}}]},{"@type":"Organization","@id":"https:\/\/www.tothenew.com\/blog\/#organization","name":"TO THE NEW Blog","url":"https:\/\/www.tothenew.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.tothenew.com\/blog\/author\/ashish-spencer\/#author","url":"https:\/\/www.tothenew.com\/blog\/author\/ashish-spencer\/","name":"Ashish V. Spencer","image":{"@type":"ImageObject","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#authorImage","url":"https:\/\/newersworld-sf-static.tothenew.net\/prod\/profilePicFolder\/4f53f295-a525-479e-89a9-4376cf7c1b33_7760-Ashish-V.-Spencer-PROFILEPICTURE.jpeg","width":96,"height":96,"caption":"Ashish V. Spencer"}},{"@type":"WebPage","@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#webpage","url":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/","name":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog","description":"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: \"We just need to add an email field. Should be quick, right?\" You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.tothenew.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/#breadcrumblist"},"author":{"@id":"https:\/\/www.tothenew.com\/blog\/author\/ashish-spencer\/#author"},"creator":{"@id":"https:\/\/www.tothenew.com\/blog\/author\/ashish-spencer\/#author"},"datePublished":"2026-06-19T11:40:18+05:30","dateModified":"2026-06-19T12:05:27+05:30"},{"@type":"WebSite","@id":"https:\/\/www.tothenew.com\/blog\/#website","url":"https:\/\/www.tothenew.com\/blog\/","name":"TO THE NEW Blog","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.tothenew.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"TO THE NEW BLOG","og:type":"blog","og:title":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog","og:description":"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &quot;We just need to add an email field. Should be quick, right?&quot; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add","og:url":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/","og:image":"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png","og:image:secure_url":"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png","twitter:card":"summary","twitter:site":"@tothenew","twitter:title":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect | TO THE NEW Blog","twitter:description":"The Problem Story Picture this. It is a Tuesday afternoon. Your product manager says: &quot;We just need to add an email field. Should be quick, right?&quot; You open the codebase. The User entity imports SqlConnection. Business logic calls the database in the same method. No interfaces. No tests. Everything wired to everything else. You add","twitter:image":"https:\/\/www.tothenew.com\/blog\/wp-content\/themes\/ttn\/images\/social-logo.png"},"aioseo_meta_data":{"post_id":"79903","title":null,"description":null,"keywords":[],"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":[],"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"created":"2026-05-28 18:30:38","updated":"2026-06-19 06:35:28","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.tothenew.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.tothenew.com\/blog\/category\/net\/\" title=\".NET\">.NET<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tLearn Onion Architecture as a Complete Beginner and Implement as an Architect\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.tothenew.com\/blog"},{"label":".NET","link":"https:\/\/www.tothenew.com\/blog\/category\/net\/"},{"label":"Learn Onion Architecture as a Complete Beginner and Implement as an Architect","link":"https:\/\/www.tothenew.com\/blog\/learn-onion-architecture-as-a-complete-beginner-and-implement-as-an-architect\/"}],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/79903","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/2282"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=79903"}],"version-history":[{"count":6,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/79903\/revisions"}],"predecessor-version":[{"id":80163,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/79903\/revisions\/80163"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=79903"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=79903"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=79903"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}