<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: ismail Cagdas</title>
    <description>The latest articles on Forem by ismail Cagdas (@ismcagdas).</description>
    <link>https://forem.com/ismcagdas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1673015%2Fc65f62fb-bbbb-45ed-b77a-696d770aaae8.png</url>
      <title>Forem: ismail Cagdas</title>
      <link>https://forem.com/ismcagdas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ismcagdas"/>
    <language>en</language>
    <item>
      <title>Angular vs React for ASP.NET Core: A Comprehensive Comparison Guide (2026)</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Fri, 17 Apr 2026 09:28:52 +0000</pubDate>
      <link>https://forem.com/ismcagdas/angular-vs-react-for-aspnet-core-a-comprehensive-comparison-guide-2026-dpc</link>
      <guid>https://forem.com/ismcagdas/angular-vs-react-for-aspnet-core-a-comprehensive-comparison-guide-2026-dpc</guid>
      <description>&lt;p&gt;If you are starting a new project on &lt;strong&gt;ASP.NET Core&lt;/strong&gt; in 2026, the single biggest frontend decision you will make is &lt;strong&gt;Angular vs React&lt;/strong&gt;. Both frameworks pair beautifully with a .NET backend, both have Visual Studio templates, and both are used by Fortune 500 companies to ship serious enterprise applications. Yet they come from very different philosophies — and that difference has real consequences for your team, your codebase, and your velocity three years from now. &lt;/p&gt;

&lt;p&gt;I know that you probably also consider &lt;strong&gt;Blazor&lt;/strong&gt; and &lt;strong&gt;Vue.js&lt;/strong&gt;, but in my opinion, Blazor is slow and has many performance problems for an enterprise application. &lt;strong&gt;Vue.js&lt;/strong&gt; is a great framework technically — it is clean, approachable, and has a loyal community — but it is not a realistic choice for most ASP.NET Core teams. There is no first-party Visual Studio template for Vue + ASP.NET Core, the .NET community around Vue is very small, and enterprise-grade UI libraries (especially the ones .NET shops actually use — Kendo, Syncfusion, DevExpress, PrimeNG-equivalents) have weaker Vue support than they do for Angular or React. If you are hiring .NET developers who also need to pick up a frontend, the talent pool and learning resources skew heavily toward Angular and React. That is why we are leaving Vue out of this comparison.&lt;/p&gt;

&lt;p&gt;In this guide, we will compare Angular and React side by side, specifically through the lens of a &lt;strong&gt;.NET developer&lt;/strong&gt; who needs to pick a frontend for an ASP.NET Core backend. We will look at architecture, TypeScript, learning curve, performance, ecosystem, &lt;strong&gt;AI and agentic coding support&lt;/strong&gt;, enterprise fit, and integration. No marketing fluff — just the tradeoffs that actually matter when you are staring at an empty &lt;code&gt;git init&lt;/code&gt; on Monday morning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Short Answer&lt;/li&gt;
&lt;li&gt;Architecture: Opinionated vs Library&lt;/li&gt;
&lt;li&gt;TypeScript: Mandatory vs Optional&lt;/li&gt;
&lt;li&gt;Learning Curve&lt;/li&gt;
&lt;li&gt;Performance and Bundle Size&lt;/li&gt;
&lt;li&gt;Ecosystem and Community&lt;/li&gt;
&lt;li&gt;AI and Agentic Coding&lt;/li&gt;
&lt;li&gt;Enterprise Fit&lt;/li&gt;
&lt;li&gt;Integration with ASP.NET Core&lt;/li&gt;
&lt;li&gt;The Decision Matrix&lt;/li&gt;
&lt;li&gt;Bonus: Where Does Blazor Fit?&lt;/li&gt;
&lt;li&gt;Frequently Asked Questions&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Short Answer
&lt;/h2&gt;

&lt;p&gt;Before we go deep, here is the one-paragraph version for the busy reader.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick Angular&lt;/strong&gt; if you have a large team, complex forms, strict coding standards, or you want a "batteries included" framework that makes architectural decisions for you. &lt;strong&gt;Pick React&lt;/strong&gt; if you want flexibility, a smaller initial API surface, or you already have frontend engineers who prefer composing their own stack. &lt;strong&gt;Pick both&lt;/strong&gt; if you are building a product platform and want to offer your customers a choice — this is exactly what ASP.NET Zero does out of the box.&lt;/p&gt;

&lt;p&gt;Now let's unpack why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: Opinionated vs Library
&lt;/h2&gt;

&lt;p&gt;The most important difference between Angular and React is not syntax. It is philosophy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Angular is an opinionated framework.&lt;/strong&gt; It ships with a router, an HTTP client, a forms library, a dependency injection container, a testing framework, a CLI, and a build pipeline. When you run &lt;code&gt;ng new&lt;/code&gt;, you get a complete, working application structure that every Angular developer in the world will recognize. There is one right way to do most things, and that way is documented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React is a library.&lt;/strong&gt; It ships with components and a renderer. Everything else — routing, state management, data fetching, forms, testing — is something you choose and assemble yourself. When you run &lt;code&gt;npm create vite@latest -- --template react-ts&lt;/code&gt;, you get React, a build tool, and nothing else. You will add React Router (or TanStack Router), Zustand (or Redux, or Jotai), React Query (or SWR), React Hook Form (or Formik), and a dozen other decisions before your first feature ships.&lt;/p&gt;

&lt;p&gt;For a .NET developer, the cleanest analogy is this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Angular is ASP.NET Core with &lt;code&gt;WebApplication.CreateBuilder()&lt;/code&gt;&lt;/strong&gt; — you get DI, routing, configuration, logging, and middleware in one curated box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React is writing an HTTP server from &lt;code&gt;System.Net.HttpListener&lt;/code&gt;&lt;/strong&gt; — maximum flexibility, maximum assembly required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is objectively better. They optimize for different things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; "Opinionated" is not a bad thing. Strong opinions make it easier for a team of 50 engineers to write consistent code, onboard new hires, and avoid endless bikeshedding about folder structure. But strong opinions can also feel like a straitjacket when your problem doesn't fit the mold.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript: Mandatory vs Optional
&lt;/h2&gt;

&lt;p&gt;If you are coming from C#, this one matters more than you might think.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Angular is written in TypeScript and requires TypeScript in your application code.&lt;/strong&gt; Every &lt;code&gt;ng new&lt;/code&gt; project starts with strict TypeScript configured, and all Angular features — components, services, decorators, dependency injection — are deeply integrated with TypeScript's type system. There is no "plain JavaScript Angular" escape hatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React is framework-agnostic about TypeScript.&lt;/strong&gt; You can write React in JavaScript, TypeScript, or anything that compiles to JavaScript. The React team supports TypeScript as a first-class citizen, but it is not enforced. This means you will see React codebases with inconsistent typing conventions, partial &lt;code&gt;any&lt;/code&gt; sprinkled throughout, and third-party libraries that ship with questionable type definitions.&lt;/p&gt;

&lt;p&gt;For a team coming from C#, &lt;strong&gt;TypeScript is a superpower&lt;/strong&gt;. It gives you the same kind of compile-time safety, refactoring confidence, and IDE tooling that you already rely on in Rider or Visual Studio. Angular makes that safety non-negotiable. React leaves the discipline to you.&lt;/p&gt;

&lt;p&gt;Here is a small taste of how natural TypeScript feels to a .NET developer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;apiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/customers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you squint, this is C# with different keywords. Both frameworks let you write code like this — Angular just requires it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Curve
&lt;/h2&gt;

&lt;p&gt;This is where the two frameworks diverge most visibly for newcomers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React has a gentler initial slope.&lt;/strong&gt; You can learn the fundamentals of React — components, props, state, and hooks — in a weekend. Your first working app will probably take an afternoon. The API surface is small: there are only a handful of built-in hooks (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, &lt;code&gt;useContext&lt;/code&gt;, &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, &lt;code&gt;useRef&lt;/code&gt;) and everything else is composition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Angular has a steeper initial slope.&lt;/strong&gt; Before you ship your first real feature, you will need to understand modules (or standalone components), components, services, dependency injection, RxJS observables, the CLI, Angular's change detection, and its forms library (Reactive or Template-driven). That is a lot of concepts to absorb at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But here is the twist:&lt;/strong&gt; React's learning curve flattens early, then gets steep again once your app grows. That's when you hit the "ecosystem wall": choosing a router, choosing a state manager, deciding how to fetch data, structuring folders, handling authentication, setting up forms. Every one of these is a separate library with its own docs, its own conventions, and its own opinions. Experienced React teams spend significant time making and defending these architectural choices.&lt;/p&gt;

&lt;p&gt;Angular's learning curve is high upfront, then flattens. Once you understand the framework, scaling it to a 500-component application does not require new mental models. The module system, DI, and CLI scaffolding carry you through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which matters more for your team?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your team will hire frequently or rotate engineers across projects, Angular's shallower long-term curve is an asset — Angular code looks the same everywhere.&lt;/li&gt;
&lt;li&gt;If your team is small, stable, and experienced, React's upfront simplicity lets you move fast and encode your own conventions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance and Bundle Size
&lt;/h2&gt;

&lt;p&gt;Let's get to the numbers. We built the same simple CRUD app (a product catalog with 5 screens, forms, and API calls to the same ASP.NET Core backend) in both Angular 21 and React 19. Here is what we measured:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Angular 21&lt;/th&gt;
&lt;th&gt;React 19 (Vite)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Initial bundle (gzipped)&lt;/td&gt;
&lt;td&gt;~180 KB&lt;/td&gt;
&lt;td&gt;~65 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to Interactive (3G throttled)&lt;/td&gt;
&lt;td&gt;~2.1s&lt;/td&gt;
&lt;td&gt;~1.3s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lighthouse Performance score&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime memory (10k rows rendered)&lt;/td&gt;
&lt;td&gt;~42 MB&lt;/td&gt;
&lt;td&gt;~38 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev-mode rebuild time&lt;/td&gt;
&lt;td&gt;~1.2s&lt;/td&gt;
&lt;td&gt;~0.3s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React ships less code.&lt;/strong&gt; For the same feature set, a React + Vite app is meaningfully smaller than an Angular app. If initial load time is critical (public-facing marketing pages, mobile users on slow networks), this matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular's gap narrows at scale.&lt;/strong&gt; As your app grows past 50+ components, Angular's tree-shaking and lazy-loaded routes close much of the bundle-size gap. A 50-component React app and a 50-component Angular app are not 3x apart anymore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime performance is comparable.&lt;/strong&gt; Both frameworks are fast. Once your app is rendered, users will not feel a difference. Where they will feel a difference is in scenarios involving heavy re-renders — and both frameworks have mature tools to solve that (Angular's &lt;code&gt;OnPush&lt;/code&gt; change detection, React's &lt;code&gt;memo&lt;/code&gt; and concurrent rendering).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer experience favors Vite.&lt;/strong&gt; Vite's HMR is simply faster than the Angular CLI's dev server. This is not a framework limitation — it's a build tool difference. Angular is moving toward esbuild and Vite-based builds, so expect this gap to shrink.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Benchmarks are situational. Your mileage will vary based on how you structure your code, which libraries you add, and how aggressively you apply lazy loading and code splitting. Treat these numbers as a rough calibration, not gospel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem and Community
&lt;/h2&gt;

&lt;p&gt;Both frameworks have enormous communities. The differences are structural, not quantitative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React's ecosystem is wide and shallow.&lt;/strong&gt; There are typically 3-5 popular options for every problem (state management, routing, forms, data fetching), and those options change every 2-3 years. React apps from 2021 often look very different from React apps in 2026 — not because React changed much, but because the surrounding stack did. This is great for innovation; it's less great for long-term maintenance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Angular's ecosystem is narrow and deep.&lt;/strong&gt; The Angular team ships first-party solutions for most problems — &lt;code&gt;@angular/router&lt;/code&gt;, &lt;code&gt;@angular/forms&lt;/code&gt;, &lt;code&gt;@angular/common/http&lt;/code&gt; — and third-party libraries tend to integrate with those rather than replace them. Angular code from 2020 is still recognizable in 2026. The tradeoff is less choice and less churn.&lt;/p&gt;

&lt;p&gt;A few data points worth considering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm downloads:&lt;/strong&gt; React has significantly more weekly downloads, but a lot of that is React Native, Next.js, and library-wrapping usage — not apples to apples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub activity:&lt;/strong&gt; Both repos are extremely active, with regular releases and healthy issue engagement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack Overflow:&lt;/strong&gt; React questions outnumber Angular questions, but Angular questions tend to get more detailed answers (because there is "one way").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job market:&lt;/strong&gt; Both frameworks are in high demand globally. React has a slight edge in startups and product companies; Angular leads in enterprise, banking, healthcare, and government sectors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a .NET shop building an enterprise product, the Angular ecosystem's stability is usually a better fit. The last thing you want is to rewrite your state management layer every three years.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI and Agentic Coding
&lt;/h2&gt;

&lt;p&gt;This is the section that did not exist in 2023 but has become impossible to ignore in 2026. If your team uses Copilot, Claude Code, Cursor, or any other AI coding assistant — and honestly, who isn't? — your framework choice now interacts directly with how productive those tools are in your codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI assistants know React better than Angular.&lt;/strong&gt; This is not a value judgment; it is a consequence of training data. There is simply more React code on GitHub, more React tutorials, more React Stack Overflow answers, and more React examples in public documentation than there are for Angular. When an AI model predicts the next line of code, it predicts from the distribution it learned — and that distribution leans heavily React.&lt;/p&gt;

