ติดตั้ง .NET บน VSCode แบบไม่ง้อ C# DevKit (Mac/Ubuntu)
คู่มือ .NET Backend บน VSCode ฉบับสมบูรณ์ — ไม่มี C# DevKit ก็ได้ประสบการณ์เทียบเท่า Visual Studio
คู่มือติดตั้งและตั้งค่าสำหรับทีมที่ใช้ GitHub Copilot โดยไม่ต้องการ C# DevKit
สารบัญ
ติดตั้งและตั้งค่า
- ทำความเข้าใจ Architecture ก่อนติดตั้ง
- ติดตั้ง .NET SDK
- จัดการ SDK Version
- Extensions ที่ต้องติดตั้ง
- VSCode Profiles
- ตั้งค่า VSCode สำหรับ .NET
เริ่มใช้งาน
- สร้าง Solution และ Project Structure
- จัดการ Project Reference และ NuGet
- Configuration Files
- VSCode Snippets สำหรับทีม
- GitHub Copilot Custom Instructions
ใช้งานประจำวัน
Appendix
บทความนี้เป็นส่วนหนึ่งของ .NET Ecosystem บน VSCode — ครอบคลุมตั้งแต่การติดตั้ง SDK, การตั้งค่า extensions, ไปจนถึง workflow การพัฒนา Backend ด้วย Clean Architecture และ GitHub Copilot โดยไม่ต้องพึ่ง Visual Studio หรือ C# DevKit ที่ต้องมี license
1. ทำความเข้าใจ Architecture ก่อนติดตั้ง
ก่อนติดตั้ง ควรทำความเข้าใจว่าแต่ละ component ทำอะไร เพื่อไม่ให้สับสนระหว่างการใช้งาน
Roslyn, OmniSharp, SonarQube คืออะไร
| Component | ทำงานตอนไหน | output คืออะไร |
|---|---|---|
| OmniSharp | ระหว่างพิม | IntelliSense, error highlight |
| Roslyn | embedded ใน OmniSharp/SonarLint/dotnet build | syntax tree, semantic model, .dll |
| Roslynator | ระหว่างพิม | code analysis 500+ rules (plugin ของ OmniSharp) |
| SonarLint | ระหว่างพิม | security, code smell |
| SonarQube Scanner | ตอน build ใน CI/CD | Quality Gate report |
| Kestrel | ตอน app รัน | รับ HTTP request จาก client |
| Language Server | ระหว่างพิม | ≠ interpreter, ไม่รันโค้ด อ่านอย่างเดียว |
หมายเหตุ: Roslyn ไม่ใช่ขั้นตอนที่รันก่อน — เป็น library ที่ทั้ง OmniSharp, SonarLint และ
dotnet buildต่างฝัง (embed) ไว้ในตัวเองและเรียกใช้แยกกัน
2. ติดตั้ง .NET SDK
สำหรับผู้ใช้ Windows: บทความนี้ครอบคลุมเฉพาะ macOS และ Ubuntu — แนะนำให้ติดตั้ง WSL2 แล้วเลือก Ubuntu เป็น distro แทนการรัน .NET บน Windows โดยตรง จากนั้นทำตามขั้นตอน Ubuntu ด้านล่างได้เลย
ทำไมต้อง Ubuntu+WSL แทน Windows ตรงๆ?
- Environment ตรงกับ Production — server จริงเกือบทั้งหมดรัน Linux ใช้ WSL ทำให้ path, file permission, line ending (
LFvsCRLF) และ shell script ทำงานตรงกับ server ทันที ไม่ต้องแก้ bug ที่เกิดเฉพาะบน Windows- Docker ทำงานได้ดีกว่า — Docker Desktop บน Windows ใช้ทรัพยากรสูงและมีข้อจำกัดด้าน volume performance ส่วน WSL2 รัน Docker engine ใน Linux kernel โดยตรง เร็วกว่าและเสถียรกว่า
- Shell script ใช้ได้เลย — build script, CI/CD script และ tool ส่วนใหญ่ในทีมเขียนเป็น bash ใช้ได้ใน WSL โดยไม่ต้องดัดแปลง
- OmniSharp เสถียรกว่า — มีรายงานปัญหา OmniSharp crash และ IntelliSense ช้าบน Windows โดยเฉพาะกับ solution ขนาดใหญ่ WSL ช่วยลดปัญหานี้ได้
- ยังใช้ UI ของ Windows ได้ปกติ — VSCode บน Windows เชื่อมต่อเข้า WSL ผ่าน Remote - WSL extension ได้โดยตรง ไม่ต้องเปิด terminal แยก
macOS — วิธีที่ 1: GUI Installer (แนะนำสำหรับทีมที่ไม่ถนัด CLI)
- ไปที่ https://dotnet.microsoft.com/en-us/download
- เลือก SDK version ที่ต้องการ (แนะนำ .NET 8 LTS)
- ดาวน์โหลด
.pkgแล้วคลิก Next → Next → Finish - ติดได้หลาย version พร้อมกัน ไม่ต้องถอนของเก่า
macOS — วิธีที่ 2: Homebrew
brew install dotnet@8
brew install dotnet@9 # ติดหลาย version พร้อมกันได้
Ubuntu
# Ubuntu 22.04 / 24.04
sudo apt-get update
sudo apt-get install -y dotnet-sdk-8.0
# หรือผ่าน Microsoft feed
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update && sudo apt-get install -y dotnet-sdk-8.0
ตรวจสอบ
dotnet --version
dotnet sdk check # ดู version ทั้งหมดที่ติดอยู่
3. จัดการ SDK Version
global.json — Pin Version ให้ทั้งทีมใช้ตรงกัน
global.json ควรวางที่ solution root (เดียวกับ .sln) จะครอบทุก .csproj ข้างในทั้งหมด ไม่ต้องวางซ้ำในแต่ละ project
MySystem/ ← วาง global.json ตรงนี้
├── global.json
├── MySystem.sln
├── src/
│ ├── MySystem.API/
│ ├── MySystem.Application/
│ ├── MySystem.Domain/
│ └── MySystem.Infrastructure/
└── tests/
└── MySystem.Tests/
{
"sdk": {
"version": "8.0.404",
"rollForward": "disable"
}
}
.NET จะหา global.json โดยเดิน up directory จาก working directory ขึ้นไปเรื่อยๆ จนเจออันแรก
ค่า rollForward ที่ควรรู้
| ค่า | ความหมาย |
|---|---|
disable | ใช้ version นี้เป๊ะ ถ้าไม่มีให้ error — แนะนำสำหรับทีม |
patch | ยอมให้ใช้ patch ใหม่กว่าได้ แต่ minor/major ต้องตรง |
latestMinor | ใช้ minor ใหม่สุดที่มี |
latestMajor | ใช้ version ใหม่สุดที่มีในเครื่อง |
กรณีหลาย Solution ใช้ .NET ต่าง Version
repos/
├── OrderService/
│ ├── global.json ← { "sdk": { "version": "8.0.404" } }
│ └── OrderService.sln
└── LegacyService/
├── global.json ← { "sdk": { "version": "6.0.0" } }
└── LegacyService.sln
ตรวจสอบ Version ที่ติดอยู่
dotnet sdk check # ดูสถานะทุก version + แจ้ง patch ใหม่
dotnet --list-sdks # ดู SDK พร้อม path
dotnet --list-runtimes # ดู Runtime ที่ติด
dotnet --version # ดู version ที่ project ใช้อยู่จริง (รันใน folder ที่มี global.json)
output ของ dotnet sdk check:
.NET SDKs:
Version Status
-------------------------------------------
6.0.420 Up to date.
8.0.100 Patch 8.0.404 is available. ← มี patch ใหม่
8.0.404 Up to date.
Upgrade Patch Version
macOS — GUI
ดาวน์โหลด installer version ใหม่จาก dotnet.microsoft.com แล้วรันทับได้เลย ไม่ต้องถอนของเก่า
macOS — Homebrew
Homebrew ติด latest patch ของ major version ให้เสมอ ระบุ patch เองตรงๆ ไม่ได้ ต้องใช้ install script หากต้องการระบุ version
brew info dotnet@8 # ดู version ที่มีใน homebrew
brew upgrade dotnet@8 # upgrade เป็น latest patch
macOS / Ubuntu — ระบุ patch version ตรงๆ ด้วย install script
# ดู version ที่มีทั้งหมด
curl -sL https://raw.githubusercontent.com/dotnet/install-scripts/main/src/dotnet-install.sh | bash -s -- --list-versions --channel 8.0
# ติด patch version ที่ต้องการ
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin \
--version 8.0.404 \
--install-dir $HOME/.dotnet
Ubuntu — apt
sudo apt-get update
apt-cache madison dotnet-sdk-8.0 # ดู version ทั้งหมดที่มีใน repo
sudo apt-get install dotnet-sdk-8.0=8.0.404-0ubuntu1~22.04.1
Flow Upgrade
dotnet sdk check
↓
เห็นว่ามี patch ใหม่
↓
Mac: brew upgrade dotnet@8
Ubuntu: apt-get install dotnet-sdk-8.0=<version>
↓
dotnet sdk check ← verify อีกครั้ง
↓
อัปเดต global.json ให้ตรง
↓
dotnet build ← ทดสอบว่า project ยัง build ได้
Downgrade Patch Version
.NET ติดได้หลาย version พร้อมกัน — downgrade จริงๆ คือ ติด version เก่าเพิ่ม แล้ว pin ด้วย global.json ไม่ต้องถอน version ใหม่ออก
macOS — install script
Homebrew เก็บแค่ latest ของแต่ละ major version ต้องใช้ install script แทน
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin \
--version 8.0.100 \
--install-dir $HOME/.dotnet
dotnet sdk check # ตรวจสอบว่ามีครบ
Ubuntu — apt
apt-cache madison dotnet-sdk-8.0 # ดู version ที่มีใน repo
sudo apt-get install dotnet-sdk-8.0=8.0.100-0ubuntu1~22.04.1
# apt จะถามว่า downgrade มั้ย กด Y
แก้ global.json หลัง Downgrade
{
"sdk": {
"version": "8.0.100",
"rollForward": "disable"
}
}
Flow Downgrade
dotnet sdk check
↓
ติด version เก่าที่ต้องการ (install script / apt)
↓
แก้ global.json → version เก่า + rollForward: disable
↓
dotnet --version ← verify ใน project folder
↓
dotnet build ← ทดสอบ
4. Extensions ที่ต้องติดตั้ง
ทั้งหมดนี้ ฟรี 100% (GitHub Copilot ต้องจ่ายแต่ทีมมีอยู่แล้ว)
Core — จำเป็นต้องมี
| Extension | ID | ทำอะไร |
|---|---|---|
| C# (OmniSharp) | ms-dotnettools.csharp | IntelliSense, debug, go-to-def — หัวใจหลัก |
| .NET Install Tool | ms-dotnettools.vscode-dotnet-runtime | dependency ของ C# extension (ทำงานเบื้องหลังอัตโนมัติ) |
| Solution Explorer | fernandoescolar.vscode-solution-explorer | GUI จัดการ .sln, add reference, add project คลิกขวาได้ |
Productivity
| Extension | ID | ทำอะไร |
|---|---|---|
| NuGet Gallery | patcx.vscode-nuget-gallery | GUI ค้นหาและติด NuGet package |
| Roslynator | josefpihrt-vscode.roslynator | Code analysis 500+ rules + auto fix ด้วย Ctrl+. |
| REST Client | humao.rest-client | ทดสอบ API จากไฟล์ .http แทน Postman |
| .NET Core Test Explorer | formulahendry.dotnet-test-explorer | รัน/debug test แบบ click-to-run |
Utility (Default ใช้ได้ทุก Profile)
| Extension | หมายเหตุ |
|---|---|
| GitHub Copilot | ใช้ได้ทุกภาษา |
| GitHub Copilot Chat | ใช้ @terminal ให้ generate CLI command แทนได้ |
วิธีใช้ Roslynator
- วางเคอร์เซอร์บนโค้ดที่ขีดเส้น → กด
Ctrl+.→ เลือก fix - คลิกขวาที่โค้ด → Refactor → เลือก action
- เปิด Problems panel:
Ctrl+Shift+M
Roslynator เปรียบได้กับ ESLint ของ JavaScript — ชี้ปัญหาแบบ real-time และ fix ให้อัตโนมัติ ส่วน SonarQube เปรียบได้กับศูนย์ตรวจรถที่ต้องนำรถไปตรวจเป็นรอบ
5. VSCode Profiles
ควรแยก profile สำหรับแต่ละภาษา เพื่อลด RAM และป้องกัน extension ชนกัน
วิธีสร้าง Profile
ซ้ายล่าง → คลิก ⚙️ → Profiles → Create Profile → ตั้งชื่อ "dotnet"
แนะนำ Profile Structure
| Profile | Extensions |
|---|---|
| dotnet | C#, .NET Install Tool, Solution Explorer, NuGet Gallery, Roslynator, REST Client, Test Explorer |
| frontend | ESLint, Prettier, Tailwind, TypeScript, Volar |
| python | Python, Pylance, Jupyter, Black Formatter |
| default (ทุก profile) | GitHub Copilot, GitHub Copilot Chat, GitLens |
Switch Profile
Ctrl+Shift+P → "Profiles: Switch Profile" → เลือก profile
6. ตั้งค่า VSCode สำหรับ .NET
.vscode/settings.json
{
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,
"omnisharp.organizeImportsOnFormat": true,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"dotnet-test-explorer.testProjectPath": "**/*.Tests.csproj",
"dotnet-test-explorer.autoWatch": true,
"dotnet-test-explorer.showCodeLens": true,
"vscode-solution-explorer.trackActiveItem": true,
"vscode-solution-explorer.showTerminalOnError": true
}
.vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": ["build", "${workspaceFolder}"],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": ["watch", "run", "--project", "${workspaceFolder}/src/MySystem.API"],
"problemMatcher": "$msCompile",
"isBackground": true
}
]
}
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/src/MySystem.API/bin/Debug/net8.0/MySystem.API.dll",
"args": [],
"cwd": "${workspaceFolder}/src/MySystem.API",
"stopAtEntry": false,
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "https://localhost:5001;http://localhost:5000"
}
}
]
}
7. สร้าง Solution และ Project Structure
Shell Script — สร้างครั้งเดียวใช้ซ้ำได้ทั้งทีม
สร้างไฟล์ create-service.sh เก็บไว้ใน repo:
#!/bin/bash
# create-service.sh
# Usage: ./create-service.sh OrderService
NAME=$1
mkdir -p $NAME && cd $NAME
dotnet new sln -n $NAME
mkdir -p src tests
# สร้างทุก project
dotnet new webapi -n $NAME.API -o src/$NAME.API
dotnet new classlib -n $NAME.Application -o src/$NAME.Application
dotnet new classlib -n $NAME.Domain -o src/$NAME.Domain
dotnet new classlib -n $NAME.Infrastructure -o src/$NAME.Infrastructure
dotnet new xunit -n $NAME.Tests -o tests/$NAME.Tests
# เพิ่มทุก project เข้า sln
dotnet sln add src/$NAME.API/$NAME.API.csproj
dotnet sln add src/$NAME.Application/$NAME.Application.csproj
dotnet sln add src/$NAME.Domain/$NAME.Domain.csproj
dotnet sln add src/$NAME.Infrastructure/$NAME.Infrastructure.csproj
dotnet sln add tests/$NAME.Tests/$NAME.Tests.csproj
# Reference chain
dotnet add src/$NAME.API reference src/$NAME.Application/$NAME.Application.csproj
dotnet add src/$NAME.Application reference src/$NAME.Domain/$NAME.Domain.csproj
dotnet add src/$NAME.Infrastructure reference src/$NAME.Application/$NAME.Application.csproj
echo "✅ $NAME solution ready!"
chmod +x create-service.sh
./create-service.sh OrderService
หรือใช้ Copilot Chat แทน
@terminal สร้าง solution ชื่อ OrderService
ใช้ Clean Architecture: API, Application, Domain, Infrastructure, Tests
8. จัดการ Project Reference และ NuGet
Add Project Reference
วิธีที่ 1 — Solution Explorer (GUI คลิกขวา)
Solution Explorer → คลิกขวาที่ project → Add → Project Reference
วิธีที่ 2 — Copilot Chat
@terminal เพิ่ม reference จาก MySystem.Application เข้าไปใน MySystem.API
วิธีที่ 3 — CLI
dotnet add src/MySystem.API reference src/MySystem.Application/MySystem.Application.csproj
วิธีที่ 4 — แก้ .csproj ตรงๆ (OmniSharp จะ reload ให้อัตโนมัติ)
<ItemGroup>
<ProjectReference Include="..\MySystem.Application\MySystem.Application.csproj"/>
</ItemGroup>
Add NuGet Package
วิธีที่ 1 — NuGet Gallery (GUI)
Ctrl+Shift+P → "NuGet: Open NuGet Gallery" → ค้นหา → เลือก version → Install
วิธีที่ 2 — Copilot Chat
@terminal เพิ่ม MediatR และ FluentValidation ลงใน MySystem.Application
วิธีที่ 3 — CLI
dotnet add src/MySystem.Application package MediatR
dotnet add src/MySystem.Application package FluentValidation
9. Configuration Files
ตำแหน่งไฟล์ใน Solution
MySystem/
├── global.json ← SDK version (solution level)
├── MySystem.sln
└── src/
├── MySystem.API/
│ ├── appsettings.json ← base config
│ ├── appsettings.Development.json
│ ├── appsettings.Production.json ← ใส่ใน .gitignore
│ └── MySystem.API.csproj
├── MySystem.Application/ ← ไม่มี appsettings.json
├── MySystem.Domain/ ← ไม่มี appsettings.json
└── MySystem.Infrastructure/ ← ไม่มี appsettings.json
appsettings.jsonวางได้เฉพาะ project ที่ run ได้เท่านั้น (เช่น.API) ส่วนglobal.jsonวาง 1 ไฟล์ที่ solution root ครอบทุก project
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": ""
},
"Jwt": {
"Issuer": "myapp",
"ExpiryMinutes": 60
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
appsettings.Development.json
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=mydb_dev;Username=postgres"
}
}
.gitignore — สิ่งที่ต้องระวัง
appsettings.Production.json
appsettings.*.local.json
*.user
.env
10. VSCode Snippets สำหรับทีม
สร้างไฟล์ .vscode/dotnet.code-snippets ใน repo เพื่อให้ทุกคนในทีมใช้ snippets ร่วมกัน
{
"CQRS Command": {
"prefix": "cmd",
"description": "สร้าง MediatR Command + Handler",
"body": [
"namespace ${1:MyApp}.Application.${2:Feature}.Commands;",
"",
"public record ${3:Create}${2:Feature}Command(",
" $4",
") : IRequest<${5:Result}>;",
"",
"public class ${3:Create}${2:Feature}CommandHandler(",
" $6",
") : IRequestHandler<${3:Create}${2:Feature}Command, ${5:Result}>",
"{",
" public async Task<${5:Result}> Handle(",
" ${3:Create}${2:Feature}Command request,",
" CancellationToken cancellationToken)",
" {",
" $0",
" }",
"}"
]
},
"CQRS Query": {
"prefix": "qry",
"description": "สร้าง MediatR Query + Handler",
"body": [
"namespace ${1:MyApp}.Application.${2:Feature}.Queries;",
"",
"public record Get${2:Feature}Query($3) : IRequest<${4:Result}>;",
"",
"public class Get${2:Feature}QueryHandler(",
" $5",
") : IRequestHandler<Get${2:Feature}Query, ${4:Result}>",
"{",
" public async Task<${4:Result}> Handle(",
" Get${2:Feature}Query request,",
" CancellationToken cancellationToken)",
" {",
" $0",
" }",
"}"
]
},
"API Controller": {
"prefix": "ctrl",
"description": "สร้าง API Controller พร้อม MediatR",
"body": [
"namespace ${1:MyApp}.API.Controllers;",
"",
"[ApiController]",
"[Route(\"api/[controller]\")]",
"public class ${2:Feature}Controller(ISender sender) : ControllerBase",
"{",
" [HttpGet]",
" public async Task<IActionResult> GetAll(CancellationToken ct)",
" {",
" var result = await sender.Send(new Get${2:Feature}Query(), ct);",
" return Ok(result);",
" }",
"",
" [HttpPost]",
" public async Task<IActionResult> Create(",
" [FromBody] Create${2:Feature}Command command,",
" CancellationToken ct)",
" {",
" var result = await sender.Send(command, ct);",
" return Ok(result);",
" }",
"}"
]
},
"Domain Entity": {
"prefix": "ent",
"description": "สร้าง Domain Entity",
"body": [
"namespace ${1:MyApp}.Domain.Entities;",
"",
"public class ${2:Entity}",
"{",
" public Guid Id { get; private set; } = Guid.NewGuid();",
" $0",
"",
" private ${2:Entity}() { }",
"",
" public static ${2:Entity} Create($3)",
" {",
" return new ${2:Entity} { $4 };",
" }",
"}"
]
}
}
วิธีใช้ Snippets
| พิม | กด | ได้อะไร |
|---|---|---|
cmd | Tab | MediatR Command + Handler |
qry | Tab | MediatR Query + Handler |
ctrl | Tab | API Controller พร้อม MediatR |
ent | Tab | Domain Entity |
11. GitHub Copilot Custom Instructions
เนื่องจากทีมมี subscription อยู่แล้ว สามารถใช้ Custom Instructions เพื่อให้ Copilot รู้บริบทของทีมได้ทันที ไม่ต้องอธิบายซ้ำทุกครั้ง
วิธีที่ 1 — Repository Level (แนะนำ — ใช้ร่วมกันทั้งทีม)
สร้างไฟล์ .github/copilot-instructions.md:
# Team .NET Backend Guidelines
## Stack
- .NET 8, ASP.NET Core Web API
- Entity Framework Core, PostgreSQL
- MediatR (CQRS pattern)
- FluentValidation
## Code style
- ใช้ primary constructor (C# 12)
- ใช้ async/await ทุก I/O operation
- ใช้ Result pattern แทน throw exception
- XML doc comment บน public method ทุกตัว
## Architecture
- Clean Architecture: Domain / Application / Infrastructure / API
- Repository pattern สำหรับ data access
- Validation ด้วย FluentValidation
## Naming
- Command: `CreateOrderCommand`, `UpdateProductCommand`
- Query: `GetOrderQuery`, `ListProductsQuery`
- Controller suffix: `OrdersController`
## Testing
- xUnit สำหรับ unit test
- Testcontainers สำหรับ integration test
วิธีที่ 2 — VSCode User Settings (per-person)
{
"github.copilot.chat.codeGeneration.instructions": [
{
"text": "ฉันพัฒนา .NET 8 Web API ใช้ Clean Architecture, MediatR, EF Core. ใช้ async/await, Result pattern, FluentValidation เสมอ"
}
]
}
วิธีที่ 3 — ใช้ Copilot Chat แทน CLI (สำหรับทีมที่ไม่ถนัด CLI)
@terminal สร้าง Web API project ชื่อ OrderService ใช้ .NET 8
@terminal เพิ่ม NuGet package MediatR ลงใน project Application
@terminal สร้าง feature Order แบบ vertical slice
มี Command, Query, Validator, DTO
12. รัน Test ใน VSCode
ใช้ .NET Core Test Explorer extension
Test Explorer Panel
TEST EXPLORER
└── 📁 MySystem.sln
└── 📁 MySystem.Tests
├── 📁 OrderTests
│ ├── ✅ CreateOrder_ValidInput_ReturnsSuccess ▶
│ ├── ✅ CreateOrder_EmptyItems_ReturnsFail ▶
│ └── ❌ CreateOrder_NullCustomer_Throws ▶
└── 📁 PaymentTests
└── ✅ ProcessPayment_Success ▶
CodeLens ใน Editor
// ▶ Run Test | 🐛 Debug Test ← ปุ่มลอยอยู่เหนือ method
[Fact]
public async Task CreateOrder_ValidInput_ReturnsSuccess()
{
...
}
ระดับที่รัน test ได้
| ระดับ | วิธี |
|---|---|
| ทั้ง solution | คลิก ▶ ที่ node .sln |
| ทั้ง project | คลิก ▶ ที่ node .csproj |
| ทั้ง class | คลิก ▶ ที่ชื่อ class |
| test case เดียว | คลิก ▶ หน้าชื่อ method |
| debug test | คลิกขวา → Debug Test |
ร่วมกับ Copilot
/tests สร้าง unit test สำหรับ CreateOrderCommandHandler
ครอบคลุม happy path และ edge cases
13. Debug ใน VSCode
| Action | Shortcut |
|---|---|
| Start debugging | F5 |
| Stop debugging | Shift+F5 |
| Step over | F10 |
| Step into | F11 |
| Step out | Shift+F11 |
| Toggle breakpoint | F9 |
14. สรุป Workflow
Keyboard Shortcuts สำคัญ
| Shortcut | Action |
|---|---|
F5 | Run & Debug |
Ctrl+Shift+B | Build |
F12 | Go to Definition |
Alt+F12 | Peek Definition |
Shift+F12 | Find all References |
F2 | Rename Symbol |
Ctrl+. | Quick Fix (Roslynator) |
Ctrl+Shift+P | Command Palette |
Daily Workflow
1. เปิด VSCode → Switch ไป dotnet profile
↓
2. สร้าง feature ใหม่ → Copilot Chat บอกชื่อ feature
↓
3. สร้าง file เพิ่ม → Snippets (cmd / qry / ctrl / ent)
↓
4. เขียน business logic → Copilot Autocomplete ช่วย
↓
5. รัน test → คลิก ▶ จาก Test Explorer หรือ CodeLens
↓
6. Debug → F5 วาง breakpoint กด F9
↓
7. Test API → REST Client ไฟล์ .http
เปรียบเทียบ VSCode vs Visual Studio
| Feature | Visual Studio | VSCode + Extensions |
|---|---|---|
| IntelliSense | ✅ | ✅ OmniSharp |
| Breakpoint & Debug | ✅ | ✅ F5 |
| Hot Reload | ✅ | ✅ dotnet watch run |
| Go to Definition | ✅ | ✅ F12 |
| Refactor / Rename | ✅ | ✅ F2 + Roslynator |
| NuGet GUI | ✅ | ✅ NuGet Gallery |
| Solution Explorer | ✅ | ✅ Solution Explorer ext |
| Add Project Reference | ✅ GUI | ✅ Solution Explorer ext |
| Test Runner GUI | ✅ | ✅ .NET Core Test Explorer |
| Code Analysis | ✅ | ✅ Roslynator |
| ราคา | 💰 | ✅ ฟรี (ยกเว้น Copilot) |
สรุป Extensions ทั้งหมด
| Extension | ID | ฟรี |
|---|---|---|
| C# (OmniSharp) | ms-dotnettools.csharp | ✅ |
| .NET Install Tool | ms-dotnettools.vscode-dotnet-runtime | ✅ |
| Solution Explorer | fernandoescolar.vscode-solution-explorer | ✅ |
| NuGet Gallery | patcx.vscode-nuget-gallery | ✅ |
| Roslynator | josefpihrt-vscode.roslynator | ✅ |
| REST Client | humao.rest-client | ✅ |
| .NET Core Test Explorer | formulahendry.dotnet-test-explorer | ✅ |
| GitHub Copilot | github.copilot | ❌ (ทีมมีอยู่แล้ว) |
| GitHub Copilot Chat | github.copilot-chat | ❌ (ทีมมีอยู่แล้ว) |
FAQ
Q: VSCode กับ Visual Studio ต่างกันอย่างไรสำหรับการพัฒนา .NET?
Visual Studio เป็น full IDE ที่มี GUI ครบทุกอย่างแต่ต้องใช้ license (Windows เป็นหลัก) ส่วน VSCode เป็น lightweight editor ที่ติด extensions เพิ่มได้ฟรี — เมื่อใช้ร่วมกับ OmniSharp, Solution Explorer, NuGet Gallery และ GitHub Copilot จะได้ประสบการณ์ใกล้เคียงกันมาก และรองรับทั้ง Mac และ Ubuntu
Q: จำเป็นต้องใช้ C# DevKit มั้ย ถ้าพัฒนา .NET บน VSCode?
ไม่จำเป็นครับ C# DevKit ต้องการ license แต่ C# extension (OmniSharp) ซึ่งเป็น open source ให้ IntelliSense, debug, go-to-definition และ refactoring ครบถ้วนโดยไม่มีค่าใช้จ่าย บทความนี้ใช้ OmniSharp เป็นหลักตลอด
Q: OmniSharp กับ Roslyn ต่างกันอย่างไร?
Roslyn คือ compiler platform ของ Microsoft ที่ทำหน้าที่ parse และวิเคราะห์โค้ด C# — OmniSharp คือ Language Server ที่ embed Roslyn ไว้ข้างใน แล้วส่งผลลัพธ์กลับมาแสดงใน VSCode แบบ real-time ทั้งสองทำงานพร้อมกันขณะพิม ไม่ใช่ sequential
Q: GitHub Copilot ช่วยการพัฒนา .NET บน VSCode ได้อย่างไร?
Copilot ช่วยได้ 3 ทาง:
@terminal— generate dotnet CLI command แทนการพิมเอง เหมาะกับทีมที่ไม่ถนัด CLI- Custom Instructions ใน
.github/copilot-instructions.md— ทำให้ Copilot รู้ว่าทีมใช้ Clean Architecture, MediatR, EF Core โดยไม่ต้องอธิบายซ้ำทุกครั้ง /testsใน Copilot Chat — สร้าง unit test ครอบคลุม happy path และ edge cases ได้ทันที
Q: ข้อผิดพลาดที่พบบ่อยเมื่อติดตั้ง .NET บน Mac/Ubuntu คืออะไร?
มี 3 เรื่องที่พบบ่อย:
- ไม่มี
global.json— ทำให้ทีมแต่ละคนใช้ SDK version ต่างกันโดยไม่รู้ตัว แก้ด้วยการวางglobal.jsonที่ solution root พร้อมrollForward: disable - OmniSharp ไม่ทำงาน — เพราะ
.NET Install Toolextension ขาดหาย ต้องติด extension นี้ก่อนเสมอ - บน Ubuntu ใช้
apt-get upgradeแทนapt-get install— ทำให้ไม่สามารถระบุ patch version ได้ ควรใช้apt-get install dotnet-sdk-8.0=<version>ตรงๆ
Q: ควรใช้ VSCode Profile แยกสำหรับ .NET มั้ย?
ควรครับ โดยเฉพาะถ้าทีมเขียนหลายภาษา การแยก profile ทำให้ OmniSharp และ Language Server อื่นๆ ไม่รันพร้อมกัน ลด RAM ได้ชัดเจน switch profile ด้วย Ctrl+Shift+P → Profiles: Switch Profile ได้ทันที
Appendix — ถอนการติดตั้ง .NET ออกจากเครื่องทั้งหมด
ตรวจสอบก่อนถอน
dotnet sdk check # ดู version ทั้งหมดที่ติดอยู่
dotnet --list-sdks # ดู SDK พร้อม path ที่ติดตั้ง
dotnet --list-runtimes # ดู Runtime ที่ติดตั้ง
สิ่งที่ต้องถอนทั้งหมด
| ส่วน | ขนาดโดยประมาณ |
|---|---|
| .NET SDK (1 version) | ~300–500MB |
| .NET Runtime | ~100–200MB |
| NuGet cache | ~500MB–2GB (แล้วแต่ใช้มาเท่าไหร่) |
| OmniSharp cache | ~100–300MB |
| Global tools | แล้วแต่ติดไว้ |
macOS — GUI (แนะนำ)
Microsoft มี uninstall tool โดยเฉพาะ ดาวน์โหลดฟรี:
https://learn.microsoft.com/en-us/dotnet/core/additional-tools/uninstall-tool
เลือก version ที่ต้องการถอน → คลิก Uninstall — ปลอดภัยกว่าลบ folder เองครับ
macOS — Homebrew
brew uninstall dotnet@8
# ถ้าติดแบบ cask
brew uninstall --cask dotnet-sdk
macOS — ลบ folder ตรงๆ (กรณีติดผ่าน install script)
# ดู path ก่อน
dotnet --list-sdks
# output: 8.0.100 [/usr/local/share/dotnet/sdk]
# ลบ SDK version ที่ต้องการ
sudo rm -rf /usr/local/share/dotnet/sdk/8.0.100
# ลบ Runtime ที่เกี่ยวข้องด้วย
sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0
sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/8.0.0
Ubuntu — apt
# ถอน SDK version เดียว
sudo apt-get remove dotnet-sdk-8.0
# ถอนทั้งหมดที่เกี่ยวกับ dotnet
sudo apt-get remove --purge dotnet*
sudo apt-get autoremove
ถอน VSCode Extensions
| Extension | ถอนด้วย |
|---|---|
| C# (OmniSharp) | VSCode Extensions panel → Uninstall |
| .NET Install Tool | VSCode Extensions panel → Uninstall |
| Solution Explorer | VSCode Extensions panel → Uninstall |
| NuGet Gallery | VSCode Extensions panel → Uninstall |
| Roslynator | VSCode Extensions panel → Uninstall |
| .NET Core Test Explorer | VSCode Extensions panel → Uninstall |
| REST Client | ⚠️ ใช้กับภาษาอื่นได้ด้วย แล้วแต่จะเก็บ |
ลบ Cache และ Folder ที่เหลือ
rm -rf ~/.omnisharp/ # OmniSharp cache
rm -rf ~/.nuget/packages/ # NuGet cache
rm -rf ~/.dotnet/ # dotnet folder (กรณีติดผ่าน install script)
ตรวจสอบหลังถอน
dotnet --list-sdks # ควรไม่มี version ที่ถอนแล้ว
dotnet --version # ถ้าถอนหมด command นี้จะ error หรือ command not found
ข้อควรระวัง
| กรณี | ต้องทำอะไร |
|---|---|
ถอน version ที่ global.json ชี้อยู่ | แก้ global.json ให้ชี้ version อื่นก่อน |
| ถอนแล้ว project build ไม่ผ่าน | รัน dotnet sdk check ดูว่ามี version ที่ใช้ได้อยู่มั้ย |
| ถอน runtime แต่ยังมี SDK อยู่ | SDK จะติดตั้ง runtime ให้อัตโนมัติตอน build |
ลำดับที่ควรถอน
1. ถอน VSCode Extensions ทั้งหมดที่เกี่ยวกับ .NET
↓
2. ถอน .NET SDK + Runtime (GUI tool / apt / brew)
↓
3. ลบ NuGet cache → ~/.nuget/packages/
↓
4. ลบ OmniSharp cache → ~/.omnisharp/
↓
5. ลบ ~/.dotnet/ (ถ้าติดผ่าน install script)
↓
6. ตรวจสอบ
dotnet --version ← ควร error หรือ command not found
