ASP.NET CORE Web API - Final Recap & Mega Quiz

14 topics. 30 questions. This is what takes down Zomato at 8pm on Saturday.

Staff Engineer Rule: If you cannot debug a 500 in prod with just logs + Postman, you are not senior. Memorization = junior. Root cause analysis = principal.

1. Recap Table: 14 API Concepts That Crash Production

TopicKey IdeaProduction CodeFAANG Trap - Zomato Incident
Minimal API vs Controllers Controllers = MVC pipeline. Minimal = Endpoint routing only. No filters app.MapGet("/api/restaurants", () => repo.GetAll()); Mixed Minimal + Controllers. Auth filter on controller skipped for Minimal endpoint. GET /api/admin/users exposed. CVE-2024-28001
HTTP Methods GET=Safe+Idempotent. POST=Not. PUT=Idempotent. PATCH=Partial [HttpPut("cart/{id}")] vs [HttpPatch] Used POST for Zomato cart update. Retry on timeout = duplicate items added. $2M refunds. PUT would be idempotent
Model Binding [FromBody]=JSON. [FromQuery]=URL. [FromRoute]=/path/{id}. Only 1 body public IActionResult Order([FromBody] OrderDto dto) [FromBody] + x-www-form-urlencoded = 415. Zomato mobile app crash. OR bound to Entity = Overposting. Hacker sets Order.Total=0.01
Swagger/OpenAPI Swashbuckle generates from XML + Attributes. Use AddSwaggerGen app.UseSwagger(); app.UseSwaggerUI(); Swagger enabled in prod. /swagger/v1/swagger.json leaked admin endpoints. Bots enumerated. Mass scraping. 100k req/s DDoS
Authentication & JWT Bearer token. ValidateIssuer, Audience, Lifetime, IssuerSigningKey builder.Services.AddAuthentication("Bearer").AddJwtBearer() ValidateAudience=false. Hacker reused JWT from dev env on prod. Took over Zomato Gold accounts. Token forgery
Filters & Middleware Middleware=app pipeline. Filters=MVC pipeline. Order matters public class ZomatoLogFilter : IAsyncActionFilter Exception middleware after UseRouting. Exception in routing = Yellow screen. Or Sync filter with Task.Wait = Thread pool starvation
CORS & Security Browser preflight OPTIONS. AllowCredentials!= AllowAnyOrigin policy.WithOrigins("https://zomato.com").AllowCredentials() AllowAnyOrigin + AllowCredentials = CORS error. OR wildcard *.zomato.com allowed evil.zomato.com. CSRF token stolen
API Versioning URL /v1/, Header, Query. DefaultVersion ignored without AssumeDefaultVersionWhenUnspecified services.AddApiVersioning(o => o.ApiVersionReader = new UrlSegmentApiVersionReader()) v2 breaking change deployed. Mobile app still calls /v1/. 404s spike. No fallback. 30% users can't order
Global Error Handling UseExceptionHandler first. Or IExceptionFilter. Never leak stack traces app.UseExceptionHandler("/error"); 500 returned {stackTrace: "at Zomato.Db..."} leaked table names. SQL injection next. Or no logging = silent failures
Async & CancellationToken async Task, not async void. Pass CancellationToken to EF/HttpClient public async Task Get(CancellationToken ct) User closed Zomato app. Request cancelled but DB query still runs 30s. Snowball = DB connection pool exhausted. 503s
Status Codes 200 OK, 201 Created, 204 NoContent, 400 BadRequest, 401 Unauth, 403 Forbidden, 404, 409 Conflict, 500 return CreatedAtAction(nameof(Get), new {id}, dto); Return 200 for POST = client can't get Location header. Return 500 for validation error = monitoring alerts fire. Pager fatigue
Rate Limiting .NET 7+ RateLimiter. FixedWindow, Sliding, TokenBucket, Concurrency app.UseRateLimiter(new RateLimiterOptions()) No rate limit. Bot spams /api/restaurant/search?q=a. DB CPU 100%. Real users 504 Timeout. Zomato down 20min
Content Negotiation Accept header. Json, XML. Return 406 if not supported services.AddControllers().AddXmlSerializerFormatters() Client sends Accept: application/xml. You return JSON anyway. Client crash. OR 406 with no body = hard to debug
ProblemDetails RFC7807. Standard error format. type, title, status, detail, instance services.AddProblemDetails(); app.UseExceptionHandler(); Custom error {msg: "fail"} = frontend can't parse. ProblemDetails gives traceId for correlation. Saves 2 hours debugging

