After 3+ years of building enterprise applications
and government portals in ASP.NET Core, I discovered
features that most developers completely ignore.
These are not in tutorials. These are not in YouTube
videos. These are things I learned the hard way —
in production.
## 1. IOptionsSnapshot — Config Jo Live Reload Hota Hai
Most developers use IOptions<T> — but this has one
big problem. It never refreshes after app starts.
❌ Wrong way:
public class MyService
{
private readonly MySettings _settings;
public MyService(IOptions<MySettings> options)
{
_settings = options.Value; // Never updates!
}
}
✅ Right way — use IOptionsSnapshot:
public class MyService
{
private readonly IOptionsSnapshot<MySettings> _options;
public MyService(IOptionsSnapshot<MySettings> options)
{
_options = options; // Refreshes every request!
}
}
Now change appsettings.json — no restart needed!
## 2. Output Caching — Response Cache Se 10x Fast
Most developers use [ResponseCache] — but Output
Caching is way more powerful.
// Program.cs
builder.Services.AddOutputCache();
app.UseOutputCache();
// Controller
[OutputCache(Duration = 60)]
public IActionResult GetData()
{
return Ok(expensiveOperation());
}
Output Caching stores actual response — not just
headers. Result? 10x faster API responses!
## 3. Minimal APIs — Controller Ke Bina API
Nobody uses this in India — but it is incredibly fast:
app.MapGet("/api/users/{id}", async (int id,
IUserService service) =>
{
var user = await service.GetByIdAsync(id);
return user is null ? Results.NotFound()
: Results.Ok(user);
});
No Controller. No [HttpGet]. No [Route].
30% less code. 15% faster than controllers!
## 4. IExceptionHandler — Global Error Handler
Most developers write try-catch everywhere.
❌ Wrong:
public async Task<IActionResult> Index()
{
try { ... }
catch (Exception ex) { ... }
}
✅ Right — One place for all errors:
public class GlobalExceptionHandler : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(
HttpContext context,
Exception exception,
CancellationToken token)
{
context.Response.StatusCode = 500;
await context.Response.WriteAsJsonAsync(new
{
Error = exception.Message,
StatusCode = 500
});
return true;
}
}
// Program.cs
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
Now every exception is handled in ONE place!
## 5. Request Decompression Middleware
Clients can send compressed requests — most APIs
reject them. Enable this hidden feature:
// Program.cs
builder.Services.AddRequestDecompression();
app.UseRequestDecompression();
Now your API accepts gzip/brotli compressed requests.
Result? 40% less bandwidth on large payloads!
## 6. Health Checks — Production Mein Life Saver
Most developers never add health checks — until
production crashes at 3 AM!
builder.Services.AddHealthChecks()
.AddSqlServer(connectionString)
.AddUrlGroup(new Uri("https://api.example.com"))
.AddDiskStorageHealthCheck(setup =>
setup.AddDrive("C:\\", 1024));
app.MapHealthChecks("/health");
Now hit /health — instantly know if DB, API,
or disk is failing!
## 7. Keyed Services — Same Interface, Different Implementation
Ever needed two implementations of same interface?
// Register
builder.Services.AddKeyedScoped<IPaymentService,
RazorpayService>("razorpay");
builder.Services.AddKeyedScoped<IPaymentService,
PaytmService>("paytm");
// Use
public class OrderController
{
public OrderController(
[FromKeyedServices("razorpay")]
IPaymentService payment) { }
}
No more if-else for selecting implementation!
## 8. Rate Limiting — Free DDoS Protection
Most developers buy expensive tools for rate limiting.
It is FREE in ASP.NET Core 7+:
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("api", opt =>
{
opt.PermitLimit = 100;
opt.Window = TimeSpan.FromMinutes(1);
});
});
app.UseRateLimiter();
// Controller
[EnableRateLimiting("api")]
public IActionResult GetData() { }
100 requests per minute — automatic blocking after that!
## 9. Problem Details — Professional API Errors
Most developers return random error formats.
Use RFC 7807 standard:
builder.Services.AddProblemDetails();
// Automatic professional error response:
{
"type": "https://tools.ietf.org/html/rfc7807",
"title": "Not Found",
"status": 404,
"detail": "User with ID 5 not found",
"instance": "/api/users/5"
}
Every big company follows this standard — now you do too!
## 10. Lazy<T> Injection — Heavy Service Load Optimization
Some services are heavy to initialize — but you
may not always use them:
// ❌ Always initializes — even when not needed
public class ReportService
{
private readonly IHeavyPdfService _pdf;
public ReportService(IHeavyPdfService pdf)
{
_pdf = pdf; // Initialized always!
}
}
// ✅ Only initializes when actually used
public class ReportS