Skip to main content

01 - Intro

What this course is really about

This course is about building web applications with C# and ASP.NET Core, but the long-term topic is architecture.

We will use ASP.NET Core and EF Core as practical tools, but the bigger question is this:

How do you structure a codebase so that it stays understandable when the project grows?

That is why this lecture is a map of the course, not a deep technical tutorial.

The big picture

Most applications in this course follow the same high-level flow:

Browser / frontend client
↓ HTTP
ASP.NET Core application

Business logic

Database

Sometimes the ASP.NET Core application returns HTML for a browser. Sometimes it returns JSON for another program. The transport is still HTTP.

What we are going to build

There are two main kinds of outputs in this course:

  • Server-rendered web applications
    • ASP.NET Core MVC or Razor Pages
    • the server returns HTML
  • Web APIs
    • ASP.NET Core Web API
    • the server returns JSON or other serialized data

Both use the same platform. The main difference is what the client expects in the response.

What the next lectures will cover

This lecture stays high level. The next lectures go into the mechanics in detail:

  1. ASP.NET Core
    • project structure
    • controllers, views, routing, model binding, middleware
    • MVC and Web API
  2. EF Core
    • entities, DbContext, relationships, migrations, queries
    • how relational databases fit into ASP.NET Core applications
  3. Architecture
    • N-tier as a baseline
    • Clean / Onion architecture
    • modular monoliths
    • microservices and their trade-offs

So the course starts with framework basics, but architecture becomes the main focus.

HTTP in one page

Web applications and APIs communicate over HTTP.

Every interaction is basically:

  • a request from client to server
  • a response from server to client

Common HTTP methods:

  • GET - read data
  • POST - create data or submit a form
  • PUT / PATCH - update data
  • DELETE - remove data

Common response codes:

  • 200 OK
  • 201 Created
  • 204 No Content
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 500 Internal Server Error

For APIs in this course, the most common data format is JSON.

MVC vs Web API

ASP.NET Core supports both server-rendered applications and APIs.

MVC / Razor Pages

  • Best when the server renders HTML
  • Good for classic CRUD apps, admin panels, and internal tools
  • Browser talks directly to the ASP.NET Core app

Web API

  • Best when the server returns data instead of HTML
  • Good when the backend is consumed by JavaScript, mobile apps, or another backend
  • The client app becomes separate from the server

The important idea is that these are not separate worlds. They are two delivery styles on top of the same platform.

Why EF Core matters

Almost every real application needs persistence.

Entity Framework Core gives us:

  • entity classes
  • DbContext
  • LINQ queries
  • relationship mapping
  • migrations

EF Core is a productivity tool, not magic.

You still need to understand:

  • relational data
  • keys and relationships
  • SQL basics
  • what kind of SQL your ORM generates

If the generated SQL is bad, the application is still bad.

Architecture progression in this course

The course is not just about building one app. It is about seeing how architecture evolves as complexity grows.

1. N-tier as the baseline

The starting point is usually something like this:

Web -> Services -> Data Access -> Database

This is simple, fast to explain, and good enough for many small systems.

It also teaches useful habits:

  • controllers should not do everything
  • business logic should not live in views
  • data access should not be scattered across the whole app

But N-tier has an important weakness: dependencies usually flow toward the data access layer. That makes large systems harder to test and harder to change.

2. Clean / Onion architecture

Later we revisit the same problem and flip the dependency direction:

Infrastructure -> Domain <- Application <- Web

The core idea is simple:

  • business rules should be at the center
  • frameworks and databases should stay on the outside
  • external technology choices should be replaceable

This is where dependency inversion becomes practical, not theoretical.

3. Modular monolith

Even clean layers are not enough if the whole system becomes one tangled blob.

A modular monolith keeps one deployment, but splits the codebase into clear modules with explicit boundaries.

One deployable application
└── multiple internal modules

This is often the most useful real-world middle ground:

  • simpler than microservices
  • more structured than a classic monolith
  • easier to evolve later

4. Microservices

Microservices go one step further:

  • separate deployables
  • separate ownership boundaries
  • communication over the network

That can help in the right context, but it also introduces new problems:

  • distributed communication
  • partial failures
  • eventual consistency
  • deployment and monitoring overhead

So the point of this course is not "microservices are modern, therefore use them". The point is to understand when extra architectural complexity is justified and when it is not.

Low coupling and high cohesion

Two ideas will keep showing up throughout the course:

  • Low coupling
    • one part of the system should not know too much about another part
    • a change in one area should not force unrelated changes elsewhere
  • High cohesion
    • code that belongs together should stay together
    • one module or class should have one clear reason to exist

If you remember only one architecture heuristic from this lecture, remember this:

Low coupling between parts, high cohesion inside parts.

Web services in this course

In a broad sense, a web service means program-to-program communication over the web.

In this course, when we say "service" or "API", we usually mean:

  • HTTP
  • JSON
  • REST-style endpoints
  • OpenAPI / Swagger documentation

SOAP still exists in enterprise systems, but it is not the main focus here.

What the course is trying to teach you

This course is not mainly about memorizing framework APIs.

It is trying to teach you how to:

  • build working ASP.NET Core applications
  • persist data with EF Core
  • expose and consume APIs over HTTP
  • keep controllers thin and responsibilities clear
  • understand why architectural boundaries exist
  • make trade-offs instead of copying trends