2. The 6 Production Killers - Zomato Code Examples

A. Captive Dependency - Restaurant Data Leak
// STARTUP - THE BUG
builder.Services.AddSingleton<IRestaurantCache, RestaurantCache>();
builder.Services.AddScoped<IZomatoDbContext, ZomatoDbContext>();

public class RestaurantCache : IRestaurantCache {
    private readonly IZomatoDbContext _db; // Captures first request's DbContext
    public RestaurantCache(IZomatoDbContext db) => _db = db;
    public async Task<List<Restaurant>> GetForUserAsync(int userId) {
        // Request #1: User 123. _db cached.
        // Request #2: User 456 calls this. _db still has User 123 data in ChangeTracker
        return await _db.Restaurants.Where(r => r.CityId == GetUserCity(userId)).ToListAsync(); // Returns wrong city
    }
}
// FIX: Inject IServiceScopeFactory, create scope per method call
B. Overposting - Free Zomato Order
// ENTITY
public class Order { public int Id {get;set;} public decimal Total {get;set;} public bool IsPaid {get;set;} }

// BAD API - Binds to Entity
[HttpPost] public IActionResult Create(Order order) { // Hacker posts {total:0.01, isPaid:true}
    _db.Orders.Add(order); _db.SaveChanges(); // BOOM - $0.01 order marked paid
}

// GOOD - Input DTO = Whitelist
public class OrderCreateDto { public List<CartItemDto> Items {get;set;} }
[HttpPost] public IActionResult Create(OrderCreateDto dto) {
    var order = new Order {
        Total = CalculateTotal(dto.Items), // Server calculates
        IsPaid = false // Server controls
    };
    _db.Orders.Add(order); _db.SaveChanges();
}
C. JWT ValidateAudience=false - Account Takeover
// BAD CONFIG
services.AddAuthentication("Bearer").AddJwtBearer(o => {
    o.TokenValidationParameters = new TokenValidationParameters {
        ValidateIssuer = true,
        ValidateAudience = false, // BUG
        IssuerSigningKey = key
    };
});
// Attack: Get JWT from dev.zomato.com. Audience=dev. Replay to api.zomato.com.
// Server accepts because audience not checked. Hacker = you.
// FIX: ValidateAudience = true, ValidAudience = "api.zomato.com"
D. CORS AllowAnyOrigin + AllowCredentials - Cookie Theft
// BAD
builder.Services.AddCors(o => o.AddPolicy("AllowAll", p => {
    p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials();
}));
// Browser blocks this: Cannot use wildcard origin with credentials.
// But if you use.SetIsOriginAllowed(_ => true), it passes.
// Hacker site evil.com makes fetch('https://api.zomato.com/user', {credentials:'include'})
// Browser sends Zomato cookies to hacker. Session hijack.
// FIX:.WithOrigins("https://www.zomato.com", "https://m.zomato.com").AllowCredentials()
E. Exception Middleware Order - Yellow Screen in Prod
// BAD ORDER
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(e => e.MapControllers());
app.UseExceptionHandler("/error"); // TOO LATE
// Exception thrown in UseRouting or Auth = not caught. Unhandled exception = 500 YSOD
// FIX: app.UseExceptionHandler("/error"); MUST be first after app.UseDeveloperExceptionPage
F. No CancellationToken - DB Meltdown
// BAD
[HttpGet("restaurants")] public async Task<IActionResult> Search([FromQuery] string q) {
    return Ok(await _db.Restaurants.Where(r => r.Name.Contains(q)).ToListAsync()); // No CT
}
// User searches, closes app. Request cancelled. But EF query still runs 30s.
// 10k users do this = 10k DB connections stuck. Pool exhausted. All requests 503.
// FIX: ToListAsync(cancellationToken). Pass CancellationToken ct to action.

Mega Quiz ๐Ÿง  - 30 Questions. Zomato API Edition.

Next: Interview Questions - If you missed Q20-Q30, FAANG will reject you. These are Stripe/Uber/Zomato actual incidents.

Comments on ASP.NET CORE Web API - Final Recap & Mega Quiz (0)

No comments yet. Be the first to share your thoughts!