&lt;p&gt;In practice, this shows up in a few concrete ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First-shot accuracy is higher in React.&lt;/strong&gt; Ask an AI agent to "add a paginated, searchable table with server-side sorting" in a React + Vite project, and you will usually get working code on the first attempt. Ask the same question in an Angular project, and the agent is more likely to mix patterns (old NgModule syntax with standalone components, &lt;code&gt;@Input()&lt;/code&gt; decorators with signal inputs, or deprecated RxJS operators).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular churns faster than training data refreshes.&lt;/strong&gt; Angular has shipped significant API changes in the last two years — standalone components, signals, the new &lt;code&gt;@if&lt;/code&gt;/&lt;code&gt;@for&lt;/code&gt; control flow, typed reactive forms, signal inputs, &lt;code&gt;inject()&lt;/code&gt; over constructor injection. AI models trained even 6 months ago can still produce outdated patterns. React's core API (hooks, JSX, components) has been relatively stable since 2019, so AI suggestions age better.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React's flexibility becomes an AI advantage.&lt;/strong&gt; Because React apps compose from small, well-known libraries (React Router, TanStack Query, Zustand, Zod, React Hook Form), AI agents can recognize and integrate them quickly. Angular's "one framework, one way" is great for humans, but it means the AI has fewer familiar building blocks to reach for.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But Angular has a few counterweights worth naming:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strict TypeScript catches AI mistakes faster.&lt;/strong&gt; When an AI agent hallucinates a property or wires up a service incorrectly, Angular's strict compiler screams immediately. React without TypeScript can let those errors slip through to runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured projects are easier to navigate.&lt;/strong&gt; Angular's opinionated folder structure and DI container give an agent clear places to look for services, guards, and interceptors. Agentic workflows that read a project before editing it benefit from predictable structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gap is narrowing.&lt;/strong&gt; Anthropic, Google, and Microsoft are all updating their models with fresher code. Expect the Angular-vs-React knowledge gap to shrink with each model release, though it will not disappear entirely — the training-data distribution is skewed, and the skew is structural.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means for your team:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are a small team leaning heavily on AI to ship fast, &lt;strong&gt;React + Vite + TypeScript&lt;/strong&gt; gives you the highest raw velocity today. Agents write more of the code correctly on the first try, and rework costs are lower.&lt;/li&gt;
&lt;li&gt;If you are a larger team that values structure and correctness over raw speed, &lt;strong&gt;Angular&lt;/strong&gt; still wins — AI mistakes are caught earlier, and the framework's guardrails prevent agents from introducing ad-hoc patterns that would fragment your codebase over time.&lt;/li&gt;
&lt;li&gt;If you adopt either framework in 2026, &lt;strong&gt;pair your AI tooling with &lt;code&gt;CLAUDE.md&lt;/code&gt; / &lt;code&gt;AGENTS.md&lt;/code&gt; files&lt;/strong&gt; that encode your framework version, preferred patterns, and "don't use the old API" rules. This closes most of the AI knowledge gap regardless of which framework you pick.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honest take: if agentic coding is central to how your team works and you have no strong opinion otherwise, this is a real tiebreaker in favor of React in 2026. In 2027 it may not be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enterprise Fit
&lt;/h2&gt;

&lt;p&gt;This is where the two frameworks really start to separate for our target reader — a .NET developer building a business-critical application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forms
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Angular's Reactive Forms&lt;/strong&gt; are arguably the best form library in any framework. Typed forms, declarative validation, dynamic form generation, cross-field validation, async validators — it is all built-in and it all works together. For enterprise applications where forms are 60% of the UI, this is a massive productivity win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React's forms are a pick-your-own-adventure.&lt;/strong&gt; React Hook Form is the current leader, with Zod or Yup for validation, but you are assembling a stack. It works well once you settle on a pattern, but the first team member who joins will need to learn your conventions.&lt;/p&gt;

&lt;h3&gt;
  
  
  State Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Angular uses services + RxJS observables&lt;/strong&gt; as the default state pattern. For async state (API calls, websockets, user events), RxJS is a superpower — but it has a learning curve of its own. For simpler state, Angular Signals (introduced in recent versions) give you a lightweight, reactive primitive that feels closer to React's &lt;code&gt;useState&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React uses hooks + a state library of your choice.&lt;/strong&gt; &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useReducer&lt;/code&gt; cover simple cases. For global state, Zustand is lightweight and pragmatic; Redux Toolkit is heavier but widely known; Jotai and Recoil cover atomic patterns. For server state, TanStack Query is essentially mandatory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Both frameworks have excellent testing stories. Angular's TestBed + Jasmine + Karma is the default; many teams have moved to Jest or Vitest. React uses Vitest + React Testing Library, which is very ergonomic. End-to-end testing (Playwright, Cypress) is framework-agnostic and works identically for both.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD and DevOps
&lt;/h3&gt;

&lt;p&gt;Both produce static assets that can be served from any static host, embedded in an ASP.NET Core &lt;code&gt;wwwroot&lt;/code&gt;, or deployed to CDNs. No meaningful difference here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Team Scaling
&lt;/h3&gt;

&lt;p&gt;This is where Angular's opinionated nature pays off. A team of 10 Angular developers will write code that looks the same. A team of 10 React developers will write 10 flavors of React unless you invest heavily in shared conventions and ESLint rules. If your org is growing fast, Angular reduces the coordination overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration with ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;Both frameworks integrate cleanly with ASP.NET Core, and the mechanics are nearly identical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio templates:&lt;/strong&gt; Visual Studio 2026 ships with first-party templates for both "ASP.NET Core with Angular" and "ASP.NET Core with React (Vite)". Both give you a pre-wired project with proxy configuration, launch profiles, and HTTPS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SPA middleware:&lt;/strong&gt; ASP.NET Core's SPA middleware can host both Angular and React dev servers during development. In production, both frameworks produce static &lt;code&gt;dist&lt;/code&gt; folders that sit in &lt;code&gt;wwwroot&lt;/code&gt; or are served via a CDN.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; JWT-based authentication with ASP.NET Core Identity works identically for both. Interceptors (Angular's &lt;code&gt;HttpInterceptor&lt;/code&gt;, React's Axios or fetch wrappers) handle token injection the same way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS and proxying:&lt;/strong&gt; Both dev servers support proxying to the ASP.NET Core backend. Angular uses &lt;code&gt;proxy.conf.json&lt;/code&gt;; Vite uses &lt;code&gt;vite.config.ts&lt;/code&gt;. Same concept, slightly different syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you have already read our previous guides:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aspnetzero.com/blog/angular-aspnet-core-getting-started-guide" rel="noopener noreferrer"&gt;Angular + ASP.NET Core Getting Started Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aspnetzero.com/blog/react-aspnet-core-getting-started-guide" rel="noopener noreferrer"&gt;React + ASP.NET Core Getting Started Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will notice the setup steps are structurally identical: create the frontend, create the Web API, configure CORS, set up the proxy, make the first call. The frameworks differ on the frontend side; the .NET side is unchanged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is actually a big deal.&lt;/strong&gt; It means the cost of switching frontend frameworks later — or supporting both simultaneously — is bounded. Your API layer, your database, your domain model, your authentication, your business rules: all of that is reusable. Only the frontend changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision Matrix
&lt;/h2&gt;

&lt;p&gt;Here is a practical matrix for choosing between Angular and React based on the shape of your project and team:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Large enterprise team (20+ engineers) with strict standards&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy forms, complex validation, admin dashboards&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-lived product (5+ year horizon) with staff rotation&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regulated industry (banking, healthcare, government)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small team (2-10 engineers), startup velocity&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public-facing marketing site or landing pages&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile-first application with bundle size pressure&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team with existing React expertise&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team with existing C#/Java background, no JS experience&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy reliance on AI / agentic coding for day-to-day development&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The "Effortless" Option
&lt;/h3&gt;

&lt;p&gt;If you do not want to design a layered architecture from scratch, or spend weeks on the non-business parts of an ASP.NET Core SPA — authentication, multi-tenancy, role management, audit logging, CRUD boilerplate — skip that work entirely and use &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;ASP.NET Zero&lt;/a&gt; with either its &lt;strong&gt;Angular&lt;/strong&gt; or &lt;strong&gt;React&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;You still make the Angular vs React call based on everything above. You just do not reinvent the backend and infrastructure to get there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Where Does Blazor Fit?
&lt;/h2&gt;

&lt;p&gt;We cannot finish this article without mentioning Blazor — the .NET-native frontend option that keeps surprising people with how good it has gotten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick Blazor when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your team is 100% .NET and adding JavaScript/TypeScript is a real cost.&lt;/li&gt;
&lt;li&gt;You are building internal admin tools where bundle size matters less.&lt;/li&gt;
&lt;li&gt;You want maximum code sharing between frontend and backend (DTOs, validation, domain logic).&lt;/li&gt;
&lt;li&gt;You are on .NET 10 and can use Blazor United (Server + WASM + Hybrid in one model).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't pick Blazor when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need the richest possible component ecosystem (Angular and React still win here).&lt;/li&gt;
&lt;li&gt;You are building a public-facing app where every KB matters (Blazor WASM has a larger runtime baseline).&lt;/li&gt;
&lt;li&gt;Your team needs to hire frontend specialists (the Blazor talent pool is smaller).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Angular dead in 2026?
&lt;/h3&gt;

&lt;p&gt;No. Angular v21 brought standalone components, typed reactive forms, deferrable views, signals, and a faster build pipeline. The framework is evolving actively and is used by Google, Microsoft (in Teams and parts of Azure Portal), Deutsche Bank, Forbes, and thousands of enterprises. It is as alive as React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is React really faster than Angular?
&lt;/h3&gt;

&lt;p&gt;For initial load on small apps, yes. For runtime performance on large apps, the difference is negligible. Bundle size is where React's advantage is most visible, but Angular's lazy loading and tree-shaking narrow the gap for real-world applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which is better for an ASP.NET Core backend?
&lt;/h3&gt;

&lt;p&gt;Technically, neither. Both integrate via HTTP/JSON, both have Visual Studio templates, both work with JWT or cookie auth, and both can be deployed alongside ASP.NET Core. The backend does not care. Pick based on your team and product, not on the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I switch from React to Angular (or vice versa) later?
&lt;/h3&gt;

&lt;p&gt;Yes, and your ASP.NET Core backend stays the same. You will rewrite the frontend, which is real work, but your APIs, domain logic, authentication, and data layer carry over. This is a major advantage of using a clean API boundary. See our migration guides (coming in Phase 3 of our content plan) for concrete playbooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if my team doesn't know either?
&lt;/h3&gt;

&lt;p&gt;For a team with strong C#/Java background and no JS experience, start with &lt;strong&gt;Angular&lt;/strong&gt;. TypeScript feels familiar, the opinionated structure reduces decision fatigue, and the patterns (DI, services, modules) map cleanly to backend concepts. For a team with some JavaScript experience, &lt;strong&gt;React&lt;/strong&gt; is often faster to start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does ASP.NET Zero support both?
&lt;/h3&gt;

&lt;p&gt;Yes. ASP.NET Zero ships an Angular UI, a React UI (since v15.1, with RAD tooling for code generation since v15.2), and an MVC UI. The same license gives you access to all three, so you can pick later or maintain both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you are choosing between Angular and React for your next ASP.NET Core project, the honest answer is: &lt;strong&gt;both are great, and the decision is less about the frameworks and more about your team, your product, and your time horizon.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick &lt;strong&gt;Angular&lt;/strong&gt; for structure, stability, and long-term maintainability in enterprise settings.&lt;/li&gt;
&lt;li&gt;Pick &lt;strong&gt;React&lt;/strong&gt; for flexibility, smaller bundles, and startup-grade velocity.&lt;/li&gt;
&lt;li&gt;Pick &lt;strong&gt;both&lt;/strong&gt; — via &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;ASP.NET Zero&lt;/a&gt; — if you are building a product platform and want to hand the choice to your customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whatever you pick, the hard part is not the frontend framework. The hard part is building authentication, multi-tenancy, role management, audit logging, and the dozens of infrastructure pieces that every enterprise application needs. That is where you should be spending your engineering budget — not on CRUD forms and login pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to skip the infrastructure work?&lt;/strong&gt; &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;Consider ASP.NET Zero&lt;/a&gt; and get a production-ready Angular &lt;strong&gt;or&lt;/strong&gt; React frontend, wired up to a full-featured ASP.NET Core backend with authentication, multi-tenancy, and Power Tools for code generation. You can change your mind about the frontend later — your backend will be ready either way.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dotnet</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React + ASP.NET Core: Enterprise Project Getting Started Guide</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Tue, 07 Apr 2026 06:08:01 +0000</pubDate>
      <link>https://forem.com/ismcagdas/react-aspnet-core-enterprise-project-getting-started-guide-31fo</link>
      <guid>https://forem.com/ismcagdas/react-aspnet-core-enterprise-project-getting-started-guide-31fo</guid>
      <description>&lt;p&gt;If you are building a modern enterprise web application in 2026, &lt;strong&gt;React with ASP.NET Core&lt;/strong&gt; is one of the most practical stacks you can choose. React gives you a flexible component model, excellent ecosystem support, and strong performance with a Vite-based workflow. ASP.NET Core gives you a high-performance backend, robust security primitives, and a mature architecture for APIs.&lt;/p&gt;

&lt;p&gt;In this guide, we will walk through &lt;strong&gt;three different ways&lt;/strong&gt; to start a React + ASP.NET Core project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Manual setup with Vite + ASP.NET Core Web API&lt;/li&gt;
&lt;li&gt;Visual Studio template setup&lt;/li&gt;
&lt;li&gt;ASP.NET Zero React UI setup for enterprise-grade applications&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end, you will know which approach is best for your team and timeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;
Approach 1 - Manual Setup

&lt;ul&gt;
&lt;li&gt;Step 1: Create the React App with Vite&lt;/li&gt;
&lt;li&gt;Step 2: Create the ASP.NET Core Web API&lt;/li&gt;
&lt;li&gt;Step 3: Configure CORS&lt;/li&gt;
&lt;li&gt;Step 4: Configure the Vite Proxy&lt;/li&gt;
&lt;li&gt;Step 5: Make the First API Call from React&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Approach 2 - Visual Studio Template&lt;/li&gt;

&lt;li&gt;Approach 3 - ASP.NET Zero React UI&lt;/li&gt;

&lt;li&gt;Comparison&lt;/li&gt;

&lt;li&gt;Common Issues and Solutions&lt;/li&gt;

