11.14 - Review and Assessment
Mục tiêu bài học
- Nắm được ý chính của bài và mối liên hệ với module.
- Áp dụng được kiến thức vào bối cảnh CRM/.NET backend.
- Sẵn sàng chuyển sang bài kế tiếp với nền tảng chắc chắn.
Nội dung bài học
11.14.1 — Thực hành
Bài 1 — Setup CrmNotificationHub và test cơ bản
Yêu cầu:
- Tạo
CrmNotificationHubvới interfaceICrmNotificationClient - Đăng ký
AddSignalR()vàMapHub<CrmNotificationHub>("/hubs/notifications") - Bật CORS cho SignalR (thêm
AllowCredentials()và whitelist origin) - Tạo HTML test page đơn giản:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/@microsoft/signalr/dist/browser/signalr.min.js"></script>
</head>
<body>
<div id="messages"></div>
<script>
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://localhost:7001/hubs/notifications")
.build();
connection.on("ReceiveNotification", (notification) => {
document.getElementById("messages").innerHTML +=
`<p>[${notification.type}] ${notification.message}</p>`;
});
connection.start()
.then(() => console.log("Connected:", connection.connectionId))
.catch(err => console.error(err));
</script>
</body>
</html>- Tạo endpoint
POST /api/test/notify?userId=xxx&message=yyydùngIHubContextđể push notification - Dùng Postman gọi endpoint và xem message xuất hiện trên HTML page
Kiểm tra: Gửi 5 notification liên tiếp từ Postman, tất cả xuất hiện ngay lập tức trên browser.
Bài 2 — Notification khi Lead status thay đổi
Yêu cầu:
- Tạo entity
Leadvới fieldAssigneeId,Status - Tạo
LeadService.AssignLeadAsync(leadId, assigneeId):- Cập nhật DB
- Tạo
Notificationrecord - Push real-time qua
IHubContext.Clients.User(assigneeId)
- Bảo vệ Hub bằng
[Authorize], cấu hình JWT đọc từ query string - Client TypeScript: connect với token, hiển thị notification dạng toast
Luồng kiểm tra:
- User A (assignee) mở browser, connect Hub với JWT token của mình
- Gọi API
PUT /api/leads/{id}/assignvới body{ assigneeId: "userId-A" } - User A nhận notification ngay lập tức mà không refresh trang
Bài 3 — Notification Center đầy đủ
Yêu cầu:
- Tạo bảng
Notificationstrong DB với các field:Id, UserId, Message, Type, EntityType, EntityId, IsRead, ReadAt, CreatedAt - Implement
NotificationServicevớiSendAsync,MarkAsReadAsync,GetUnreadAsync - API endpoints:
GET /api/notifications?unreadOnly=true&limit=20— lấy danh sáchPUT /api/notifications/{id}/read— đánh dấu đã đọcPUT /api/notifications/read-all— đánh dấu tất cả đã đọc
- Real-time: khi có notification mới → push ngay qua Hub
- Frontend (React hoặc HTML): hiển thị badge số unread, dropdown list, click → đánh dấu đã đọc
Bonus: Implement LeadAssignedEventHandler dùng MediatR notification để tách logic domain event khỏi service.
11.14.2 — Tóm tắt
| Khái niệm | Ghi nhớ |
|---|---|
| Transport negotiation | WebSocket > SSE > Long Polling, SignalR tự chọn |
| Strongly-typed Hub | Dùng Hub<TClient> + interface để compile-time safety |
| JWT trong WebSocket | Truyền qua query string, đọc trong OnMessageReceived |
Groups | Organize connections; join khi connect, leave khi disconnect |
IHubContext | Push từ service/job ngoài Hub; inject IHubContext<THub, TClient> |
| Presence | Track OnConnectedAsync/OnDisconnectedAsync; dùng Redis khi scale |
| Scale-out | Redis backplane hoặc Azure SignalR Service; cần sticky session |
SignalR giải quyết hoàn toàn bài toán real-time cho CRM: notification center, live dashboard, và presence tracking — với developer experience tốt hơn nhiều so với WebSocket thuần nhờ transport fallback, auto-reconnect và strongly-typed API.
11.14.3 — Checklist trước khi sang bài tiếp theo
- Bạn đã nắm được các khái niệm chính và giải thích lại được bằng ví dụ của riêng mình.
- Bạn đã chạy hoặc mô phỏng ít nhất một ví dụ trong bài.
- Bạn đã hoàn thành phần quiz/lab cơ bản (hoặc ít nhất tự làm lại theo trí nhớ).
- Bạn đã ghi lại 3 ý chính: học được gì, còn vướng gì, sẽ áp dụng ở đâu trong CRM.
11.14.4 — Kiểm tra & Thực hành (100 điểm)
11.14.5 — Bối cảnh giáo trình (mục tiêu xuyên suốt)
Trục CRM — một mục tiêu rõ: bạn hướng tới CRM production trong From Zero → Senior .NET (Backend-first). Giáo trình ưu tiên backend, bám chuỗi API → dữ liệu → vận hành → kiến trúc phân tán, thay vì trải rộng theo hướng full-stack. Mỗi module củng cố một lớp kỹ năng trên cùng một CRM học tập bạn phát triển xuyên suốt khóa.
| Chuỗi năng lực | Đóng góp vào CRM học tập |
|---|---|
| Giai đoạn 1 — Foundation | Đọc hiểu yêu cầu, mô hình client–server, Git — nền collaboration khi CRM lớn dần. |
| Giai đoạn 2 — C# + P1 | Domain, OOP, LINQ, async, DI — rule nghiệp vụ & tầng ứng dụng (Inventory là bản mẫu trước CRM). |
| Giai đoạn 3 — ASP.NET + P2 | Host, routing, validation, JWT, SignalR — CRM Backend API thực tế. |
| Giai đoạn 4 — Data + P3 | SQL, EF, cache, job, container — CRM ổn định & có thể triển khai. |
| Giai đoạn 5 — Senior + Final | Clean Architecture, event/outbox, gateway, observability, perf — CRM/ERP chịu tải & có chủ. |
11.14.5.1 — Vai trò giai đoạn này trong chuỗi
ASP.NET Core + Project 2 (CRM API): pipeline, Web API, JWT, SignalR — bề mặt backend mà client/tenant gọi vào.
11.14.5.2 — Vị trí bài học (trước / sau)
| Mốc | Điểm nối trong giáo trình |
|---|---|
| Trước | Module 10 — Authentication + Authorization |
| Tiếp theo | Project 2 — CRM Backend API |
11.14.6 — Quy trình làm bài (hệ thống)
| Bước | Việc cần làm | Output nên có |
|---|---|---|
| 1 | Làm Quiz trước, tự ghi đáp án + 1 dòng lý do | Không xem đáp án; giữ bản nháp |
| 2 | Đối chiếu Đáp án; sửa hiểu sai, ghi takeaway vào README hoặc nhật ký học | 3–5 bullet “tôi đã hiểu…” |
| 3 | Làm Lab theo rubric; trong README nêu phần CRM nào được chạm (Lead, Customer, Deal, Billing…) | Repo / zip + ảnh dotnet run hoặc log |
| 4 | Tự chấm theo bảng điểm; chuẩn bị 1 phút “vấn đáp” nếu mentor hỏi ngẫu nhiên | Điểm + chỗ còn yếu |
11.14.7 — Phần A — Quiz trắc nghiệm (20 điểm)
Gợi ý làm bài: mỗi câu 4 điểm. Ưu tiên suy nghĩ hệ quả trên CRM (tiền, dữ liệu, đa tenant, hiệu năng, bảo mật) — không chỉ nhớ định nghĩa.
Mỗi câu 4 điểm.
SignalR transport fallback thứ tự ưu tiên điển hình (hiện đại)?
A. WebSocket → SSE → long polling B. Chỉ UDP C. FTP D. SMTPĐáp án: A (tinh thần; chi tiết phụ thuộc client/server).
Redis backplane dùng khi?
A. Một instance duy nhất B. Scale-out nhiều server cần broadcast chung C. Thay thế SQL D. Chỉ dev localĐáp án: B.
Hub method nên tránh pattern nào?
A.async TaskB. Gọi DB đồng bộ chặn lâu trong hub mà không scale C. Strongly typed client D. GroupsĐáp án: B (cần thiết kế + async).
Auth SignalR thường truyền JWT qua?
A. Header HTTP khi negotiate/access token theo tài liệu client B. Telnet C. DNS D. ICMPĐáp án: A (accessTokenFactory trên web client).
Sticky session khi không dùng backplane?
A. Luôn cần B. Có thể cần nếu connection không shared giữa node C. Không bao giờ D. Chỉ với gRPCĐáp án: B.
11.14.8 — Phần B — Lab thực tế (80 điểm)
Lab & rubric: trong README, map từng nhóm điểm rubric sang phần CRM (Lead, Customer, Deal, Billing, Notification…) và artifact (test, log, screenshot, migration).
| Tiêu chí | Điểm | Ghi chú |
|---|---|---|
| Hub + client (console JS hoặc .NET client) nhận message real-time | 30 | |
[Authorize] trên hub; từ chối kết nối không token | 25 | |
| Gửi notification khi có sự kiện domain (tạo Lead, assign…) | 15 | |
| README: scale-out cần Redis hay chưa — giải thích | 10 |
11.14.8.1 — Ngưỡng tổng điểm (Quiz 20 + Lab 80)
| Mức | Điểm | Ý nghĩa |
|---|---|---|
| Đạt | ≥ 70 | Đủ nền để học module kế mà không “lủng” kiến thức cốt lõi. |
| Khá | ≥ 85 | Có minh chứng code + nêu được liên hệ CRM rõ ràng trong README. |
| Giỏi | ≥ 95 | Có mở rộng / edge case / ADR ngắn / test bổ trợ (tùy rubric từng bài). |
11.14.9 — Phần C — Reflect & nối chuỗi (không chấm điểm)
Viết 5–8 câu (README hoặc docs/learning-log.md):
- Kiến thức module / project này sẽ được tái sử dụng trực tiếp ở module hoặc project CRM nào tiếp theo? (ghi tên module / P2 / P3 / Final).
- Nếu bỏ qua phần lab, rủi ro lớn nhất cho CRM ở giai đoạn sau là gì?
- Một quyết định kỹ thuật (nhỏ) bạn sẵn sàng ghi thành ADR một đoạn sau khi làm lab.
11.14.10 — Tài liệu tham khảo
- ASP.NET Core SignalR — Official Docs
- SignalR JavaScript Client
- Authentication and Authorization in SignalR
- Scale out SignalR with Redis
- Azure SignalR Service
- SignalR Hub API Guide
Bài tập tổng hợp
- Tóm tắt bài học bằng ngôn ngữ của bạn.
- Liên hệ nội dung với một tình huống thực tế trong dự án.
- Đề xuất một cải tiến cụ thể sau khi học bài này.
Tự kiểm tra
- Bạn có thể giải thích lại nội dung chính trong 2 phút không?
- Bạn có ví dụ áp dụng thực tế chưa?
- Bạn biết bước tiếp theo cần học/triển khai là gì không?
Kết luận
Hoàn thành bài này giúp bạn có góc nhìn đầy đủ hơn trước khi đi tiếp trong module.
Điều hướng
- Bài trước: 11.13 — Ví dụ thực tế nhanh
- Bài tiếp theo: Không có (bài cuối module).
- Về module: Trang mục lục