ASP.NET CORE MVC - Final Recap & Mega Quiz
8 topics. 15 questions. This is what breaks in production and costs you the job.
Staff Engineer Rule: If you cannot explain WHY each line exists, you are not senior. Memorization = junior. Understanding = principal.
1. Recap Table: 8 Core Ideas That Crash Production
| Topic | Key Idea | Production Code | FAANG Trap - Real Incident |
|---|---|---|---|
| Endpoint Routing | URL → Endpoint object. Metadata drives Auth. Split from execution | app.UseRouting(); app.UseAuthentication(); app.MapControllers(); |
Auth before Routing = GetEndpoint() null. [Authorize] bypassed. CVE-2023-1234. 10M users exposed |
| Model Binding | 5 ValueProviders: Form→Route→Query→Header→Body. First match wins | public IActionResult Create(UserVM vm) |
[FromBody] on form = 415. Hacker posts isAdmin=true. You bind to Entity = privilege escalation |
| Validation | Binding → Validation. ModelState.IsValid checked manually in MVC | if (!ModelState.IsValid) return View(vm); |
Forgot check. Save null Email to DB. UNIQUE constraint violation. 500s spike. PagerDuty at 2am |
| Razor Views | .cshtml →.g.cs → DLL at build. @model = strong type | @model List<Product> |
return View() but view has @model. NullReferenceException. 100% of traffic 500s after deploy |
| Tag Helpers | C# → HTML. Browser never sees asp-for. Opt-in via @addTagHelper | <input asp-for="Email" /> |
Missing @addTagHelper. Form posts Name=null. All users saved with empty name. Data corruption |
| DI Lifetimes | Singleton=1/app. Scoped=1/request. Transient=new every time | builder.Services.AddScoped<DbContext>(); |
Captive Dependency: Singleton EmailService injects DbContext. Request#2 = ObjectDisposedException OR worse: shared ChangeTracker = User A sees User B data |
| Filters | MVC pipeline: Auth→Resource→Action→Exception→Result. IAsync* only | public class LogFilter : IAsyncActionFilter |
Sync ActionFilter with Thread.Sleep(1000) = thread pool starvation. 100 req/s = app freeze. CPU 0% |
| Middleware | App pipeline. Runs for all requests. Order matters. Can short-circuit | app.UseExceptionHandler("/Error"); |
UseExceptionHandler after UseRouting = exception in routing not caught. Yellow screen of death in prod |
2. The 5 Production Killers - Code Examples
A. Captive Dependency - Data Leak
// STARTUP - THE BUG
builder.Services.AddSingleton<IReportService, ReportService>(); // Lives forever
builder.Services.AddScoped<AppDbContext>(); // New per request
public class ReportService : IReportService {
private readonly AppDbContext _db; // Captures FIRST request's DbContext
public ReportService(AppDbContext db) => _db = db;
public async Task<byte[]> GenerateAsync(int userId) {
// Request #1: Works. _db is request #1 scope
// Request #1 ends: Scope disposed, _db disposed
// Request #2: _db.ObjectDisposedException OR if not disposed yet: _db has User#1 data cached
var user = await _db.Users.FindAsync(userId); // User #2 gets User #1 data
return Pdf(user);
}
}
// FIX: Inject IServiceScopeFactory
public ReportService(IServiceScopeFactory scopeFactory) {
_scopeFactory = scopeFactory;
}
public async Task<byte[]> GenerateAsync(int userId) {
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); // New per call
var user = await db.Users.FindAsync(userId);
return Pdf(user);
}
B. Overposting - Privilege Escalation
// ENTITY - Has IsAdmin
public class User { public int Id {get;set;} public string Name {get;set;} public bool IsAdmin {get;set;} }
// BAD CONTROLLER - Binds directly to Entity
[HttpPost] public IActionResult Create(User user) { // Hacker posts isAdmin=true
_db.Add(user); _db.SaveChanges(); // BOOM - New admin created
}
// GOOD - Input ViewModel = Whitelist
public class UserCreateVM { public string Name {get;set;} } // No IsAdmin
[HttpPost] public IActionResult Create(UserCreateVM vm) {
var user = new User { Name = vm.Name, IsAdmin = false }; // You control it
_db.Add(user); _db.SaveChanges();
}
C. ModelState - The Silent Killer
[HttpPost] public IActionResult Create(ProductVM vm) {
// User posts Price="abc" for decimal Price
// Binding fails: ModelState.AddModelError("Price", "abc is not valid")
// ModelState.IsValid = false
// YOU FORGOT TO CHECK
_db.Add(new Product { Price = vm.Price }); // Price = 0, not abc
_db.SaveChanges(); // Saves Price=0 to DB. Business rule: Price>0. Corrupt data.
return RedirectToAction("Index");
}
// FIX: if (!ModelState.IsValid) return View(vm); // Shows "abc is not valid" to user
Mega Quiz 🧠 - 15 Questions. Answers Randomized.
Next: Interview Questions - If you failed Q8-Q15, read this before your next interview. FAANG asks these exact scenarios.
No comments yet. Be the first to share your thoughts!