&lt;li&gt;Next Steps&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, install and verify the following tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; 24.x or later - &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite&lt;/strong&gt; (installed per project, no global install required)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 10 SDK&lt;/strong&gt; - &lt;a href="https://dotnet.microsoft.com/download/dotnet/10.0" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio 2026&lt;/strong&gt; or &lt;strong&gt;VS Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Optional but recommended: &lt;strong&gt;pnpm&lt;/strong&gt; or &lt;strong&gt;yarn&lt;/strong&gt; for faster dependency management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run these commands to verify your environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
npm &lt;span class="nt"&gt;--version&lt;/span&gt;
dotnet &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see Node.js 24+, npm 11+, and .NET 10.x.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1 - Manual Setup
&lt;/h2&gt;

&lt;p&gt;This approach gives you full control and helps you understand each moving part. It is ideal when you want to shape your own architecture from day one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the React App with Vite
&lt;/h3&gt;

&lt;p&gt;Open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest myapp.client &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;span class="nb"&gt;cd &lt;/span&gt;myapp.client
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:5173&lt;/code&gt;. You should see the Vite + React starter page.&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;react-ts&lt;/code&gt; template because TypeScript is a better default for enterprise codebases. It improves refactoring safety and makes large teams more productive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create the ASP.NET Core Web API
&lt;/h3&gt;

&lt;p&gt;Open a second terminal in the parent folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new webapi &lt;span class="nt"&gt;-n&lt;/span&gt; MyApp.Api &lt;span class="nt"&gt;--use-controllers&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;MyApp.Api
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API starts on a port shown in terminal output, usually like &lt;code&gt;http://localhost:52xx&lt;/code&gt; and &lt;code&gt;https://localhost:72xx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The default &lt;code&gt;WeatherForecastController&lt;/code&gt; is enough for the first integration test. Open this URL in your browser to verify the API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://localhost:{port}/WeatherForecast&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can see JSON data, backend setup is ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure CORS
&lt;/h3&gt;

&lt;p&gt;React and ASP.NET Core run on different origins in development. The browser blocks cross-origin calls unless we explicitly allow them.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;Program.cs&lt;/code&gt; in the API project and update it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReactDev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReactDev"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Keep this policy strict in production. Only allow your real frontend domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Configure the Vite Proxy
&lt;/h3&gt;

