IConfiguration vs IOptions NET
Synchronous and Asynchronous in .NET Core
Model Binding and Validation in ASP.NET Core
ControllerBase vs Controller in ASP.NET Core
ConfigureServices and Configure methods
IHostedService interface in .NET Core
ASP.NET Core request processing
| Model-Binding-NET-Core | Model Binding and Validation in ASP.NET Core | |
Synchronous and Asynchronous in .NET Core, C# |
Synchronous: Runs on the calling thread and blocks it until the work finishes.
Asynchronous: Returns quickly with a Task or Task<T>, freeing the calling thread while work completes.
string ReadFileSync(string path)
{
return File.ReadAllText(path); // blocks calling thread
}
async Task<string> ReadFileAsync(string path)
{
return await File.ReadAllTextAsync(path);
}
// synchronous
public IActionResult GetSync()
{
var json = File.ReadAllText("data.json");
return Content(json, "application/json");
}
// asynchronous
public async Task<IActionResult> GetAsync()
{
var json = await File.ReadAllTextAsync("data.json");
return Content(json, "application/json");
}
// synchronous
var items = dbContext.Items.ToList();
// asynchronous
var items = await dbContext.Items.ToListAsync();
async IAsyncEnumerable<int> StreamNumbersAsync()
{
for (int i = 0; i < 100; i++)
{
await Task.Delay(100);
yield return i;
}
}
async void except for event handlers..Result and .Wait().Task.Run in ASP.NET Core.ConfigureAwait(false) in libraries.CancellationToken.try/catch around await.Task / Task<T>, not void.IAsyncEnumerable<T> for streaming data.
// Bad: can deadlock in UI apps
var result = SomeAsync().Result;
In UI apps, this blocks the thread and prevents async continuations from running. ASP.NET Core avoids most of these deadlocks, but blocking is still discouraged.
CancellationToken.Task, not void..Result, .Wait()).ConfigureAwait(false) in libraries.
public async Task<string> DownloadStringWithCancellationAsync(
HttpClient httpClient, string url, CancellationToken ct)
{
try
{
using var resp = await httpClient.GetAsync(
url, HttpCompletionOption.ResponseHeadersRead, ct);
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync(ct);
}
catch (OperationCanceledException) when (ct.IsCancellationRequested)
{
throw;
}
catch (Exception ex)
{
throw new InvalidOperationException("Download failed", ex);
}
}
Synchronous: blocks threads. Good only for trivial CPU-bound work.
Asynchronous: frees threads during I/O. Better scalability, responsiveness, and resource usage.
| Aspect | Synchronous | Asynchronous |
|---|---|---|
| Execution model | Call blocks until work completes | Call returns a Task; awaiting yields while work continues |
| Thread usage | Occupies a thread the entire time | Frees the thread during waits; resumes later on a pooled thread |
| Best for | Short, CPU-bound, in-process work | I/O-bound (DB, HTTP, file, message bus) and bursty load |
| Throughput | Lower under concurrency; risk of thread pool starvation | Higher under concurrency; better scalability |
| Latency for a single call | Same or marginally lower (less machinery) | Same or marginally higher (state machine) |
| UI responsiveness | Risk of freezes | Stays responsive |
| Error propagation | Immediate exceptions | Faulted Tasks; exceptions surface on await |
| Coding model | Straight-line, simple | async/await state machine; “async all the way” |
Sources: The .NET async/await model frees threads during I/O waits and resumes work when results are ready. This improves scalability, not raw speed.
Synchronous call: “Wait here.” Your thread sits idle while the DB/HTTP/file system works. Under load, many threads sit idle, and new requests queue.
Asynchronous call: “Start it, tell me when.” You start the I/O, return the thread to the pool, and resume later when the result arrives. This keeps a small thread pool serving many requests.
Direct answer: Prefer async in ASP.NET Core because it scales better under concurrent I/O. It doesn’t make the DB faster; it stops your server from wasting threads waiting.
// Prefer async: frees thread while DB/HTTP runs
[HttpGet("{id:int}")]
public async Task<ActionResult<ProductDto>> Get(int id, CancellationToken ct)
{
var entity = await _repo.GetByIdAsync(id, ct);
if (entity is null) return NotFound();
return Ok(_mapper.Map<ProductDto>(entity));
}
// Synchronous: blocks thread during I/O (avoid in ASP.NET Core)
[HttpGet("{id:int}")]
public ActionResult<ProductDto> GetSync(int id)
{
var entity = _repo.GetById(id); // Blocks thread
if (entity is null) return NotFound();
return Ok(_mapper.Map<ProductDto>(entity));
}
public async Task<WeatherSummary> GetSummaryAsync(CancellationToken ct)
{
var a = _http.GetStringAsync("svc/A", ct);
var b = _http.GetStringAsync("svc/B", ct);
await Task.WhenAll(a, b); // both awaited concurrently
return Combine(await a, await b);
}
await using var input = File.OpenRead(path);
await using var output = File.Create(destPath);
await input.CopyToAsync(output, 81920, ct);
// Only when you truly want to move CPU work off the request thread
var result = await Task.Run(() => DoCpuIntensiveWork(model), ct);
| Model-Binding-NET-Core | Model Binding and Validation in ASP.NET Core | |