โหมดมืด
บทที่ 0 — ASP.NET Core คืออะไร และทำงานยังไง
📌 อ่านก่อน — ควรผ่าน csharp/ มาถึงบท async มาก่อน async คือการเขียนโค้ดที่รอผล (เช่น รอ database ตอบ) โดยไม่บล็อกโปรแกรมทั้งตัว — สอนเต็มใน csharp/บทที่ 11 เล่มนี้ใช้ async ตั้งแต่ต้น ถ้ายังไม่เคยเห็น
async/awaitมาก่อน ให้จำแค่ว่า: เวลาเห็นคำว่าasyncหน้า method และawaitหน้าคำสั่งที่ต้องรอ (เช่น query database) แปลว่าโปรแกรมจะไปทำงานอื่นระหว่างรอ แทนที่จะหยุดนิ่งเฉย ๆ — พอผลลัพธ์มาค่อยกลับมาทำต่อจากจุดนั้น รายละเอียดจริงเรียนเต็มในบทที่ 11
🧱 เวอร์ชัน baseline ของหนังสือ (last reviewed: 2026-06 — ตรวจ release notes ทางการก่อนใช้) ตัวอย่างในเล่มใช้ syntax ระดับ .NET 8 LTS เป็นพื้น (คือเวอร์ชันต่ำสุดที่ตัวอย่างในเล่มนี้ยังใช้งานได้ — รันได้ไม่ error) — ตัวอย่างควรรันได้บน .NET 9 และ .NET 10 ด้วย และยกบาง API ของ .NET 9 STS (เช่น
AddOpenApi) มาเสริมเป็นจุด ๆสำหรับโปรเจกต์ใหม่ปี 2026: แนะนำติดตั้ง .NET 10 LTS (GA ปลายปี 2026) แทน .NET 8 — syntax พื้นฐานเหมือนกัน แต่จะรับ support ยาวกว่า (.NET 8 EOL พฤศจิกายน 2026) ถ้ายังใช้ .NET 8 อยู่ ตัวอย่างทั้งหมดยังใช้ได้
CI/CD ในบทที่ 4 ตั้ง (pin = ตรึงเวอร์ชัน) ไว้ที่
8.0.xเป็นค่าเริ่มต้นเพื่อรักษาความเข้ากันได้กับ LTS ตัวเก่า — ทีมคุณเปลี่ยนเป็นเวอร์ชันที่ใช้จริงได้หมายเหตุเรื่องเวอร์ชัน:
- .NET 8 LTS ยัง support ถึงพฤศจิกายน 2026
- .NET 10 LTS GA (General Availability — ปล่อยใช้จริง) ปลายปี 2026 และ syntax พื้นฐานเหมือนเดิม — แนะนำสำหรับโปรเจกต์ใหม่
- ก่อนอัปเดตเวอร์ชัน ให้เช็ค breaking change (การเปลี่ยนที่ทำให้โค้ดเก่าพัง) ใน release notes ก่อนเสมอ
🧭 บทนี้ปูภาพรวมก่อน — ส่วนต้น ๆ จะอธิบายแนวคิดพื้นฐาน (pipeline = สายท่อที่ request วิ่งผ่าน, DI = Dependency Injection การฉีด dependency ให้อัตโนมัติ) ซึ่งช่วยให้เข้าใจบทถัด ๆ ไป ถ้าอยากลงมือเขียนโค้ดเลย ข้ามไปที่ส่วน "Hello World" (หัวข้อ 14) หรือ Checkpoint ท้ายบทได้ แล้วค่อยย้อนกลับมาอ่านทฤษฎีทีหลัง — ลำดับหัวข้อจริงไม่ได้เปลี่ยน แค่ชี้ทางลัดให้
API (Application Programming Interface) = ช่องทางให้โปรแกรมคุยกัน เช่น เว็บหน้าบ้านยิงคำขอมาขอข้อมูลจากเซิร์ฟเวอร์
ASP.NET Core คือ framework (ชุดเครื่องมือสำเร็จรูป) ที่หนังสือเล่มนี้ใช้เขียน API ด้วยภาษา C# — ส่วน "ASP.NET Framework" ที่จะเทียบให้ดูในหัวข้อถัดไป คือรุ่นเก่าก่อนหน้านี้ (ปิดตัวไปแล้ว ไม่แนะนำให้ใช้กับโปรเจกต์ใหม่)
ก่อนเขียน API บรรทัดแรก เราจะตอบคำถาม 5 ข้อ:
- ASP.NET Core ต่างจาก ASP.NET Framework เก่ายังไง
- Host + Pipeline + DI ทำงานยังไง
- Kestrel คืออะไร — ทำไมเร็ว
- Minimal API vs Controller — เลือกอะไร
- เทียบ ASP.NET Core vs Spring Boot vs Express/NestJS
1. ประวัติฉบับย่อ
ASP.NET Framework (เก่า, 2002-2018) — Windows only (รันได้แต่ Windows), IIS (Internet Information Services — web server ของ Windows) integration ลึก, monolith (ระบบก้อนเดียวขนาดใหญ่) ใหญ่
ASP.NET Core (2016+) — เขียนใหม่หมด:
- Cross-platform (ทำงานข้ามระบบปฏิบัติการ Win/Linux/Mac)
- Modular (เลือก middleware ที่ใช้ — ตัวคั่นกลางที่ประมวลผล request, อธิบายต่อหัวข้อ 2)
- Built-in DI (มี Dependency Injection ในตัว — การฉีด dependency ให้อัตโนมัติ, อธิบายหัวข้อ 3)
- Embedded web server (มี web server ฝังมาในตัว ชื่อ Kestrel)
- เร็วกว่า ASP.NET Framework เก่ามาก (ตัวเลข exact ขึ้นกับ workload — ดู Microsoft blog "Performance Improvements in .NET" รายปี และ TechEmpower round ล่าสุดเพื่อตัวเลขที่อ้างได้)
ในหนังสือเล่มนี้ "ASP.NET" = ตัวใหม่ (Core) เสมอ
2. Request Pipeline — Middleware
Middleware = ตัวคั่นกลางที่ประมวลผล request ระหว่างทาง ก่อนถึงโค้ดหลัก (เช่น ตรวจ token, redirect เป็น HTTPS, log)
Middleware ทำงานเรียงเป็นชั้น ๆ ทั้งขาเข้าและขากลับ ลองนึกภาพแบบนี้:
- ขาเข้า — request เหมือนจดหมายที่ต้องผ่านด่านหลายชั้นก่อนถึงปลายทาง (โค้ดที่ตอบจริง) ด่านแรกตรวจอย่างหนึ่งแล้วส่งต่อด่านสอง ด่านสองตรวจอีกอย่างแล้วส่งต่อด่านสาม ไปเรื่อย ๆ
- ขากลับ — พอตอบเสร็จ คำตอบ (response) เดินทางย้อนกลับผ่านด่านเดิมทีละชั้นจนถึง client
- รูปทรง — ลักษณะ "เข้าทีละชั้น–ออกย้อนชั้น" นี้เหมือน ตุ๊กตาแม่ลูกดก (matryoshka / Russian doll pattern) ที่ซ้อนกันเป็นชั้น ๆ
Middleware = function ที่ "ครอบ" handler (handler = โค้ดที่ตอบ request จริง) — นี่คือ matryoshka / Russian doll pattern ที่อธิบายไว้ข้างบน
ลำดับการลงทะเบียน middleware = ลำดับการทำงาน → สำคัญมาก (ลงทะเบียนก่อน = ทำงานก่อน)
3. Built-in Dependency Injection
Dependency Injection (DI — การฉีด dependency ให้อัตโนมัติ) = แทนที่จะให้ class สร้างของที่มันต้องใช้เอง เราบอก framework ว่า class นี้ต้องใช้อะไร แล้ว framework "ฉีด" ให้ตอนสร้าง
เหมือนสั่งอาหารในร้าน — แทนที่คุณจะลุกไปหาวัตถุดิบมาทำอาหารเอง คุณแค่บอกว่าอยากได้อะไร แล้วคนเสิร์ฟนำมาให้
ข้อดีคือสลับ implementation (เช่นเปลี่ยนจากฐานข้อมูลจริงเป็นตัวปลอมตอนเทสต์) และเขียน test ได้ง่ายขึ้นมาก (ลงลึกในบทที่ 7)
ASP.NET Core มี DI container (ตัวเก็บและแจกจ่าย service ในแอป — ในที่นี้ไม่ใช่ Docker container) ในตัว — ไม่ต้องใช้ library ภายนอกอย่าง Autofac/Ninject เหมือนสมัยเก่า
csharp
var builder = WebApplication.CreateBuilder(args);
// IClock, IUserRepository, IPriceCalculator คือ interface (สัญญาว่าจะมี method บางอย่าง)
// ชื่อขึ้นต้นด้วย I ตามขนบ C# — ดูเพิ่มใน csharp/บท OOP
builder.Services.AddSingleton<IClock, SystemClock>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddTransient<IPriceCalculator, PriceCalculator>(); // helper เล็ก ๆ ไม่มี state💡 ของใหม่ใน .NET 8+ —
TimeProvider(อยู่ในSystem) เป็น abstraction สำหรับเวลาที่ Microsoft แนะนำให้ใช้ในโปรเจกต์ใหม่แทนIClockที่เขียนเอง (test เวลา fake ได้ง่ายในตัว) ตัวอย่างIClockข้างบนเก็บไว้เพื่อสื่อแนวคิด
Lifetime (อายุของ instance — สร้างใหม่บ่อยแค่ไหน) 3 แบบ:
ก่อนดูตาราง: stateless service = service ที่ไม่เก็บสถานะระหว่างการเรียก เรียกกี่ครั้งผลก็เหมือนเดิม (เช่น ตัวคำนวณราคา ที่รับ input → คืน output โดยไม่จำอะไร) cache = ที่พักข้อมูลไว้ใช้ซ้ำเพื่อไม่ต้องคำนวณหรือ query ใหม่
| Lifetime | สร้างเมื่อ | ใช้กับ |
|---|---|---|
| Singleton | ครั้งเดียวต่อ app (ใช้ตัวเดิมตลอด) | stateless service, config, cache |
| Scoped | ครั้งเดียวต่อ HTTP request | DB context (ตัวเชื่อม database), request data |
| Transient | ทุกครั้งที่ inject (ฉีดทีไรสร้างใหม่ทุกที) | lightweight helper (ตัวช่วยเล็ก ๆ) |
⚠️ กับดักที่เจอบ่อยที่สุด — Singleton ห้าม depend (พึ่งพา) บน Scoped ตรง ๆ (เช่น Singleton inject
DbContextที่เป็น Scoped) เพราะ Scoped จะติดอยู่ใน Singleton ยาวเกินอายุที่ควร (เรียกว่า captive dependency) ถ้าจำเป็นต้องใช้ ให้ injectIServiceScopeFactoryแทน — เรื่องนี้ลึกในบทที่ 7
ดูลึกในบทที่ 7
4. Kestrel — Web Server
Kestrel = web server ที่ Microsoft เขียนใหม่ใน C#:
- async I/O ตั้งแต่ต้น (จัดการ input/output แบบไม่บล็อก รับงานหลายอย่างพร้อมกันได้)
- ใช้
Span/Memory<T>ลด allocation[^alloc] (ข้ามส่วนนี้ได้ถ้ายังไม่คุ้นเรื่อง memory) — ปกติเวลาตัดข้อความยาวออกมาเป็นชิ้นเล็ก โค้ดทั่วไปจะคัดลอกข้อมูลไปสร้าง array ใหม่ แต่Span/Memory<T>คือ type ที่ชี้ไปดูข้อมูลก้อนเดิมในหน่วยความจำโดยตรง (ไม่คัดลอก) จึงเร็วกว่าและกิน memory น้อยกว่า - รองรับ HTTP/1.1, HTTP/2, HTTP/3 (QUIC — โปรโตคอลขนส่งข้อมูลรุ่นใหม่ที่เร็วกว่า)
TechEmpower benchmark[^bench]: Kestrel + minimal API ติดอันดับท็อปของโลกในหลาย round (โดยเฉพาะ plain text/JSON workload) (ตัวเลขอันดับและ throughput exact ขึ้นกับ round + workload + hardware — เช็ค round ล่าสุดที่ techempower.com/benchmarks ก่อนอ้างกับทีม flagged 2026-06)
ใน production (สภาพแวดล้อมใช้งานจริง) มักวาง reverse proxy[^revproxy] (Nginx/Traefik/YARP) หน้า Kestrel เพื่อ TLS termination (จุดที่ถอดรหัส HTTPS), caching — ดู devops/08-nginx-deep.md
[^alloc]: allocation = การจองหน่วยความจำเพื่อสร้าง object ใหม่ ยิ่งจองบ่อย ตัวเก็บขยะ (garbage collector) ยิ่งต้องทำงานหนัก แอปจึงช้าลง การลด allocation = ทำให้เร็วขึ้น [^bench]: benchmark = การทดสอบวัดประสิทธิภาพแล้วเทียบกัน หน่วย req/s = requests per second (จำนวนคำขอที่รับไหวต่อวินาที) ยิ่งสูงยิ่งรับโหลดได้มาก [^revproxy]: reverse proxy = เซิร์ฟเวอร์ตัวกลางที่รับ request จากภายนอกแล้วส่งต่อให้แอปข้างหลัง ช่วยทำ HTTPS, แคช, กระจายโหลด
5. Hosting Model
ทุกแอป ASP.NET Core เริ่มจากโครงสร้างเดียวกัน — สร้าง builder (อ่าน config + register DI), Build() ได้ WebApplication, ตั้ง middleware/route แล้ว Run() เข้าใจลำดับ 6 ขั้นนี้แล้วจะอ่านโค้ด startup ของโปรเจกต์ใดก็ออก:
csharp
var builder = WebApplication.CreateBuilder(args);
// สร้างและลงทะเบียน service ต่าง ๆ...
var app = builder.Build();
// ตั้งค่า pipeline (สายท่อ middleware)...
app.Run();ลำดับ:
CreateBuilder= อ่าน config (จาก env variable,appsettings.json)builder.Services.Add...= ลงทะเบียน service เข้า DIbuilder.Build()= สร้างWebApplicationapp.Use...= ตั้งค่า middlewareapp.Map...= กำหนด route (เส้นทาง URL → handler)app.Run()= เริ่มฟัง request
6. Minimal API vs Controller
Minimal API (.NET 6+)
csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello!");
app.MapGet("/users/{id}", (int id) => new { Id = id, Name = "Alice" });
app.MapPost("/users", (CreateUserDto dto) => Results.Created($"/users/1", dto));
app.Run();Controller
csharp
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
[HttpGet]
public IActionResult List() => Ok(new[] { /*...*/ });
[HttpGet("{id}")]
public IActionResult Get(int id) => Ok(new { Id = id });
}เลือกอย่างไร:
| Minimal API | Controller | |
|---|---|---|
| ขนาด | สั้น | ยาวกว่า |
| Feature ครบ | ใกล้เคียง Controller ใน .NET 8+ (รองรับ filter, attribute routing, model binding ส่วนใหญ่) | เต็ม โดยเฉพาะ MVC สมัยเก่า |
| Performance | เร็วกว่าเล็กน้อย | กลาง |
| เหมาะกับ | microservice, prototype (ตัวต้นแบบ), simple API | ระบบใหญ่, complex routing (การจัดเส้นทาง URL ซับซ้อน), งาน MVC แบบ classic |
ศัพท์ที่ใช้ในตาราง:
- filter = ตัวกรองที่รันก่อน/หลัง handler เช่นตรวจ permission
- model binding = การแปลงข้อมูลจาก request (query string, body) เป็น parameter ของ method อัตโนมัติ
คำแนะนำ: ใช้ Minimal เป็น default (ค่าตั้งต้น) — switch มา Controller เมื่อต้องการ feature ที่ขาด (filter เยอะ, model binder ซับซ้อน)
7. ASP.NET Core vs ตัวอื่น
| Spring Boot | ASP.NET Core | NestJS | Express | |
|---|---|---|---|---|
| Language | Java | C# | TS | JS |
| DI built-in | ✅ | ✅ | ✅ | ❌ |
| วิธีกำกับโค้ด (Convention)[^conv] | annotation | attribute | decorator | function |
| Performance (req/s)[^bench] | สูงมาก | สูงมาก (Native AOT[^aot] ช่วยอีก) | กลาง-สูง | กลาง |
| Learning curve (ความชันของการเรียนรู้) | สูง | กลาง | กลาง | ต่ำ |
| Job market (Asia/EU) | สูง | สูง enterprise (องค์กรใหญ่) | กลาง | สูง |
| Modern feature | กลาง | สูงสุด | สูง | กลาง |
ใกล้กับ Spring Boot ที่สุดในแง่แนวคิดการออกแบบ (design approach) — แต่ syntax (รูปแบบการเขียนโค้ด) สั้นกว่า เพราะ C#
📊 เรื่อง performance — ตัวเลข req/s จาก benchmark ลอย ๆ เปรียบเทียบกันตรง ๆ ไม่ได้ (ขึ้นกับ hardware, workload — plain text/JSON/DB-bound, version ของ framework, GC settings) ใช้ตารางนี้ดูภาพรวมเชิงคุณภาพ แล้วทดสอบกับ workload จริงของคุณก่อนตัดสินใจ — เช็ค TechEmpower round ล่าสุดถ้าอยากเทียบกันแบบแฟร์ (เงื่อนไขเดียวกันทุกฝั่ง) (flagged 2026-06)
[^conv]: annotation / attribute / decorator = ป้ายกำกับที่แปะบนโค้ด (class, method) เพื่อบอก framework ว่าให้ทำอะไรพิเศษ เป็นแนวคิดเดียวกันแต่ละภาษาเรียกต่างกัน: - Java เรียก annotation เช่น @GetMapping - C# เรียก attribute เช่น [HttpGet] - TypeScript เรียก decorator เช่น @Get() [^aot]: Native AOT (Ahead-Of-Time compilation) = การแปลงโค้ดเป็นไฟล์ native (เครื่องรันได้ตรง ๆ) ตั้งแต่ตอน build แทนที่จะแปลตอนรัน ทำให้แอปเริ่มเร็วและใช้ memory น้อยลง (ลงรายละเอียดในบทที่ 5)
8. Configuration
ASP.NET Core อ่าน config (ค่าตั้งค่า) จากหลายแหล่ง (override กันตามลำดับ — แหล่งหลังทับแหล่งหน้า):
appsettings.jsonappsettings.{Environment}.json(เช่นappsettings.Development.json)- Environment variables (ตัวแปรสภาพแวดล้อมของระบบ)
- Command-line args (ค่าที่ส่งตอนสั่งรันจาก terminal)
- User secrets (ที่เก็บความลับเฉพาะเครื่อง dev)
- Azure Key Vault / AWS SSM (ที่เก็บความลับสำหรับ production)
jsonc
// appsettings.json
{
"Logging": {
"LogLevel": { "Default": "Information" }
},
"ConnectionStrings": {
"Default": "Host=localhost;Database=app;Username=pg;Password=pg"
}
}csharp
// อ่านค่า config ออกมาใช้
var cs = builder.Configuration.GetConnectionString("Default");
var logLevel = builder.Configuration["Logging:LogLevel:Default"];Best practice (แนวทางที่แนะนำ): ใช้ Options pattern (เดี๋ยวบทที่ 7 อธิบาย) — strongly-typed config (config ที่ผูกกับ type ชัดเจน เขียนผิดจะรู้ตั้งแต่ compile)
9. Environment
ASP.NET Core รู้ว่ากำลังรันใน environment ไหนผ่านตัวแปร ASPNETCORE_ENVIRONMENT (Development/Staging/Production) — ทำให้โหลด config ต่างกันและเปิด/ปิดฟีเจอร์ตาม env ได้ (เช่นเปิด Swagger เฉพาะตอน dev) ส่วนนี้แสดงวิธีตั้งและใช้:
💡 OpenAPI คืออะไร — เอกสารอธิบาย endpoint ของ API แบบที่เครื่องอ่านได้ (machine-readable) สร้างอัตโนมัติจากโค้ด แล้วให้เครื่องมืออย่าง Swagger UI เอาไปแสดงผล/ให้ทดลองยิง request ได้ — โค้ดด้านล่างเปิดเอกสารนี้เฉพาะตอน dev
powershell
# Windows (PowerShell) — ตั้งค่า environment variable
$env:ASPNETCORE_ENVIRONMENT = "Development"
dotnet runbash
# Linux / macOS
ASPNETCORE_ENVIRONMENT=Production dotnet runค่ามาตรฐาน: Development, Staging, Production
csharp
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // .NET 9+ built-in — เปิดเอกสาร API ที่ /openapi/v1.json
// หมายเหตุ: ถ้าใช้ .NET 8 + Swashbuckle ใช้ app.UseSwagger(); app.UseSwaggerUI(); แทน
}10. Project Templates
dotnet new มี template หลายแบบให้เริ่มโปรเจกต์ตามประเภทงาน — web API, MVC, Razor Pages, Blazor, gRPC, worker เลือกให้ตรงกับสิ่งที่จะสร้างจะได้โครงเริ่มต้นที่เหมาะ หนังสือนี้ใช้ webapi แบบ Minimal API เป็นหลัก:
bash
dotnet new web # ขั้น minimal — แค่ Hello World
dotnet new webapi # API (Minimal)
dotnet new webapi --use-controllers # API (Controller)
dotnet new mvc # MVC + views (สร้าง HTML ที่ฝั่ง server)
dotnet new razor # Razor Pages
dotnet new blazorserver # Blazor Server (เว็บโต้ตอบได้)
dotnet new blazor # Blazor Web (.NET 8+, render แบบผสม)
dotnet new grpc # gRPC service (โปรโตคอลเรียก service ข้ามเครื่องที่เร็ว)
dotnet new worker # background service (บริการทำงานเบื้องหลัง)
dotnet new sln # solution file (ไฟล์รวมหลายโปรเจกต์)หนังสือนี้ใช้ webapi Minimal API เป็นหลัก
11. ลองโปรเจกต์แรก
ลงมือสร้างโปรเจกต์แรกกันเลย — สร้าง webapi, รัน แล้วเปิด endpoint ตัวอย่างใน browser เพื่อเห็นว่า ASP.NET Core ทำงานได้จริงในไม่กี่คำสั่ง ก่อนจะลงรายละเอียดในบทถัด ๆ ไป (dotnet คือ command-line tool ที่ใช้สร้าง/build/รันโปรเจกต์ .NET ส่วนคำที่ขึ้นต้นด้วย - หรือ -- คือ flag/option ที่ปรับพฤติกรรมคำสั่งนั้น เช่น -n ตั้งชื่อโปรเจกต์):
bash
dotnet new webapi -n Api --use-program-main # .NET 8+ flag — สร้าง Program.cs ที่มี Main() แทน top-level statements
cd Api
dotnet run
# → port จะอ่านจาก Properties/launchSettings.json ของโปรเจกต์ (มักเป็น http://localhost:5xxx + https://localhost:7xxx)
# → มี endpoint ตัวอย่างชื่อ /weatherforecast มาให้💡 top-level statements vs
--use-program-main: top-level statements คือ C# 9+ feature ที่ให้เขียนโค้ดในไฟล์ได้โดยไม่ต้องมีclass Program { static void Main() {...} }รอบนอก — เหมาะเขียนสั้น แต่เวลาเรียนรู้--use-program-mainทำให้เห็นโครงสร้างชัดกว่า ในหนังสือนี้ใช้ทั้งสองแบบสลับกัน หน้าตาไฟล์Program.csที่ template สร้างให้จริง ๆ จะอธิบายละเอียดใน บทที่ 1
ลองเปิด URL ที่ console พิมพ์ออกมา ตามด้วย /weatherforecast (เช่น http://localhost:5141/weatherforecast) ใน browser → จะได้ JSON array (ลิสต์ข้อมูลรูปแบบ JSON)
12. โครงสร้างไฟล์มาตรฐาน
โปรเจกต์ ASP.NET Core มีโครงสร้างไฟล์มาตรฐานที่ควรรู้จัก — Program.cs (entry + config), appsettings.json (config ต่อ env), โฟลเดอร์ Controllers/Models/Services และ launchSettings.json (โปรไฟล์ dev) คุ้นกับผังนี้แล้วจะหาของในโปรเจกต์ใดก็เจอ:
text
Api/
├── Api.csproj
├── Program.cs ← จุดเริ่มโปรแกรม (entry point) + config
├── appsettings.json
├── appsettings.Development.json
├── Controllers/ ← ถ้าใช้ Controller
├── Models/
├── Services/
└── Properties/
└── launchSettings.json ← โปรไฟล์สำหรับ dev13. NuGet packages ที่จะใช้บ่อย
NuGet = ระบบจัดการ library (แพ็กเกจโค้ดสำเร็จรูป) ของ .NET คล้าย npm ของ Node ติดตั้งด้วยคำสั่ง dotnet add package <ชื่อ> เช่น:
bash
dotnet add package Microsoft.AspNetCore.OpenApipackages หลักที่จะใช้ในหนังสือนี้:
bash
# core
Microsoft.AspNetCore.OpenApi # OpenAPI/Swagger (เอกสาร API อัตโนมัติ) — built-in ใน .NET 9+ ไม่ต้องใช้ Swashbuckle แล้ว
# database
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Npgsql.EntityFrameworkCore.PostgreSQL # provider สำหรับ PostgreSQL หรือ
Microsoft.EntityFrameworkCore.SqlServer
# auth
Microsoft.AspNetCore.Authentication.JwtBearer
Microsoft.AspNetCore.Identity.EntityFrameworkCore
# logging
Serilog.AspNetCore # structured logging ที่นิยม (log แบบมีโครงสร้าง ค้นง่าย)
# testing
xunit
Microsoft.AspNetCore.Mvc.Testing
Testcontainers.PostgreSqlติดตั้งทีหลัง — บทถัด ๆ ไปจะแนะนำเมื่อใช้
14. Hello World — full version
csharp
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// ลงทะเบียน service เข้า DI
builder.Services.AddEndpointsApiExplorer(); // บอกให้ OpenAPI สแกนหา endpoint ที่เรากำหนดไว้ใน MapGet/MapPost (จำเป็นใน .NET 8 แต่ .NET 9+ ไม่ต้องแล้ว)
builder.Services.AddOpenApi(); // .NET 9+ — ถ้าใช้ .NET 8 SDK ต้อง `dotnet add package Microsoft.AspNetCore.OpenApi` ก่อน (ของเก่ากว่านั้นใช้ AddSwaggerGen จาก Swashbuckle)
var app = builder.Build();
// ตั้งค่า pipeline (สายท่อ middleware)
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // เปิดเอกสาร API ที่ /openapi/v1.json เฉพาะตอน dev
}
app.UseHttpsRedirection(); // บังคับเปลี่ยน http เป็น https
// กำหนด endpoint (เส้นทาง URL → โค้ดที่ตอบ)
app.MapGet("/", () => "Hello, World!");
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));
app.Run();3-4 ชั้น แต่ทุกชั้นมีหน้าที่ชัด — เดี๋ยวบทถัดไปจะเขียน REST API จริง
🛠️ Checkpoint 0 — ลงมือทำ
dotnet new webapi -n MyApi --use-program-main→ run- เปิด
/weatherforecastใน browser - ลบ default endpoint → เพิ่ม
app.MapGet("/hello", () => "Hello!") - ลอง
dotnet run+ เปิด/hello - ตั้ง
ASPNETCORE_ENVIRONMENT=Production→ ดู endpoint/openapi/v1.jsonหาย (เพราะใน Hello World เรา mapMapOpenApi()เฉพาะตอน Development)- หมายเหตุ: ถ้าเทมเพลตที่คุณสร้าง (scaffold) ด้วย
dotnet new webapiเป็นเวอร์ชันที่ใช้ Swashbuckle จะเห็น/swaggerUI หายแทน
- หมายเหตุ: ถ้าเทมเพลตที่คุณสร้าง (scaffold) ด้วย
สรุปบทที่ 0
- ASP.NET Core = framework ใหม่ ตั้งแต่ .NET Core 1.0 — cross-platform + เร็วมาก
- Pipeline = chain (สายต่อกัน) ของ middleware (ลำดับสำคัญ)
- DI built-in มี 3 lifetime: Singleton/Scoped/Transient
- Kestrel = web server ของ .NET (ติดอันดับ top tier ใน TechEmpower benchmark)
- Minimal API (default) + Controller (สำหรับงานซับซ้อน)
- Config มาจาก appsettings + env var + secret manager (ที่เก็บความลับ)
🔤 Glossary · 📋 Style guide · 📅 last_verified: 2026-06-12