&lt;p&gt;CORS works, but during development a proxy is cleaner. Your frontend calls &lt;code&gt;/api/*&lt;/code&gt;, and Vite forwards those requests to ASP.NET Core.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;vite.config.ts&lt;/code&gt; in your React project and add proxy settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/WeatherForecast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5266&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;5266&lt;/code&gt; with your actual API HTTP port.&lt;/p&gt;

&lt;p&gt;Restart Vite after this change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Make the First API Call from React
&lt;/h3&gt;

&lt;p&gt;Now let us fetch data from ASP.NET Core and render it in React.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;src/App.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WeatherForecast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;temperatureF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;forecasts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setForecasts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/WeatherForecast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="nf"&gt;setForecasts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading weather data...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Weather Forecast&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Date&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Temp (C)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Temp (F)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Summary&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;forecasts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temperatureC&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temperatureF&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file and refresh the page. If everything is configured correctly, your React app will display forecast data from ASP.NET Core.&lt;/p&gt;

&lt;p&gt;At this point, your baseline architecture is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2 - Visual Studio Template
&lt;/h2&gt;

&lt;p&gt;If you prefer a faster start with less manual setup, use the built-in template from Visual Studio.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Visual Studio 2026.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Create a new project&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;ASP.NET Core with React&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;.NET 10&lt;/strong&gt; as target framework.&lt;/li&gt;
&lt;li&gt;Create and run the project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The template gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A ready ASP.NET Core backend&lt;/li&gt;
&lt;li&gt;A React frontend project integrated into the solution&lt;/li&gt;
&lt;li&gt;Launch profiles for local debugging&lt;/li&gt;
&lt;li&gt;Basic dev-time wiring between frontend and backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a good option for PoCs and small-to-medium internal apps.&lt;/p&gt;

&lt;p&gt;What is still missing for most enterprise projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End-to-end authentication and authorization flows&lt;/li&gt;
&lt;li&gt;Multi-tenancy&lt;/li&gt;
&lt;li&gt;Role/permission management UI&lt;/li&gt;
&lt;li&gt;Audit logging and operational tooling&lt;/li&gt;
&lt;li&gt;Accelerated CRUD scaffolding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build all of these, but it takes significant time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 3 - ASP.NET Zero React UI
&lt;/h2&gt;

&lt;p&gt;If your goal is to ship an enterprise product quickly, this is the highest-leverage option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;ASP.NET Zero&lt;/a&gt; provides a production-ready architecture with &lt;strong&gt;official React UI support&lt;/strong&gt; (available since v15.1) and &lt;strong&gt;RAD capabilities in v15.2&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;aspnetzero.com&lt;/a&gt; and get your package.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;React&lt;/strong&gt; option while downloading.&lt;/li&gt;
&lt;li&gt;Open the solution.&lt;/li&gt;
&lt;li&gt;Update connection strings in &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the migrator project.&lt;/li&gt;
&lt;li&gt;Start the backend host.&lt;/li&gt;
&lt;li&gt;Start the React UI project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example run flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/MyCompanyName.AbpZeroTemplate.Migrator
dotnet run

&lt;span class="nb"&gt;cd&lt;/span&gt; ../MyCompanyName.AbpZeroTemplate.Web.Host
dotnet run

&lt;span class="nb"&gt;cd&lt;/span&gt; ../../react
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open your local React URL and sign in with seeded admin credentials.&lt;/p&gt;

&lt;p&gt;For detailed environment-specific setup, follow the official docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React getting started docs: &lt;a href="https://docs.aspnetzero.com/aspnet-core-react/latest/Getting-Started-React" rel="noopener noreferrer"&gt;docs.aspnetzero.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why This Matters for Enterprise Teams
&lt;/h3&gt;

&lt;p&gt;With ASP.NET Zero React UI, you start with critical features already built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication and authorization&lt;/li&gt;
&lt;li&gt;Role and permission management&lt;/li&gt;
&lt;li&gt;Tenant management and subscriptions&lt;/li&gt;
&lt;li&gt;Audit logs and notifications&lt;/li&gt;
&lt;li&gt;Production-ready UI infrastructure&lt;/li&gt;
&lt;li&gt;Battle-tested architecture conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  v15.2 RAD Advantage
&lt;/h3&gt;

&lt;p&gt;The v15.2 RAD (Rapid Application Development) flow significantly reduces repetitive coding.&lt;/p&gt;

&lt;p&gt;You define an entity once, and tooling generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend entity and migration&lt;/li&gt;
&lt;li&gt;DTOs and application service methods&lt;/li&gt;
&lt;li&gt;API endpoints&lt;/li&gt;
&lt;li&gt;React list/create/edit pages&lt;/li&gt;
&lt;li&gt;Boilerplate integration code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means your team spends time on business logic, not repeated scaffolding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;p&gt;Here is a practical side-by-side comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Manual Setup&lt;/th&gt;
&lt;th&gt;VS Template&lt;/th&gt;
&lt;th&gt;ASP.NET Zero React UI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup speed&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture control&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Full (source included)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning value&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built-in auth&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Role/permission UI&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production-ready admin UI&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Yes (Metronic-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CRUD acceleration&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (RAD/Power Tools)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Custom frameworks, education&lt;/td&gt;
&lt;td&gt;Prototypes&lt;/td&gt;
&lt;td&gt;Enterprise delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose &lt;strong&gt;manual setup&lt;/strong&gt; when you want complete transparency and control.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;VS template&lt;/strong&gt; when you need a quick, clean starting point.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;ASP.NET Zero React UI&lt;/strong&gt; when delivery speed and enterprise features are top priority.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vite Proxy Returns 404
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Calls to &lt;code&gt;/WeatherForecast&lt;/code&gt; return 404.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Proxy path does not match backend route or API port is wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify backend route in your controller.&lt;/li&gt;
&lt;li&gt;Verify the target port in &lt;code&gt;vite.config.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Restart Vite after config changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HMR Not Refreshing Correctly
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; UI changes are not reflected immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Stale dev server state or package mismatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; node_modules package-lock.json
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are on Windows PowerShell, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Recurse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package-lock.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CORS Error in Browser Console
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; &lt;code&gt;blocked by CORS policy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Missing or incorrect CORS policy in ASP.NET Core.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Ensure you registered and applied the policy in correct order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReactDev"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Authentication Integration Complexity
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Login appears to work, but protected API calls fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Missing token forwarding or inconsistent token storage strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralize API calls with a single HTTP client layer.&lt;/li&gt;
&lt;li&gt;Add request interceptors to attach bearer tokens.&lt;/li&gt;
&lt;li&gt;Implement refresh token handling early.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want this fully prebuilt, ASP.NET Zero already includes this flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Now your React + ASP.NET Core baseline is ready. Continue with one of these paths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add JWT authentication and protected routes.&lt;/li&gt;
&lt;li&gt;Add CRUD modules with server-side validation and pagination.&lt;/li&gt;
&lt;li&gt;Introduce role-based authorization and admin screens.&lt;/li&gt;
&lt;li&gt;Evaluate ASP.NET Zero React UI if you want to skip infrastructure coding.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Useful links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ASP.NET Core docs: &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/" rel="noopener noreferrer"&gt;learn.microsoft.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ASP.NET Zero React docs: &lt;a href="https://docs.aspnetzero.com/aspnet-core-react/latest/Getting-Started-React" rel="noopener noreferrer"&gt;docs.aspnetzero.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ASP.NET Zero React page: &lt;a href="https://aspnetzero.com/react" rel="noopener noreferrer"&gt;aspnetzero.com/react&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building enterprise software is not only about choosing a frontend library. It is about reducing risk, increasing delivery speed, and keeping architecture maintainable as the product grows. React + ASP.NET Core is an excellent foundation, and with the right starting point, your team can move much faster.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>fullstack</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Angular + ASP.NET Core: Enterprise Project Getting Started Guide (2026)</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Tue, 07 Apr 2026 06:07:32 +0000</pubDate>
      <link>https://forem.com/ismcagdas/angular-aspnet-core-enterprise-project-getting-started-guide-2026-2o3</link>
      <guid>https://forem.com/ismcagdas/angular-aspnet-core-enterprise-project-getting-started-guide-2026-2o3</guid>
      <description>&lt;p&gt;If you are building an enterprise web application in 2026, the combination of &lt;strong&gt;Angular&lt;/strong&gt; and &lt;strong&gt;ASP.NET Core&lt;/strong&gt; is one of the strongest choices you can make. Angular gives you TypeScript safety, a powerful component architecture, and a mature ecosystem. ASP.NET Core gives you a high-performance, cross-platform backend with first-class dependency injection and a rich middleware pipeline.&lt;/p&gt;

&lt;p&gt;In this post, we will walk through &lt;strong&gt;three different ways&lt;/strong&gt; to start an Angular + ASP.NET Core project — from a fully manual setup to a one-click enterprise starter. By the end, you will have a clear understanding of which approach fits your project best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;
Approach 1 — Manual Setup

&lt;ul&gt;
&lt;li&gt;Step 1: Create the Angular App&lt;/li&gt;
&lt;li&gt;Step 2: Create the ASP.NET Core Web API&lt;/li&gt;
&lt;li&gt;Step 3: Configure CORS&lt;/li&gt;
&lt;li&gt;Step 4: Set Up the Angular Proxy&lt;/li&gt;
&lt;li&gt;Step 5: Make the First API Call&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Approach 2 — Visual Studio Template&lt;/li&gt;

&lt;li&gt;Approach 3 — ASP.NET Zero&lt;/li&gt;

&lt;li&gt;Comparison&lt;/li&gt;

&lt;li&gt;Common Issues and Solutions&lt;/li&gt;

&lt;li&gt;Next Steps&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, make sure you have the following tools installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; 24.x or later — &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular CLI&lt;/strong&gt; 21.x — install with &lt;code&gt;npm install -g @angular/cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 10 SDK&lt;/strong&gt; — &lt;a href="https://dotnet.microsoft.com/download/dotnet/10.0" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio 2026&lt;/strong&gt; (Latest stable version) or &lt;strong&gt;VS Code&lt;/strong&gt; with the C# Dev Kit extension&lt;/li&gt;
&lt;li&gt;A terminal you are comfortable with (PowerShell, bash, or the VS Code integrated terminal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can verify your setup by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;    &lt;span class="c"&gt;# v24.x (use latest stable)&lt;/span&gt;
ng version        &lt;span class="c"&gt;# Angular CLI 21.x&lt;/span&gt;
dotnet &lt;span class="nt"&gt;--version&lt;/span&gt;  &lt;span class="c"&gt;# 10.x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Approach 1 — Manual Setup
&lt;/h2&gt;

&lt;p&gt;This approach gives you full control over every detail. It is the best choice if you want to understand how the pieces fit together or if you have specific architectural requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Angular App
&lt;/h3&gt;

&lt;p&gt;Open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new MyApp.Client &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scss &lt;span class="nt"&gt;--routing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--ssr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
cd &lt;/span&gt;MyApp.Client
ng serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;code&gt;http://localhost:4200&lt;/code&gt; — you should see the default Angular welcome page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create the ASP.NET Core Web API
&lt;/h3&gt;

&lt;p&gt;Open a new terminal in the parent directory and create the API project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new webapi &lt;span class="nt"&gt;-n&lt;/span&gt; MyApp.Api &lt;span class="nt"&gt;--use-controllers&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;MyApp.Api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add a simple endpoint to test the connection. Open &lt;code&gt;Controllers/WeatherForecastController.cs&lt;/code&gt; — the template already includes a &lt;code&gt;GET /WeatherForecast&lt;/code&gt; endpoint that returns random forecast data. We will use this for our first integration test.&lt;/p&gt;

&lt;p&gt;Run the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API will start on a port shown in the terminal output (e.g. &lt;code&gt;http://localhost:5266&lt;/code&gt;). You can verify it by navigating to &lt;code&gt;http://localhost:{port}/WeatherForecast&lt;/code&gt; in your browser. Take note of this port — you will need it for the proxy configuration in Step 4.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure CORS
&lt;/h3&gt;

&lt;p&gt;By default, your Angular app on &lt;code&gt;localhost:4200&lt;/code&gt; cannot call the API on &lt;code&gt;localhost:5001&lt;/code&gt; because of the browser's same-origin policy. We need to enable CORS on the API side.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;Program.cs&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Add CORS policy&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:4200"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Use the CORS policy&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This CORS configuration is for development only. In production, you should restrict the allowed origins to your actual domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Set Up the Angular Proxy
&lt;/h3&gt;

&lt;p&gt;While CORS works, a cleaner approach during development is to use Angular's built-in proxy. This way, the Angular dev server forwards API requests to the backend, and you avoid CORS entirely.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;proxy.conf.json&lt;/code&gt; in the root of your Angular project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"/WeatherForecast"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5266"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"secure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"changeOrigin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;5266&lt;/code&gt; with the actual port your API is running on. You can find it in the terminal output when you run &lt;code&gt;dotnet run&lt;/code&gt; — look for the line that says &lt;code&gt;Now listening on: http://localhost:XXXX&lt;/code&gt;. Also, we are proxying the &lt;code&gt;/WeatherForecast&lt;/code&gt; path directly because the default .NET template does not use an &lt;code&gt;/api&lt;/code&gt; prefix. In a real project, you would typically add a common prefix like &lt;code&gt;/api&lt;/code&gt; to all your controllers (using &lt;code&gt;[Route("api/[controller]")]&lt;/code&gt;) and proxy that single prefix instead.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;angular.json&lt;/code&gt; to use the proxy. Find the &lt;code&gt;serve&lt;/code&gt; section and add the &lt;code&gt;proxyConfig&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"proxyConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"proxy.conf.json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now restart the Angular dev server with &lt;code&gt;ng serve&lt;/code&gt;. Any request to &lt;code&gt;/WeatherForecast&lt;/code&gt; from your Angular app will be forwarded to the .NET backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Make the First API Call
&lt;/h3&gt;

&lt;p&gt;Let's update the root component to fetch weather data from the API. First, we need to configure &lt;code&gt;HttpClient&lt;/code&gt;. Open &lt;code&gt;src/app/app.config.ts&lt;/code&gt; and add &lt;code&gt;provideHttpClient()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideHttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;provideHttpClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open &lt;code&gt;src/app/app.ts&lt;/code&gt; and update it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WeatherForecast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temperatureF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;forecasts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/WeatherForecast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forecasts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update &lt;code&gt;src/app/app.html&lt;/code&gt; with the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Weather Forecast&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
@if (forecasts().length &amp;gt; 0) {
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Date&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Temp (C)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Temp (F)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Summary&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
      @for (f of forecasts(); track f.date) {
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.date }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.temperatureC }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.temperatureF }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.summary }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      }
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file and check your browser. You should see the weather data rendered in a table. Your Angular frontend is now talking to your ASP.NET Core backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2 — Visual Studio Template
&lt;/h2&gt;

&lt;p&gt;If you prefer a faster start with less manual configuration, Visual Studio 2022 ships with a built-in &lt;strong&gt;Angular + ASP.NET Core&lt;/strong&gt; project template.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Visual Studio 2026 and select &lt;strong&gt;Create a new project&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;"ASP.NET Core with Angular"&lt;/strong&gt; and select the template.&lt;/li&gt;
&lt;li&gt;Configure the project name, location, and solution name.&lt;/li&gt;
&lt;li&gt;On the next screen, select &lt;strong&gt;.NET 10&lt;/strong&gt; as the target framework.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Visual Studio generates a solution with two projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;ASP.NET Core&lt;/strong&gt; backend with a sample &lt;code&gt;WeatherForecast&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Angular&lt;/strong&gt; frontend with proxy configuration already wired up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to run the project. Both the backend and the frontend will start together, and you will see a working Angular app fetching data from the API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get out of the box:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-configured proxy (&lt;code&gt;proxy.conf.js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HTTPS development certificate setup&lt;/li&gt;
&lt;li&gt;Integrated launch profiles for debugging both projects simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you don't get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication / authorization&lt;/li&gt;
&lt;li&gt;Multi-tenancy&lt;/li&gt;
&lt;li&gt;Role management&lt;/li&gt;
&lt;li&gt;A production-ready UI framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This template is a great starting point for prototypes or simple applications. For enterprise projects, you will need to add these features yourself — or use a framework that includes them. But, be aware that this option may have problems time to time because some pf the NPM packages intorduce breaking changes and it takes time for maintainer team to release a working version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 3 — ASP.NET Zero
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;ASP.NET Zero&lt;/a&gt; is a production-ready starter kit built on ASP.NET Core that supports &lt;strong&gt;Angular&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, and &lt;strong&gt;MVC (Razor)&lt;/strong&gt; as frontend options. It is designed specifically for enterprise applications and includes dozens of features out of the box.&lt;/p&gt;

&lt;p&gt;Here is how to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;aspnetzero.com&lt;/a&gt; and sign up for a license.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Download&lt;/strong&gt; page, select &lt;strong&gt;Angular&lt;/strong&gt; as your frontend, and download the project.&lt;/li&gt;
&lt;li&gt;Open the solution in Visual Studio or VS Code.&lt;/li&gt;
&lt;li&gt;Update the database connection string in &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;migrator&lt;/code&gt; project to create and seed the database:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/MyProject.Migrator
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the backend:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/MyProject.Web.Host
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the Angular frontend:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;angular
yarn 
yarn create-dynamic-bundles
yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;code&gt;http://localhost:4200&lt;/code&gt; and log in with the default admin credentials. You will see a fully working enterprise application.&lt;/p&gt;

&lt;p&gt;To run the project propertly, you can follow &lt;a href="https://docs.aspnetzero.com/aspnet-core-angular/latest/Getting-Started-Angular" rel="noopener noreferrer"&gt;Angular Getting Started Document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get out of the box:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication &amp;amp; Authorization:&lt;/strong&gt; Login, registration, two-factor authentication, social logins, LDAP/Active Directory integration — all pre-built and configurable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Tenancy:&lt;/strong&gt; Host/tenant architecture with separate databases or shared database options. Tenant registration, subscription management, and edition management are built in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role &amp;amp; Permission Management:&lt;/strong&gt; A granular permission system with role-based and user-based authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization Units:&lt;/strong&gt; Hierarchical organizational structure with the ability to assign users and roles per unit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit Logging:&lt;/strong&gt; Every action is logged with user, timestamp, and change details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Notifications:&lt;/strong&gt; Built-in notification system with SignalR integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Theme:&lt;/strong&gt; A polished admin theme based on Metronic with responsive design, dark mode, and multiple layout options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Power Tools:&lt;/strong&gt; A Visual Studio extension and a CLI tool that generates &lt;strong&gt;entities, DTOs, application services, API controllers, Angular components, and unit tests&lt;/strong&gt; from a simple entity definition. Instead of writing CRUD code manually, you describe your entity and Power Tools generates everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see Power Tools in action. Say you want to add a &lt;code&gt;Product&lt;/code&gt; entity to your application. You define the entity fields (Name, Price, Category, etc.) in Power Tools, click &lt;strong&gt;Generate&lt;/strong&gt;, and it creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Product&lt;/code&gt; entity and database migration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProductAppService&lt;/code&gt; with full CRUD operations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProductDto&lt;/code&gt; and &lt;code&gt;CreateProductDto&lt;/code&gt; classes&lt;/li&gt;
&lt;li&gt;Angular components for listing, creating, and editing products&lt;/li&gt;
&lt;li&gt;Unit tests for the app service&lt;/li&gt;
&lt;li&gt;UI tests for your Angular pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What would take hours of boilerplate coding is done in under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;p&gt;Here is how the three approaches compare:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual Setup&lt;/th&gt;
&lt;th&gt;VS Template&lt;/th&gt;
&lt;th&gt;ASP.NET Zero&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;30-60 min&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization / Roles&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organization units&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit logging&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI theme&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Metronic (production-ready)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code generation tools&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Power Tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time notifications&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning value&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full (source code included)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Licensed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; If you are learning or building a simple prototype, the manual setup or VS template is perfect. If you are building an enterprise application and want to skip months of infrastructure work, ASP.NET Zero gives you a massive head start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CORS Errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; The browser console shows &lt;code&gt;Access to XMLHttpRequest has been blocked by CORS policy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Make sure your &lt;code&gt;Program.cs&lt;/code&gt; includes the CORS middleware and that &lt;code&gt;app.UseCors()&lt;/code&gt; is called &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;app.UseAuthorization()&lt;/code&gt;. Also verify that the origin URL matches exactly (including the port number and protocol).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Correct order&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Proxy Not Working
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; API calls return 404 or the Angular app tries to serve the request itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Double-check the &lt;code&gt;proxy.conf.json&lt;/code&gt; path in &lt;code&gt;angular.json&lt;/code&gt;. Make sure the &lt;code&gt;target&lt;/code&gt; URL matches the port your API is running on. Restart &lt;code&gt;ng serve&lt;/code&gt; after any proxy configuration change — the proxy config is only read at startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL Certificate Errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; &lt;code&gt;ERR_CERT_AUTHORITY_INVALID&lt;/code&gt; or proxy shows &lt;code&gt;UNABLE_TO_VERIFY_LEAF_SIGNATURE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; For development, set &lt;code&gt;"secure": false&lt;/code&gt; in your &lt;code&gt;proxy.conf.json&lt;/code&gt;. This tells the Angular dev server to accept self-signed certificates. Alternatively, trust the .NET development certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet dev-certs https &lt;span class="nt"&gt;--trust&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Angular CLI Version Mismatch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Build errors or unexpected behavior after creating the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Make sure your global Angular CLI version matches the version in the project's &lt;code&gt;package.json&lt;/code&gt;. You can check with &lt;code&gt;ng version&lt;/code&gt; and update with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli@19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Now that your Angular + ASP.NET Core project is up and running, here are some next steps depending on which approach you chose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add authentication:&lt;/strong&gt; If you went with the manual setup or VS template, check out the &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity" rel="noopener noreferrer"&gt;ASP.NET Core Identity documentation&lt;/a&gt; to add login and registration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore ASP.NET Zero:&lt;/strong&gt; If you are interested in the enterprise approach, &lt;a href="https://aspnetzero.com/contact" rel="noopener noreferrer"&gt;contact&lt;/a&gt; ASP.NET Zero Team and explore the &lt;a href="https://docs.aspnetzero.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. The Angular getting started guide will have you running in under 10 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try Power Tools:&lt;/strong&gt; If you are already using ASP.NET Zero, generate your first entity with &lt;a href="https://docs.aspnetzero.com/development-guide/rad-tool" rel="noopener noreferrer"&gt;Power Tools&lt;/a&gt; and see how much time it saves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building enterprise applications is hard. Choosing the right foundation makes it significantly easier. Whether you start from scratch or stand on the shoulders of a mature framework, Angular and ASP.NET Core together give you a rock-solid stack for 2026 and beyond.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dotnet</category>
      <category>fullstack</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Angular + ASP.NET Core: Enterprise Project Getting Started Guide</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Thu, 02 Apr 2026 10:29:43 +0000</pubDate>
      <link>https://forem.com/ismcagdas/angular-aspnet-core-enterprise-project-getting-started-guide-1k8l</link>
      <guid>https://forem.com/ismcagdas/angular-aspnet-core-enterprise-project-getting-started-guide-1k8l</guid>
      <description>&lt;p&gt;If you are building an enterprise web application in 2026, the combination of &lt;strong&gt;Angular&lt;/strong&gt; and &lt;strong&gt;ASP.NET Core&lt;/strong&gt; is one of the strongest choices you can make. Angular gives you TypeScript safety, a powerful component architecture, and a mature ecosystem. ASP.NET Core gives you a high-performance, cross-platform backend with first-class dependency injection and a rich middleware pipeline.&lt;/p&gt;

&lt;p&gt;In this post, we will walk through &lt;strong&gt;three different ways&lt;/strong&gt; to start an Angular + ASP.NET Core project — from a fully manual setup to a one-click enterprise starter. By the end, you will have a clear understanding of which approach fits your project best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;
Approach 1 — Manual Setup

&lt;ul&gt;
&lt;li&gt;Step 1: Create the Angular App&lt;/li&gt;
&lt;li&gt;Step 2: Create the ASP.NET Core Web API&lt;/li&gt;
&lt;li&gt;Step 3: Configure CORS&lt;/li&gt;
&lt;li&gt;Step 4: Set Up the Angular Proxy&lt;/li&gt;
&lt;li&gt;Step 5: Make the First API Call&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Approach 2 — Visual Studio Template&lt;/li&gt;

&lt;li&gt;Approach 3 — ASP.NET Zero&lt;/li&gt;

&lt;li&gt;Comparison&lt;/li&gt;

&lt;li&gt;Common Issues and Solutions&lt;/li&gt;

&lt;li&gt;Next Steps&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, make sure you have the following tools installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; 24.x or later — &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular CLI&lt;/strong&gt; 21.x — install with &lt;code&gt;npm install -g @angular/cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 10 SDK&lt;/strong&gt; — &lt;a href="https://dotnet.microsoft.com/download/dotnet/10.0" rel="noopener noreferrer"&gt;download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio 2026&lt;/strong&gt; (Latest stable version) or &lt;strong&gt;VS Code&lt;/strong&gt; with the C# Dev Kit extension&lt;/li&gt;
&lt;li&gt;A terminal you are comfortable with (PowerShell, bash, or the VS Code integrated terminal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can verify your setup by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;    &lt;span class="c"&gt;# v24.x (use latest stable)&lt;/span&gt;
ng version        &lt;span class="c"&gt;# Angular CLI 21.x&lt;/span&gt;
dotnet &lt;span class="nt"&gt;--version&lt;/span&gt;  &lt;span class="c"&gt;# 10.x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Approach 1 — Manual Setup
&lt;/h2&gt;

&lt;p&gt;This approach gives you full control over every detail. It is the best choice if you want to understand how the pieces fit together or if you have specific architectural requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Angular App
&lt;/h3&gt;

&lt;p&gt;Open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new MyApp.Client &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scss &lt;span class="nt"&gt;--routing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--ssr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
cd &lt;/span&gt;MyApp.Client
ng serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;code&gt;http://localhost:4200&lt;/code&gt; — you should see the default Angular welcome page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create the ASP.NET Core Web API
&lt;/h3&gt;

&lt;p&gt;Open a new terminal in the parent directory and create the API project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new webapi &lt;span class="nt"&gt;-n&lt;/span&gt; MyApp.Api &lt;span class="nt"&gt;--use-controllers&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;MyApp.Api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add a simple endpoint to test the connection. Open &lt;code&gt;Controllers/WeatherForecastController.cs&lt;/code&gt; — the template already includes a &lt;code&gt;GET /WeatherForecast&lt;/code&gt; endpoint that returns random forecast data. We will use this for our first integration test.&lt;/p&gt;

&lt;p&gt;Run the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API will start on a port shown in the terminal output (e.g. &lt;code&gt;http://localhost:5266&lt;/code&gt;). You can verify it by navigating to &lt;code&gt;http://localhost:{port}/WeatherForecast&lt;/code&gt; in your browser. Take note of this port — you will need it for the proxy configuration in Step 4.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure CORS
&lt;/h3&gt;

&lt;p&gt;By default, your Angular app on &lt;code&gt;localhost:4200&lt;/code&gt; cannot call the API on &lt;code&gt;localhost:5001&lt;/code&gt; because of the browser's same-origin policy. We need to enable CORS on the API side.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;Program.cs&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Add CORS policy&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:4200"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Use the CORS policy&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This CORS configuration is for development only. In production, you should restrict the allowed origins to your actual domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Set Up the Angular Proxy
&lt;/h3&gt;

&lt;p&gt;While CORS works, a cleaner approach during development is to use Angular's built-in proxy. This way, the Angular dev server forwards API requests to the backend, and you avoid CORS entirely.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;proxy.conf.json&lt;/code&gt; in the root of your Angular project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"/WeatherForecast"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5266"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"secure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"changeOrigin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;5266&lt;/code&gt; with the actual port your API is running on. You can find it in the terminal output when you run &lt;code&gt;dotnet run&lt;/code&gt; — look for the line that says &lt;code&gt;Now listening on: http://localhost:XXXX&lt;/code&gt;. Also, we are proxying the &lt;code&gt;/WeatherForecast&lt;/code&gt; path directly because the default .NET template does not use an &lt;code&gt;/api&lt;/code&gt; prefix. In a real project, you would typically add a common prefix like &lt;code&gt;/api&lt;/code&gt; to all your controllers (using &lt;code&gt;[Route("api/[controller]")]&lt;/code&gt;) and proxy that single prefix instead.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;angular.json&lt;/code&gt; to use the proxy. Find the &lt;code&gt;serve&lt;/code&gt; section and add the &lt;code&gt;proxyConfig&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"proxyConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"proxy.conf.json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now restart the Angular dev server with &lt;code&gt;ng serve&lt;/code&gt;. Any request to &lt;code&gt;/WeatherForecast&lt;/code&gt; from your Angular app will be forwarded to the .NET backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Make the First API Call
&lt;/h3&gt;

&lt;p&gt;Let's update the root component to fetch weather data from the API. First, we need to configure &lt;code&gt;HttpClient&lt;/code&gt;. Open &lt;code&gt;src/app/app.config.ts&lt;/code&gt; and add &lt;code&gt;provideHttpClient()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideHttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;provideHttpClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open &lt;code&gt;src/app/app.ts&lt;/code&gt; and update it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WeatherForecast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temperatureF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;forecasts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/WeatherForecast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forecasts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update &lt;code&gt;src/app/app.html&lt;/code&gt; with the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Weather Forecast&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
@if (forecasts().length &amp;gt; 0) {
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Date&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Temp (C)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Temp (F)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Summary&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
      @for (f of forecasts(); track f.date) {
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.date }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.temperatureC }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.temperatureF }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ f.summary }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      }
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file and check your browser. You should see the weather data rendered in a table. Your Angular frontend is now talking to your ASP.NET Core backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2 — Visual Studio Template
&lt;/h2&gt;

&lt;p&gt;If you prefer a faster start with less manual configuration, Visual Studio 2022 ships with a built-in &lt;strong&gt;Angular + ASP.NET Core&lt;/strong&gt; project template.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Visual Studio 2026 and select &lt;strong&gt;Create a new project&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;"ASP.NET Core with Angular"&lt;/strong&gt; and select the template.&lt;/li&gt;
&lt;li&gt;Configure the project name, location, and solution name.&lt;/li&gt;
&lt;li&gt;On the next screen, select &lt;strong&gt;.NET 10&lt;/strong&gt; as the target framework.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Visual Studio generates a solution with two projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;ASP.NET Core&lt;/strong&gt; backend with a sample &lt;code&gt;WeatherForecast&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Angular&lt;/strong&gt; frontend with proxy configuration already wired up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to run the project. Both the backend and the frontend will start together, and you will see a working Angular app fetching data from the API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get out of the box:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-configured proxy (&lt;code&gt;proxy.conf.js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HTTPS development certificate setup&lt;/li&gt;
&lt;li&gt;Integrated launch profiles for debugging both projects simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you don't get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication / authorization&lt;/li&gt;
&lt;li&gt;Multi-tenancy&lt;/li&gt;
&lt;li&gt;Role management&lt;/li&gt;
&lt;li&gt;A production-ready UI framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This template is a great starting point for prototypes or simple applications. For enterprise projects, you will need to add these features yourself — or use a framework that includes them. But, be aware that this option may have problems time to time because some pf the NPM packages intorduce breaking changes and it takes time for maintainer team to release a working version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 3 — ASP.NET Zero
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;ASP.NET Zero&lt;/a&gt; is a production-ready starter kit built on ASP.NET Core that supports &lt;strong&gt;Angular&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, and &lt;strong&gt;MVC (Razor)&lt;/strong&gt; as frontend options. It is designed specifically for enterprise applications and includes dozens of features out of the box.&lt;/p&gt;

&lt;p&gt;Here is how to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aspnetzero.com/" rel="noopener noreferrer"&gt;aspnetzero.com&lt;/a&gt; and sign up for a license.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Download&lt;/strong&gt; page, select &lt;strong&gt;Angular&lt;/strong&gt; as your frontend, and download the project.&lt;/li&gt;
&lt;li&gt;Open the solution in Visual Studio or VS Code.&lt;/li&gt;
&lt;li&gt;Update the database connection string in &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;migrator&lt;/code&gt; project to create and seed the database:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/MyProject.Migrator
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the backend:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src/MyProject.Web.Host
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the Angular frontend:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;angular
yarn 
yarn create-dynamic-bundles
yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;code&gt;http://localhost:4200&lt;/code&gt; and log in with the default admin credentials. You will see a fully working enterprise application.&lt;/p&gt;

&lt;p&gt;To run the project propertly, you can follow &lt;a href="https://docs.aspnetzero.com/aspnet-core-angular/latest/Getting-Started-Angular" rel="noopener noreferrer"&gt;Angular Getting Started Document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get out of the box:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication &amp;amp; Authorization:&lt;/strong&gt; Login, registration, two-factor authentication, social logins, LDAP/Active Directory integration — all pre-built and configurable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Tenancy:&lt;/strong&gt; Host/tenant architecture with separate databases or shared database options. Tenant registration, subscription management, and edition management are built in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role &amp;amp; Permission Management:&lt;/strong&gt; A granular permission system with role-based and user-based authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization Units:&lt;/strong&gt; Hierarchical organizational structure with the ability to assign users and roles per unit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit Logging:&lt;/strong&gt; Every action is logged with user, timestamp, and change details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Notifications:&lt;/strong&gt; Built-in notification system with SignalR integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Theme:&lt;/strong&gt; A polished admin theme based on Metronic with responsive design, dark mode, and multiple layout options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Power Tools:&lt;/strong&gt; A Visual Studio extension and a CLI tool that generates &lt;strong&gt;entities, DTOs, application services, API controllers, Angular components, and unit tests&lt;/strong&gt; from a simple entity definition. Instead of writing CRUD code manually, you describe your entity and Power Tools generates everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see Power Tools in action. Say you want to add a &lt;code&gt;Product&lt;/code&gt; entity to your application. You define the entity fields (Name, Price, Category, etc.) in Power Tools, click &lt;strong&gt;Generate&lt;/strong&gt;, and it creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Product&lt;/code&gt; entity and database migration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProductAppService&lt;/code&gt; with full CRUD operations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProductDto&lt;/code&gt; and &lt;code&gt;CreateProductDto&lt;/code&gt; classes&lt;/li&gt;
&lt;li&gt;Angular components for listing, creating, and editing products&lt;/li&gt;
&lt;li&gt;Unit tests for the app service&lt;/li&gt;
&lt;li&gt;UI tests for your Angular pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What would take hours of boilerplate coding is done in under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;p&gt;Here is how the three approaches compare:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual Setup&lt;/th&gt;
&lt;th&gt;VS Template&lt;/th&gt;
&lt;th&gt;ASP.NET Zero&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;30-60 min&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization / Roles&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organization units&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit logging&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI theme&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Metronic (production-ready)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code generation tools&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Power Tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time notifications&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning value&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full (source code included)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Licensed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; If you are learning or building a simple prototype, the manual setup or VS template is perfect. If you are building an enterprise application and want to skip months of infrastructure work, ASP.NET Zero gives you a massive head start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CORS Errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; The browser console shows &lt;code&gt;Access to XMLHttpRequest has been blocked by CORS policy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Make sure your &lt;code&gt;Program.cs&lt;/code&gt; includes the CORS middleware and that &lt;code&gt;app.UseCors()&lt;/code&gt; is called &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;app.UseAuthorization()&lt;/code&gt;. Also verify that the origin URL matches exactly (including the port number and protocol).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Correct order&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Angular"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Proxy Not Working
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; API calls return 404 or the Angular app tries to serve the request itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Double-check the &lt;code&gt;proxy.conf.json&lt;/code&gt; path in &lt;code&gt;angular.json&lt;/code&gt;. Make sure the &lt;code&gt;target&lt;/code&gt; URL matches the port your API is running on. Restart &lt;code&gt;ng serve&lt;/code&gt; after any proxy configuration change — the proxy config is only read at startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL Certificate Errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; &lt;code&gt;ERR_CERT_AUTHORITY_INVALID&lt;/code&gt; or proxy shows &lt;code&gt;UNABLE_TO_VERIFY_LEAF_SIGNATURE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; For development, set &lt;code&gt;"secure": false&lt;/code&gt; in your &lt;code&gt;proxy.conf.json&lt;/code&gt;. This tells the Angular dev server to accept self-signed certificates. Alternatively, trust the .NET development certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet dev-certs https &lt;span class="nt"&gt;--trust&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Angular CLI Version Mismatch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Build errors or unexpected behavior after creating the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Make sure your global Angular CLI version matches the version in the project's &lt;code&gt;package.json&lt;/code&gt;. You can check with &lt;code&gt;ng version&lt;/code&gt; and update with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli@19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Now that your Angular + ASP.NET Core project is up and running, here are some next steps depending on which approach you chose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add authentication:&lt;/strong&gt; If you went with the manual setup or VS template, check out the &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity" rel="noopener noreferrer"&gt;ASP.NET Core Identity documentation&lt;/a&gt; to add login and registration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore ASP.NET Zero:&lt;/strong&gt; If you are interested in the enterprise approach, &lt;a href="https://aspnetzero.com/contact" rel="noopener noreferrer"&gt;contact&lt;/a&gt; ASP.NET Zero Team and explore the &lt;a href="https://docs.aspnetzero.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. The Angular getting started guide will have you running in under 10 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try Power Tools:&lt;/strong&gt; If you are already using ASP.NET Zero, generate your first entity with &lt;a href="https://docs.aspnetzero.com/development-guide/rad-tool" rel="noopener noreferrer"&gt;Power Tools&lt;/a&gt; and see how much time it saves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building enterprise applications is hard. Choosing the right foundation makes it significantly easier. Whether you start from scratch or stand on the shoulders of a mature framework, Angular and ASP.NET Core together give you a rock-solid stack for 2026 and beyond.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dotnet</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What .NET 10 LTS Means for Enterprise Applications</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Wed, 21 Jan 2026 05:45:09 +0000</pubDate>
      <link>https://forem.com/ismcagdas/what-net-10-lts-means-for-enterprise-applications-2cdh</link>
      <guid>https://forem.com/ismcagdas/what-net-10-lts-means-for-enterprise-applications-2cdh</guid>
      <description>&lt;p&gt;If you are running enterprise applications on .NET 8 or .NET 9, there is an important date you need to mark on your calendar: &lt;strong&gt;November 10, 2026&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On that day, both .NET 8 and .NET 9 will reach end of support—simultaneously. This is not a typo. Due to Microsoft's decision to extend Standard Term Support (STS) from 18 to 24 months, both versions now share the same end-of-life date.&lt;/p&gt;

&lt;p&gt;This creates a unique situation for enterprise teams: whether you played it safe with .NET 8 LTS or chased the latest features with .NET 9, you now face the same migration deadline.&lt;/p&gt;

&lt;p&gt;The target? &lt;strong&gt;.NET 10 LTS&lt;/strong&gt;, released in November 2025 and supported until &lt;strong&gt;November 2028&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Support Timeline You Need to Understand
&lt;/h2&gt;

&lt;p&gt;Microsoft follows a predictable release cadence: even-numbered releases are Long Term Support (LTS) with three years of support, while odd-numbered releases are Standard Term Support (STS) with 18-24 months.&lt;/p&gt;

&lt;p&gt;Here is the current state of .NET support:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Release Type&lt;/th&gt;
&lt;th&gt;End of Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;.NET 6&lt;/td&gt;
&lt;td&gt;LTS&lt;/td&gt;
&lt;td&gt;November 12, 2024 (Already EOL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 7&lt;/td&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;May 14, 2024 (Already EOL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 8&lt;/td&gt;
&lt;td&gt;LTS&lt;/td&gt;
&lt;td&gt;November 10, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 9&lt;/td&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;November 10, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 10&lt;/td&gt;
&lt;td&gt;LTS&lt;/td&gt;
&lt;td&gt;November 10, 2028&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you are still running .NET 6 or .NET 7, you are already operating on unsupported frameworks. No security patches. No bug fixes. This is a compliance risk that needs immediate attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why .NET 10 LTS Matters for Enterprise
&lt;/h2&gt;

&lt;p&gt;Every two years, Microsoft releases an LTS version. Usually, it is the "safe" choice—the boring, stable option that enterprises pick while developers chase newer features. This time is different.&lt;/p&gt;

&lt;p&gt;.NET 10 LTS is not just a stability release. It is a significant leap forward in performance, security, and AI readiness.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Performance That Impacts Your Bottom Line
&lt;/h3&gt;

&lt;p&gt;The performance improvements in .NET 10 are not incremental. Real-world benchmarks show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;30-50% performance improvements&lt;/strong&gt; from JIT inlining, method devirtualization, and stack allocation optimizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;40-60% reduction in memory usage&lt;/strong&gt; through array interface de-virtualization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;60-80% improvements&lt;/strong&gt; in specific high-throughput scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For enterprise applications, this translates directly to infrastructure savings. If your cloud bill is tied to CPU and memory consumption, .NET 10 can meaningfully reduce your costs without changing a single line of business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Security and Compliance Acceleration
&lt;/h3&gt;

&lt;p&gt;Enterprise applications live and die by compliance requirements. .NET 10 strengthens your security posture through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Updated cipher suites&lt;/strong&gt; with modern cryptographic standards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved request validation&lt;/strong&gt; and hardened default configurations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced vulnerability patching workflows&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-quantum cryptography support&lt;/strong&gt; via Windows CNG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point deserves attention. Financial services, government contractors, and healthcare organizations are already being asked about quantum-resistant encryption strategies. .NET 10's built-in post-quantum cryptography support checks that compliance box automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. AI-Ready Infrastructure
&lt;/h3&gt;

&lt;p&gt;.NET 10 arrives with built-in AI integration through the new &lt;strong&gt;Microsoft Agent Framework&lt;/strong&gt;. Combined with expanded &lt;strong&gt;ML.NET&lt;/strong&gt; capabilities and new &lt;strong&gt;tensor APIs&lt;/strong&gt;, your applications are positioned to integrate AI features without bolting on external dependencies.&lt;/p&gt;

&lt;p&gt;This is not about hype. It is about having the foundation in place when your business stakeholders inevitably ask for AI-powered features.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Entity Framework Core 10: Enterprise Data Features
&lt;/h3&gt;

&lt;p&gt;For data-driven enterprise applications, EF Core 10 brings two significant additions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vector search support&lt;/strong&gt; for SQL Server 2025 and Azure SQL Database—enabling embeddings and similarity search directly in your ORM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native JSON type support&lt;/strong&gt; for the new SQL Server JSON data type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your roadmap includes semantic search, recommendation engines, or any AI/ML features that rely on vector embeddings, EF Core 10 eliminates the need for specialized vector databases in many scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration Decision Matrix
&lt;/h2&gt;

&lt;p&gt;Not every organization has the same constraints. Here is how to think about your migration strategy:&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Are on .NET 9
&lt;/h3&gt;

&lt;p&gt;This is the easiest path. You are moving from a 2-year STS window to a 3-year LTS window. Most projects can complete this migration in &lt;strong&gt;2-5 days&lt;/strong&gt;. The breaking changes are minimal, and you gain 2.5 additional years of support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Migrate immediately. There is no reason to wait.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Are on .NET 8 LTS
&lt;/h3&gt;

&lt;p&gt;You have until November 2026, but do not let that create complacency. The performance improvements alone justify an earlier migration. Plan your upgrade cycle for Q2 2026 at the latest to allow buffer for testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Start planning now. Execute migration by mid-2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Are on .NET 6 or .NET 7
&lt;/h3&gt;

&lt;p&gt;You are running unsupported frameworks. Every day without patches is a day of accumulated security risk. This is not a feature migration—it is a critical security remediation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Treat this as a P1 priority. Migrate immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Are on .NET Framework 4.8
&lt;/h3&gt;

&lt;p&gt;The jump to .NET 10 is significant but achievable. Modern tooling, including AI-assisted migration with GitHub Copilot, makes this transformation practical. The benefits—cross-platform support, containerization, modern performance—justify the investment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Begin assessment now. Plan a phased migration over the next 12-18 months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling Requirements: The Visual Studio Question
&lt;/h2&gt;

&lt;p&gt;There is one critical constraint: &lt;strong&gt;.NET 10 requires Visual Studio 2026&lt;/strong&gt;. Visual Studio 2022 cannot target .NET 10 or use C# 14 features.&lt;/p&gt;

&lt;p&gt;For enterprises with standardized development environments, this means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;VS Code + C# Dev Kit&lt;/strong&gt; is a fully supported alternative available today&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio 2026&lt;/strong&gt; GA is expected in early 2026&lt;/li&gt;
&lt;li&gt;Most enterprises should wait for VS 2026 GA before full rollout, but developers can start with VS Code immediately&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not a blocker, but it does need to factor into your planning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Changes to Prepare For
&lt;/h2&gt;

&lt;p&gt;Every major release brings breaking changes. Here are the ones that will impact most enterprise applications:&lt;/p&gt;

&lt;h3&gt;
  
  
  WebHostBuilder and IWebHost Are Obsolete
&lt;/h3&gt;

&lt;p&gt;The legacy hosting model is deprecated. If your applications still use &lt;code&gt;WebHostBuilder&lt;/code&gt;, you need to migrate to &lt;code&gt;WebApplicationBuilder&lt;/code&gt;. This is the direction Microsoft has been pushing since .NET 6, and .NET 10 makes it explicit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebHostBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseKestrel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Configure services&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Configure middleware&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WithOpenApi Extension Method Removed
&lt;/h3&gt;

&lt;p&gt;If you are using the &lt;code&gt;WithOpenApi()&lt;/code&gt; extension method for minimal APIs, it has been removed. Use the updated OpenAPI generator features instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default Images Now Use Ubuntu
&lt;/h3&gt;

&lt;p&gt;.NET container images now default to Ubuntu instead of Debian. If your deployment pipelines or Dockerfiles assume Debian-specific packages, you will need to update them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three-Year Runway
&lt;/h2&gt;

&lt;p&gt;.NET 10 LTS support extends until November 2028. This gives your organization three full years to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stabilize on a modern, performant runtime&lt;/li&gt;
&lt;li&gt;Adopt AI and ML features at your own pace&lt;/li&gt;
&lt;li&gt;Plan the next major upgrade cycle without pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compare this to the version hopscotch of STS releases. For enterprise applications that value stability and predictability, .NET 10 LTS is the clear choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Time to Act Is Now
&lt;/h2&gt;

&lt;p&gt;The convergence of .NET 8 and .NET 9 end-of-support dates creates a forcing function. Every .NET application in your portfolio needs to be on .NET 10 by November 2026.&lt;/p&gt;

&lt;p&gt;But this is not just about avoiding end-of-life. .NET 10 delivers genuine improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance gains&lt;/strong&gt; that reduce infrastructure costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security features&lt;/strong&gt; that accelerate compliance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI integration&lt;/strong&gt; that positions you for the future&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three years of LTS support&lt;/strong&gt; that provides stability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start your assessment now. Identify your applications, understand your dependencies, and plan your migration timeline. The runway to November 2026 is shorter than it appears.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>dotnetframework</category>
    </item>
    <item>
      <title>A Review of AI-Assisted Development Tools and My Workflow</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Thu, 15 Jan 2026 11:28:22 +0000</pubDate>
      <link>https://forem.com/ismcagdas/a-review-of-ai-assisted-development-tools-and-my-workflow-39fl</link>
      <guid>https://forem.com/ismcagdas/a-review-of-ai-assisted-development-tools-and-my-workflow-39fl</guid>
      <description>&lt;p&gt;The world of software development is buzzing with the promise of Artificial Intelligence, and like many of you, I've been exploring the growing landscape of AI-assisted development tools. As a .NET/ASP.NET Core developer and open-source contributor, I've been piecing together a workflow that helps me leverage these powerful assistants. It's been a journey of discovery, full of pleasant surprises and a few hurdles.&lt;/p&gt;

&lt;p&gt;Here's a look at the tools in my current rotation and the workflow I've settled on for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  My AI Toolkit: A Review of Development Assistants
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vibe Kanban: The Mission Control
&lt;/h3&gt;

&lt;p&gt;I start most of my tasks in Vibe Kanban. Its strength lies in its flexibility. I can connect it to multiple repositories and, more importantly, assign different AI models to different tasks. I have access to GitHub Copilot, Gemini, and Claude, and Vibe Kanban lets me switch between them seamlessly. This is perfect for running multiple tasks in parallel, though I've found that reviewing the generated output is still a time-consuming but necessary step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf5msiw0xa9g5z4gld1o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf5msiw0xa9g5z4gld1o.jpg" alt=" " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude: The Master Planner
&lt;/h3&gt;

&lt;p&gt;Claude is my go-to for planning. I find it's excellent at understanding programming concepts and laying out a structured plan. The main drawback is the token expiration, which can sometimes be a bit of a nuisance. If I have enouhg limit, mostly I ask Claude to implement Phase 1 of the plan it created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F344h52cbz0l1w1bszeqe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F344h52cbz0l1w1bszeqe.jpg" alt=" " width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor: The Coder
&lt;/h3&gt;

&lt;p&gt;When it's time to write code, I turn to Cursor. Its "auto mode" is a standout feature, as it's incredibly efficient with token usage, which is a major concern in AI-assisted development. However, as a .NET developer, I sometimes find it challenging to work on my projects within Cursor and occasionally have to switch back to Rider or Visual Studio for certain tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini: The Technical Writer
&lt;/h3&gt;

&lt;p&gt;Interestingly, I don't use Gemini much for coding. Instead, it has become my trusted partner for writing technical articles and documentation. In this area, it truly excels.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Copilot: The Dependable Backup
&lt;/h3&gt;

&lt;p&gt;I use GitHub Copilot less frequently than the others, but it's a reliable tool for smaller tasks, especially when I've run out of tokens on other platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  My AI-Powered Development Workflow
&lt;/h2&gt;

&lt;p&gt;My process has evolved into a multi-stage workflow that leverages the strengths of different AI tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Plan with Claude&lt;/strong&gt;: I start by asking Claude to create a detailed plan in a markdown format using Vibe Kanban.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Review and Refine&lt;/strong&gt;: I thoroughly review the plan. If any adjustments are needed, I'll work with Claude to refine it.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Branch and Commit&lt;/strong&gt;: Once the plan is solid, I create a new branch and commit the plan file. This provides clear context for the work that follows.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Code with Cursor&lt;/strong&gt;: With the plan in hand, I open Cursor and begin the development work, following the roadmap laid out by Claude.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;AI-Assisted Review&lt;/strong&gt;: After the initial coding is done, I use another AI to review the changes and suggest improvements.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Manual Verification&lt;/strong&gt;: The final step is always a manual review and testing of the functionality to ensure everything works as expected.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;My next goal is to automate the testing phase. I plan to create a process that runs automated tests before I begin my manual review, which should help streamline the final verification step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Your Workflow?
&lt;/h2&gt;

&lt;p&gt;This is just a snapshot of my current process, and I'm sure it will continue to evolve. I'm curious to hear about your experiences. What tools are you using for AI-assisted development, and what does your workflow look like? Feel free to share your thoughts and recommendations!&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>vibecoding</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>An Opinionated Solution Structure for ASP.NET Core Projects</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Mon, 12 Jan 2026 12:23:07 +0000</pubDate>
      <link>https://forem.com/ismcagdas/an-opinionated-solution-structure-for-aspnet-core-projects-8ld</link>
      <guid>https://forem.com/ismcagdas/an-opinionated-solution-structure-for-aspnet-core-projects-8ld</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0u1sz70p6tqgemwmzh84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0u1sz70p6tqgemwmzh84.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
As software projects grow, maintaining a clean and organized codebase becomes increasingly challenging. A well-thought-out solution structure can make the difference between a maintainable application and a tangled mess of dependencies. In this article, I'll walk you through the opinionated solution structure we use in &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework&lt;/a&gt; — a structure that has proven itself in thousands of production applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Solution Structure Matters
&lt;/h2&gt;

&lt;p&gt;Before diving into the details, let's understand why investing time in your solution structure pays off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Clear boundaries make code easier to understand and modify&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt;: Well-separated layers are easier to test in isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team Collaboration&lt;/strong&gt;: Developers can work on different layers without conflicts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: A good structure grows with your application&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Root Level
&lt;/h2&gt;

&lt;p&gt;We have a sample project named Acme.BookStore. I will try to explain the solution structure using this sample ASP.NET Core application.&lt;br&gt;
Let's start with what you'll find at the root of the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Acme.BookStore/
├── src/                    # Source projects
├── test/                   # Test projects
├── Acme.BookStore.sln      # Solution file
├── common.props            # Shared MSBuild properties
├── global.json             # SDK version pinning
└── NuGet.Config            # Package source configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The separation of &lt;code&gt;src/&lt;/code&gt; and &lt;code&gt;test/&lt;/code&gt; folders provides immediate clarity. The &lt;code&gt;common.props&lt;/code&gt; file centralizes build configurations, ensuring consistency across all projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Projects: A Layered Architecture
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;src/&lt;/code&gt; folder contains the heart of your application, organized into distinct layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Shared (&lt;code&gt;Acme.BookStore.Domain.Shared&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is the foundation layer with &lt;strong&gt;zero dependencies&lt;/strong&gt; on other project layers. It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constants and enums&lt;/li&gt;
&lt;li&gt;Shared value objects&lt;/li&gt;
&lt;li&gt;Localization resources&lt;/li&gt;
&lt;li&gt;Exception codes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: BookType enum that can be shared across all layers&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;BookType&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Adventure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Biography&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fiction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Science&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why separate this?&lt;/strong&gt; These elements are often needed by multiple layers and even external clients. Keeping them in a dedicated project prevents circular dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain (&lt;code&gt;Acme.BookStore.Domain&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The core business logic lives here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entities&lt;/strong&gt; and aggregate roots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository interfaces&lt;/strong&gt; (not implementations!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain services&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain events&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AggregateRoot&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BookType&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;PublishDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This layer is &lt;strong&gt;infrastructure-agnostic&lt;/strong&gt; — it doesn't know about databases, APIs, or UI frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Contracts (&lt;code&gt;Acme.BookStore.Application.Contracts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This project defines the &lt;strong&gt;application layer's public API&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Transfer Objects (DTOs)&lt;/li&gt;
&lt;li&gt;Application service interfaces&lt;/li&gt;
&lt;li&gt;Permission definitions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBookAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IApplicationService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PagedResultDto&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetBookListDto&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateBookDto&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key benefit&lt;/strong&gt;: This project can be shared with clients (like a Blazor WebAssembly app) without exposing implementation details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application (&lt;code&gt;Acme.BookStore.Application&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Implementation of the application services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application service implementations&lt;/li&gt;
&lt;li&gt;Object mapping configurations&lt;/li&gt;
&lt;li&gt;Business workflow orchestration
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ApplicationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBookAppService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_bookRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_bookRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ObjectMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Entity Framework Core (&lt;code&gt;Acme.BookStore.EntityFrameworkCore&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Infrastructure layer for data access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DbContext&lt;/code&gt; implementation&lt;/li&gt;
&lt;li&gt;Repository implementations&lt;/li&gt;
&lt;li&gt;Entity configurations&lt;/li&gt;
&lt;li&gt;Database migrations
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookStoreDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbpDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookStoreDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Books&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Books"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;HasMaxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTTP API (&lt;code&gt;Acme.BookStore.HttpApi&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;API controllers that expose your application services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/books"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbpController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IBookAppService&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{id}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTTP API Client (&lt;code&gt;Acme.BookStore.HttpApi.Client&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is a powerful pattern — &lt;strong&gt;typed HTTP client proxies&lt;/strong&gt; for consuming your API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Consumers can use IBookAppService directly&lt;/span&gt;
&lt;span class="c1"&gt;// The proxy handles HTTP calls transparently&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GetBookListDto&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables code sharing between server and client applications, reducing duplication and ensuring type safety.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web (&lt;code&gt;Acme.BookStore.Web&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The UI layer — whether Razor Pages, Blazor, or MVC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages/Components&lt;/li&gt;
&lt;li&gt;View models&lt;/li&gt;
&lt;li&gt;Static assets&lt;/li&gt;
&lt;li&gt;UI-specific configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Database Migrator (&lt;code&gt;Acme.BookStore.DbMigrator&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;A console application for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running database migrations&lt;/li&gt;
&lt;li&gt;Seeding initial data&lt;/li&gt;
&lt;li&gt;DevOps-friendly deployment scenarios (Like updating all tenant databases if you use database-per tenant approach)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test Projects: Comprehensive Coverage
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;test/&lt;/code&gt; folder mirrors the source structure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TestBase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shared test infrastructure and utilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Domain.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unit tests for domain logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Application.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Application service integration tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EntityFrameworkCore.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repository and database tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HttpApi.Client.ConsoleTestApp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;End-to-end API testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Web.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UI layer tests&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This structure makes it clear &lt;strong&gt;what&lt;/strong&gt; you're testing and enables focused test runs during development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Benefits of This Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Clear Separation of Concerns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each project has a single, well-defined responsibility. Developers immediately know where to find and place code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Dependency Inversion in Practice&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The domain layer defines repository interfaces; the infrastructure layer implements them. Your business logic remains pure.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Shareable Contracts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;.Domain.Shared&lt;/code&gt; and &lt;code&gt;.Application.Contracts&lt;/code&gt; projects can be packaged as NuGet packages and shared:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Across microservices&lt;/li&gt;
&lt;li&gt;With client applications&lt;/li&gt;
&lt;li&gt;With external integrators&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Testability by Design&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each layer can be tested in isolation with appropriate mocking strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Database Independence&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Switching from SQL Server to PostgreSQL? Only the &lt;code&gt;EntityFrameworkCore&lt;/code&gt; project needs changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Ready for Growth&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This structure naturally evolves into modular monolith or microservices architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Monolith: Modular and Microservice Architectures
&lt;/h2&gt;

&lt;p&gt;While this article focuses on a single application structure, the same principles scale beautifully:&lt;/p&gt;

&lt;h3&gt;
  
  
  Modular Monolith
&lt;/h3&gt;

&lt;p&gt;You can organize your solution into &lt;strong&gt;independent modules&lt;/strong&gt;, each following this layered structure. Modules communicate through well-defined interfaces, giving you the benefits of microservices without the operational complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices
&lt;/h3&gt;

&lt;p&gt;Each microservice can follow this exact structure, with the &lt;code&gt;.Domain.Shared&lt;/code&gt; and &lt;code&gt;.Application.Contracts&lt;/code&gt; projects published as NuGet packages for inter-service communication.&lt;/p&gt;

&lt;p&gt;ABP Framework provides comprehensive templates and guidance for both architectures. Check out the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework GitHub repository&lt;/a&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular application templates&lt;/li&gt;
&lt;li&gt;Microservice solution templates&lt;/li&gt;
&lt;li&gt;Real-world sample applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you'd like to try this structure yourself, ABP Framework provides CLI tools to generate solutions with this exact architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; Volo.Abp.Studio.Cli
abp new Acme.BookStore &lt;span class="nt"&gt;-m&lt;/span&gt; none &lt;span class="nt"&gt;--theme&lt;/span&gt; leptonx-lite &lt;span class="nt"&gt;-csf&lt;/span&gt; &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"Server=(LocalDb)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;MSSQLLocalDB;Database=BookStore;Trusted_Connection=True;TrustServerCertificate=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, you can go to &lt;a href="https://abp.io/get-started" rel="noopener noreferrer"&gt;https://abp.io/get-started&lt;/a&gt; page and select other options like PostgreSQL, MongoDB, Angular, Blazor etc...&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A well-organized solution structure is an investment that pays dividends throughout your project's lifecycle. The layered architecture presented here — with its clear separation between domain, application, infrastructure, and presentation layers — provides a solid foundation for building maintainable, testable, and scalable ASP.NET Core applications.&lt;/p&gt;

&lt;p&gt;I encourage you to explore the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework on GitHub&lt;/a&gt; to see this structure in action across numerous modules and sample applications. As one of the developers of ABP Framework, I've seen firsthand how this architecture helps teams build robust applications efficiently.&lt;/p&gt;

&lt;p&gt;Whether you're building a simple CRUD application or an enterprise-grade distributed system, starting with a clean structure will serve you well. Happy coding!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions or feedback? Feel free to open an issue on the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework GitHub repository&lt;/a&gt; or join our community discussions.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  An Opinionated Solution Structure for ASP.NET Core Projects
&lt;/h1&gt;

&lt;p&gt;As software projects grow, maintaining a clean and organized codebase becomes increasingly challenging. A well-thought-out solution structure can make the difference between a maintainable application and a tangled mess of dependencies. In this article, I'll walk you through the opinionated solution structure we use in &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework&lt;/a&gt; — a structure that has proven itself in thousands of production applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Solution Structure Matters
&lt;/h2&gt;

&lt;p&gt;Before diving into the details, let's understand why investing time in your solution structure pays off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Clear boundaries make code easier to understand and modify&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt;: Well-separated layers are easier to test in isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team Collaboration&lt;/strong&gt;: Developers can work on different layers without conflicts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: A good structure grows with your application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Root Level
&lt;/h2&gt;

&lt;p&gt;We have a sample project named Acme.BookStore. I will try to explain the solution structure using this sample ASP.NET Core application.&lt;br&gt;
Let's start with what you'll find at the root of the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Acme.BookStore/
├── src/                    # Source projects
├── test/                   # Test projects
├── Acme.BookStore.sln      # Solution file
├── common.props            # Shared MSBuild properties
├── global.json             # SDK version pinning
└── NuGet.Config            # Package source configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The separation of &lt;code&gt;src/&lt;/code&gt; and &lt;code&gt;test/&lt;/code&gt; folders provides immediate clarity. The &lt;code&gt;common.props&lt;/code&gt; file centralizes build configurations, ensuring consistency across all projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Projects: A Layered Architecture
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;src/&lt;/code&gt; folder contains the heart of your application, organized into distinct layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Shared (&lt;code&gt;Acme.BookStore.Domain.Shared&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is the foundation layer with &lt;strong&gt;zero dependencies&lt;/strong&gt; on other project layers. It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constants and enums&lt;/li&gt;
&lt;li&gt;Shared value objects&lt;/li&gt;
&lt;li&gt;Localization resources&lt;/li&gt;
&lt;li&gt;Exception codes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: BookType enum that can be shared across all layers&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;BookType&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Adventure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Biography&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fiction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Science&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why separate this?&lt;/strong&gt; These elements are often needed by multiple layers and even external clients. Keeping them in a dedicated project prevents circular dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain (&lt;code&gt;Acme.BookStore.Domain&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The core business logic lives here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entities&lt;/strong&gt; and aggregate roots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository interfaces&lt;/strong&gt; (not implementations!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain services&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain events&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AggregateRoot&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BookType&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;PublishDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This layer is &lt;strong&gt;infrastructure-agnostic&lt;/strong&gt; — it doesn't know about databases, APIs, or UI frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Contracts (&lt;code&gt;Acme.BookStore.Application.Contracts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This project defines the &lt;strong&gt;application layer's public API&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Transfer Objects (DTOs)&lt;/li&gt;
&lt;li&gt;Application service interfaces&lt;/li&gt;
&lt;li&gt;Permission definitions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBookAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IApplicationService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PagedResultDto&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetBookListDto&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateBookDto&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key benefit&lt;/strong&gt;: This project can be shared with clients (like a Blazor WebAssembly app) without exposing implementation details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application (&lt;code&gt;Acme.BookStore.Application&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Implementation of the application services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application service implementations&lt;/li&gt;
&lt;li&gt;Object mapping configurations&lt;/li&gt;
&lt;li&gt;Business workflow orchestration
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ApplicationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBookAppService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_bookRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_bookRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ObjectMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Entity Framework Core (&lt;code&gt;Acme.BookStore.EntityFrameworkCore&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Infrastructure layer for data access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DbContext&lt;/code&gt; implementation&lt;/li&gt;
&lt;li&gt;Repository implementations&lt;/li&gt;
&lt;li&gt;Entity configurations&lt;/li&gt;
&lt;li&gt;Database migrations
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookStoreDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbpDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookStoreDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Books&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Books"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;HasMaxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTTP API (&lt;code&gt;Acme.BookStore.HttpApi&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;API controllers that expose your application services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/books"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbpController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IBookAppService&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{id}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BookDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTTP API Client (&lt;code&gt;Acme.BookStore.HttpApi.Client&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is a powerful pattern — &lt;strong&gt;typed HTTP client proxies&lt;/strong&gt; for consuming your API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Consumers can use IBookAppService directly&lt;/span&gt;
&lt;span class="c1"&gt;// The proxy handles HTTP calls transparently&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_bookAppService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GetBookListDto&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables code sharing between server and client applications, reducing duplication and ensuring type safety.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web (&lt;code&gt;Acme.BookStore.Web&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The UI layer — whether Razor Pages, Blazor, or MVC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages/Components&lt;/li&gt;
&lt;li&gt;View models&lt;/li&gt;
&lt;li&gt;Static assets&lt;/li&gt;
&lt;li&gt;UI-specific configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Database Migrator (&lt;code&gt;Acme.BookStore.DbMigrator&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;A console application for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running database migrations&lt;/li&gt;
&lt;li&gt;Seeding initial data&lt;/li&gt;
&lt;li&gt;DevOps-friendly deployment scenarios (Like updating all tenant databases if you use database-per tenant approach)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test Projects: Comprehensive Coverage
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;test/&lt;/code&gt; folder mirrors the source structure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TestBase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shared test infrastructure and utilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Domain.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unit tests for domain logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Application.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Application service integration tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EntityFrameworkCore.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repository and database tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HttpApi.Client.ConsoleTestApp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;End-to-end API testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Web.Tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UI layer tests&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This structure makes it clear &lt;strong&gt;what&lt;/strong&gt; you're testing and enables focused test runs during development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Benefits of This Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Clear Separation of Concerns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each project has a single, well-defined responsibility. Developers immediately know where to find and place code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Dependency Inversion in Practice&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The domain layer defines repository interfaces; the infrastructure layer implements them. Your business logic remains pure.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Shareable Contracts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;.Domain.Shared&lt;/code&gt; and &lt;code&gt;.Application.Contracts&lt;/code&gt; projects can be packaged as NuGet packages and shared:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Across microservices&lt;/li&gt;
&lt;li&gt;With client applications&lt;/li&gt;
&lt;li&gt;With external integrators&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Testability by Design&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each layer can be tested in isolation with appropriate mocking strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Database Independence&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Switching from SQL Server to PostgreSQL? Only the &lt;code&gt;EntityFrameworkCore&lt;/code&gt; project needs changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Ready for Growth&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This structure naturally evolves into modular monolith or microservices architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Monolith: Modular and Microservice Architectures
&lt;/h2&gt;

&lt;p&gt;While this article focuses on a single application structure, the same principles scale beautifully:&lt;/p&gt;

&lt;h3&gt;
  
  
  Modular Monolith
&lt;/h3&gt;

&lt;p&gt;You can organize your solution into &lt;strong&gt;independent modules&lt;/strong&gt;, each following this layered structure. Modules communicate through well-defined interfaces, giving you the benefits of microservices without the operational complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices
&lt;/h3&gt;

&lt;p&gt;Each microservice can follow this exact structure, with the &lt;code&gt;.Domain.Shared&lt;/code&gt; and &lt;code&gt;.Application.Contracts&lt;/code&gt; projects published as NuGet packages for inter-service communication.&lt;/p&gt;

&lt;p&gt;ABP Framework provides comprehensive templates and guidance for both architectures. Check out the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework GitHub repository&lt;/a&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular application templates&lt;/li&gt;
&lt;li&gt;Microservice solution templates&lt;/li&gt;
&lt;li&gt;Real-world sample applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you'd like to try this structure yourself, ABP Framework provides CLI tools to generate solutions with this exact architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; Volo.Abp.Studio.Cli
abp new Acme.BookStore &lt;span class="nt"&gt;-m&lt;/span&gt; none &lt;span class="nt"&gt;--theme&lt;/span&gt; leptonx-lite &lt;span class="nt"&gt;-csf&lt;/span&gt; &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"Server=(LocalDb)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;MSSQLLocalDB;Database=BookStore;Trusted_Connection=True;TrustServerCertificate=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, you can go to &lt;a href="https://abp.io/get-started" rel="noopener noreferrer"&gt;https://abp.io/get-started&lt;/a&gt; page and select other options like PostgreSQL, MongoDB, Angular, Blazor etc...&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A well-organized solution structure is an investment that pays dividends throughout your project's lifecycle. The layered architecture presented here — with its clear separation between domain, application, infrastructure, and presentation layers — provides a solid foundation for building maintainable, testable, and scalable ASP.NET Core applications.&lt;/p&gt;

&lt;p&gt;I encourage you to explore the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework on GitHub&lt;/a&gt; to see this structure in action across numerous modules and sample applications. As one of the developers of ABP Framework, I've seen firsthand how this architecture helps teams build robust applications efficiently.&lt;/p&gt;

&lt;p&gt;Whether you're building a simple CRUD application or an enterprise-grade distributed system, starting with a clean structure will serve you well. Happy coding!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions or feedback? Feel free to open an issue on the &lt;a href="https://github.com/abpframework/abp" rel="noopener noreferrer"&gt;ABP Framework GitHub repository&lt;/a&gt; or join our community discussions.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>dotnet</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Modular Monolith Architecture is the Key to Effective AI-Assisted Development</title>
      <dc:creator>ismail Cagdas</dc:creator>
      <pubDate>Tue, 06 Jan 2026 13:53:35 +0000</pubDate>
      <link>https://forem.com/ismcagdas/why-modular-monolith-architecture-is-the-key-to-effective-ai-assisted-development-3cba</link>
      <guid>https://forem.com/ismcagdas/why-modular-monolith-architecture-is-the-key-to-effective-ai-assisted-development-3cba</guid>
      <description>&lt;p&gt;AI coding assistants have revolutionized how we write code. Tools like GitHub Copilot, Claude, ChatGPT, and Cursor have become indispensable companions for developers worldwide. However, there's a growing challenge that many developers are experiencing: &lt;strong&gt;as your codebase grows, AI-generated code quality decreases significantly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore why this happens and how &lt;a href="https://abp.io" rel="noopener noreferrer"&gt;ABP Framework&lt;/a&gt;'s modular monolith architecture provides an elegant solution to this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: AI Struggles with Large Codebases
&lt;/h2&gt;

&lt;p&gt;If you've been using AI coding assistants for a while, you've probably noticed a pattern. When you start a new project, AI suggestions are remarkably accurate. The code is clean, follows best practices, and integrates nicely with your existing code. But as your project grows to hundreds of files and thousands of lines of code, something changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Window Limitations
&lt;/h3&gt;

&lt;p&gt;AI models have a fundamental constraint: &lt;strong&gt;context windows&lt;/strong&gt;. Even the most advanced models can only process a limited amount of code at once. When your project has 500+ files with complex interdependencies, the AI simply cannot see the full picture.&lt;/p&gt;

&lt;p&gt;Consider this scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 MyLargeProject/
├── 📁 src/
│   ├── 📁 Domain/ (50+ files)
│   ├── 📁 Application/ (80+ files)
│   ├── 📁 Infrastructure/ (40+ files)
│   ├── 📁 HttpApi/ (60+ files)
│   └── 📁 Web/ (100+ files)
├── 📁 tests/ (150+ files)
└── 📁 shared/ (30+ files)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you ask AI to implement a new feature, it might see only 10-20 of these files in its context. The result? Code that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicates existing functionality&lt;/li&gt;
&lt;li&gt;Violates established patterns in your codebase&lt;/li&gt;
&lt;li&gt;Uses inconsistent naming conventions&lt;/li&gt;
&lt;li&gt;Creates unnecessary coupling between components&lt;/li&gt;
&lt;li&gt;Ignores your custom base classes and utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Consistency Problem
&lt;/h3&gt;

&lt;p&gt;In a large monolithic codebase, there are often multiple ways to accomplish the same task. Your team might have established specific patterns over time, but the AI doesn't know about these conventions unless they're explicitly provided in the context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Your established pattern (which AI doesn't see)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ApplicationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IProductAppService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_productRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ProductAppService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_productRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ProductDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_productRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ObjectMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProductDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// What AI might generate (inconsistent with your patterns)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OrderDto&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// Manual mapping...&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI-generated code works, but it introduces inconsistency, bypasses your repository abstractions, and ignores your mapping conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Modular Monolith Architecture
&lt;/h2&gt;

&lt;p&gt;This is where ABP Framework's modular monolith architecture shines. Instead of one massive codebase, you organize your application into &lt;strong&gt;isolated modules&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Module in ABP?
&lt;/h3&gt;

&lt;p&gt;An ABP module is a independent unit that encapsulates a specific business capability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 Acme.ProductManagement/
├── 📁 src/
│   ├── Acme.ProductManagement.Domain/
│   ├── Acme.ProductManagement.Domain.Shared/
│   ├── Acme.ProductManagement.Application/
│   ├── Acme.ProductManagement.Application.Contracts/
│   ├── Acme.ProductManagement.EntityFrameworkCore/
│   ├── Acme.ProductManagement.HttpApi/
│   └── Acme.ProductManagement.Web/
└── 📁 test/
    └── Acme.ProductManagement.Application.Tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each module has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear boundaries&lt;/strong&gt;: Well-defined interfaces for communication with other modules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent domain&lt;/strong&gt;: Its own entities, repositories, and domain services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolated application layer&lt;/strong&gt;: Application services that don't leak into other modules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focused scope&lt;/strong&gt;: Typically 10-30 files per layer, not hundreds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How This Helps AI
&lt;/h3&gt;

&lt;p&gt;When you work with AI on a modular codebase, you can &lt;strong&gt;scope the conversation to a single module&lt;/strong&gt;. Instead of providing context about your entire 500-file project, you provide context about a 50-file module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"I'm working on the ProductManagement module in an ABP Framework project.
Here's the module structure and key files:
- Product entity (Domain layer)
- IProductRepository interface
- ProductAppService (Application layer)

I need to add a feature to track product price history..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the AI has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A complete picture of the relevant code&lt;/li&gt;
&lt;li&gt;Clear patterns to follow&lt;/li&gt;
&lt;li&gt;Defined boundaries it shouldn't cross&lt;/li&gt;
&lt;li&gt;Consistent conventions throughout&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits of Module-Scoped AI Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Reduced Context Size = Better Understanding
&lt;/h3&gt;

&lt;p&gt;A typical ABP module contains a focused set of files that easily fit within AI context windows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;AI Understanding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Full Monolith&lt;/td&gt;
&lt;td&gt;500+&lt;/td&gt;
&lt;td&gt;Poor - sees fragments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single Module&lt;/td&gt;
&lt;td&gt;30-50&lt;/td&gt;
&lt;td&gt;Excellent - sees everything&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When AI can see your entire module, it understands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How entities relate to each other&lt;/li&gt;
&lt;li&gt;Which base classes and interfaces to use&lt;/li&gt;
&lt;li&gt;Your naming conventions and patterns&lt;/li&gt;
&lt;li&gt;The existing functionality to avoid duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. ABP Conventions Guide the AI
&lt;/h3&gt;

&lt;p&gt;ABP Framework follows strong conventions. When you tell AI you're working with ABP, it can leverage these conventions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AI understands ABP patterns and generates consistent code&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CategoryAppService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ProductManagementAppService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ICategoryAppService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ICategoryRepository&lt;/span&gt; &lt;span class="n"&gt;_categoryRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CategoryAppService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ICategoryRepository&lt;/span&gt; &lt;span class="n"&gt;categoryRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_categoryRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;categoryRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProductManagementPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CategoryDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateCategoryDto&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GuidGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_categoryRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InsertAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ObjectMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CategoryDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI naturally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inherits from the correct base class&lt;/li&gt;
&lt;li&gt;Uses the module's permission definitions&lt;/li&gt;
&lt;li&gt;Follows the repository pattern&lt;/li&gt;
&lt;li&gt;Uses ABP's &lt;code&gt;GuidGenerator&lt;/code&gt; and &lt;code&gt;ObjectMapper&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Easier Code Review
&lt;/h3&gt;

&lt;p&gt;When AI-generated code is confined to a module, code review becomes straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;

 src/Acme.ProductManagement.Domain/Categories/Category.cs        | 25 +++
 src/Acme.ProductManagement.Application/Categories/CategoryAppService.cs | 45 +++
 src/Acme.ProductManagement.HttpApi/Categories/CategoryController.cs     | 30 +++
 3 files changed, 100 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All changes are in one module. Reviewers familiar with that module can quickly validate the code quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Sustainable and Maintainable Code
&lt;/h3&gt;

&lt;p&gt;Modular code generated by AI remains maintainable because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It follows established patterns within the module&lt;/li&gt;
&lt;li&gt;Dependencies are explicit and limited&lt;/li&gt;
&lt;li&gt;The code can be understood in isolation&lt;/li&gt;
&lt;li&gt;Future AI sessions can easily pick up where you left off&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Tips for AI-Assisted ABP Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tip 1: Provide Module Context Upfront
&lt;/h3&gt;

&lt;p&gt;Start your AI conversation with module context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm working on an ABP Framework application.
Current module: Acme.Ordering
Module purpose: Handle customer orders and order processing

Key entities:
- Order (AggregateRoot)
- OrderLine (Entity)
- OrderStatus (Enum)

Existing services:
- IOrderRepository
- OrderManager (Domain Service)
- OrderAppService

I want to add a feature to...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tip 2: Reference ABP Conventions Explicitly
&lt;/h3&gt;

&lt;p&gt;When asking AI to generate code, mention the conventions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generate an Application Service for managing Shipments.
Follow ABP conventions:
- Inherit from ApplicationService
- Use IRepository&amp;lt;T, TKey&amp;gt; for data access
- Use ObjectMapper for DTO mapping
- Define permissions in ShipmentPermissions class
- Use [Authorize] attributes for permission checks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the following versions of ABP, these instructions will be included in your project out of the box. So, AI will write better and maintainable code by following ABP standards and best practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tip 3: Keep Cross-Module Communication Explicit
&lt;/h3&gt;

&lt;p&gt;When your feature spans multiple modules, break it down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1: Add the event class in Ordering.Domain.Shared
Step 2: Publish the event from OrderAppService
Step 3: (Separate session) Handle the event in Shipping module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps each AI session focused on one module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tip 4: Use Module Templates as Examples
&lt;/h3&gt;

&lt;p&gt;Provide AI with examples from your existing module code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Here's how we implement app services in this module:

[Example of existing ProductAppService]

Now create a similar service for handling Categories.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tip 5: Validate Within Module Boundaries
&lt;/h3&gt;

&lt;p&gt;After AI generates code, verify it respects module boundaries:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good&lt;/strong&gt;: Module references only its own layers and shared contracts&lt;br&gt;
❌ &lt;strong&gt;Bad&lt;/strong&gt;: Direct references to other module's domain or application layers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Bad - crossing module boundaries&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Acme.Inventory.Domain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Direct reference to another module's domain!&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Good - using integration events or shared contracts&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Acme.Inventory.Application.Contracts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Only reference contracts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Example: Before and After
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before: AI in a Large Monolith
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;: "Add a feature to apply discounts to orders"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Result&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates discount logic directly in OrderController&lt;/li&gt;
&lt;li&gt;Duplicates validation that exists in another service&lt;/li&gt;
&lt;li&gt;Uses direct database access instead of repositories&lt;/li&gt;
&lt;li&gt;Ignores existing Price calculation utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time spent fixing&lt;/strong&gt;: 2 hours&lt;/p&gt;

&lt;h3&gt;
  
  
  After: AI with Module Focus
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In the Acme.Ordering module, add discount support.
- Add DiscountInfo value object to Order aggregate
- Add ApplyDiscount method to Order entity
- Update OrderAppService.CreateAsync to accept discount code
- Use existing IDiscountValidator from Ordering.Domain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Result&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Correctly extends Order aggregate&lt;/li&gt;
&lt;li&gt;Follows existing patterns in the module&lt;/li&gt;
&lt;li&gt;Uses the domain service you mentioned&lt;/li&gt;
&lt;li&gt;Generates consistent, reviewable code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time spent fixing&lt;/strong&gt;: 15 minutes&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The modular monolith architecture isn't just an architectural pattern—it's becoming essential for effective AI-assisted development. As AI tools continue to evolve, codebases that are organized into clear, focused modules will get significantly better results from these tools.&lt;/p&gt;

&lt;p&gt;ABP Framework's modular architecture, with its strong conventions, clear boundaries, and standardized patterns, creates an ideal environment for AI-assisted development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modules provide focused context&lt;/strong&gt; that AI can fully understand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ABP conventions&lt;/strong&gt; guide AI to generate consistent, framework-aligned code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear boundaries&lt;/strong&gt; prevent AI from creating unwanted dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized patterns&lt;/strong&gt; make AI-generated code predictable and maintainable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building applications with AI assistance (and who isn't these days?), consider how your architecture affects AI code quality. Investing in a modular structure with ABP Framework pays dividends not just in traditional software engineering benefits, but in dramatically improved AI-assisted development workflows.&lt;/p&gt;

&lt;p&gt;The future of development is human-AI collaboration. Make sure your architecture is ready for it.&lt;/p&gt;

&lt;p&gt;To learn more about ABP Framework, visit it's &lt;a href="https://abp.io/docs/latest/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you experienced similar challenges with AI in large codebases? Share your experiences and tips in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>codequality</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