Practical mindset for the course

A few working rules:

  • Start simple, but structure the code so it can evolve.
  • Do not put all logic into controllers.
  • Do not treat EF Core as a substitute for database knowledge.
  • Do not choose microservices just because the word sounds modern.
  • Prefer designs you can explain and defend.
  • AI can help with implementation, but it does not replace design judgment.

Course aims

By the end of the course, you should be able to:

  • build ASP.NET Core MVC applications and Web APIs
  • use EF Core for common relational data access tasks
  • explain the difference between N-tier, Clean / Onion, modular monolith, and microservices
  • choose an architecture appropriate to the problem
  • justify your technical decisions in terms of coupling, cohesion, maintainability, and trade-offs

One-sentence summary

We will use ASP.NET Core and EF Core to learn not only how to build web applications, but how to structure them so they remain maintainable as they grow.

Some drawings to visualize the concepts

Clean Architecture

Clean

Modular monolith

modular

modular

modular

Microservices

micro

How to communicate between modules?

  • Synchronous communication between modules is easy to implement, and it's performant. But it comes at the cost of tight coupling between modules.
  • Asynchronous communication using a message broker is loosely coupled. But it's more complex to implement.

We will look into mediator pattern (behavioral design pattern that lets you reduce chaotic dependencies between objects).

HTTP Reminder

  • Request
GET https://localhost:44363/People/Create HTTP/1.1
Host: localhost:44363
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://localhost:44363/People
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,et;q=0.8
Cookie: _ga=GA1.1.1433392067.1524809543;
  • Response
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcYWthdmVyXHNvdXJjZVxyZXBvc1xIVFRQVGVzdFxXZWJBcHBcUGVvcGxlXENyZWF0ZQ==?=
X-Powered-By: ASP.NET
Date: Sat, 26 Jan 2019 12:24:13 GMT
Content-Length: 3367

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Create - WebApp</title>

HTTP - POST

  • Request
POST https://localhost:44363/People/Create HTTP/1.1
Host: localhost:44363
Connection: keep-alive
Content-Length: 194
Cache-Control: max-age=0
Origin: https://localhost:44363
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://localhost:44363/People/Create
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,et;q=0.8
Cookie: _ga=GA1.1.1433392067.1524809543;

Name=Andres&__RequestVerificationToken=CfDJ8JXfYWVYzpxPgG_38dOFAzHQGkoaDtNMXtzBr3vNUFUDOYe7XT_ueh6IMyEfRXYWTTOvd2Bjm8gxjOwN8jRBGngeIIKZmnJB-xD4Wvd1enqy0M5GrgAWVgAOg0vZPgHNzvIYDBTmwJqi3L2WYM-5mm4
  • Response
HTTP/1.1 302 Found
Location: /People
Server: Microsoft-IIS/10.0
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcYWthdmVyXHNvdXJjZVxyZXBvc1xIVFRQVGVzdFxXZWJBcHBcUGVvcGxlXENyZWF0ZQ==?=
X-Powered-By: ASP.NET
Date: Sat, 26 Jan 2019 12:17:16 GMT
Content-Length: 0

Response codes

  • 1xx Informational response
    • 100 continue
    • 101 switching protocols
  • 2xx Success
    • 200 OK
    • 201 Created
    • 202 Accepted
    • 204 No Content
  • 3xx Redirection
    • 300 Multiple choices
    • 301 Moved Permanently
    • 302 Found
    • 303 See other
    • 304 Not Modified
  • 4xx Client errors
    • 400 Bad Request
    • 401 Unauthorized
    • 403 Forbidden
    • 404 Not Found
    • 409 Conflict
  • 5xx Server errors
    • 500 Internal Server Error
    • 501 Not implemented
    • 503 Service Unavailable

What to Know for Code Defense

Be prepared to explain:

  1. Why start with N-tier before Clean Architecture? — N-tier teaches the fundamentals of layer separation. You need to feel the coupling pain of downward-pointing dependencies before dependency inversion makes practical sense.
  2. Why does architecture matter if the app is small? — Small apps grow. Structuring code so it can evolve prevents rewrites later. The cost of adding structure early is low; the cost of restructuring a tangled codebase later is high.
  3. What is the difference between MVC and Web API in ASP.NET Core? — They are two delivery styles on the same platform. MVC returns HTML for browsers; Web API returns serialized data (JSON) for programmatic clients. The underlying middleware, routing, and DI infrastructure are shared.
  4. Why is "low coupling, high cohesion" the central architecture heuristic? — Low coupling means a change in one part does not force unrelated changes elsewhere. High cohesion means code that belongs together stays together. Together they make systems understandable, testable, and evolvable.
  5. Why not jump straight to microservices? — Microservices add distributed communication, partial failures, eventual consistency, and deployment overhead. These costs are only justified when organizational or scaling constraints demand separate deployables. Most projects benefit more from a well-structured monolith or modular monolith.
  6. Why is EF Core not a substitute for SQL knowledge? — EF Core generates SQL. If the generated SQL is inefficient, the application is still slow. Understanding relational data, keys, indexes, and joins is necessary to evaluate and optimize what the ORM produces.