MVC code flow


Subtitle: Clear, step‑by‑step explanation of how an ASP.NET Core MVC request travels from client to view and back, with diagrams, sample code, and a practical checklist for .NET developers.


Introduction to MVC flow

Model‑View‑Controller (MVC) is a pattern that separates concerns: Models hold data, Views render UI, and Controllers handle requests and coordinate work. In ASP.NET Core MVC a web request enters the server, passes through middleware, is routed to a controller action, the framework binds inputs to models, the action runs business logic, and finally a result (often a rendered Razor view or JSON) is returned to the client. Understanding each stage helps you debug, test, and optimize apps.


High‑level request flow

Client -> Reverse Proxy -> Kestrel -> Middleware -> Routing -> MVC Middleware
    -> Controller Action -> Model Binding -> Action Execution -> Result Execution
    -> View Rendering (if view) -> Response -> Client

Key components

  • Kestrel: web server that accepts HTTP.
  • Middleware: pipeline components such as exception handling, static files, authentication, and routing.
  • Routing: matches URL to controller/action or endpoint.
  • MVC Middleware: invokes model binding, filters, action, and result processing.
  • Controller Action: your C# method that performs work and returns an IActionResult.
  • View Engine: Razor compiles and renders HTML when a view result is returned.

Detailed MVC lifecycle (step‑by‑step)

1. Request enters server

  • Network: browser or client sends HTTP request.
  • Reverse proxy: optional front door that terminates TLS and forwards to Kestrel.
  • Kestrel: receives request and hands it to ASP.NET Core.

2. Middleware pipeline

  • Order matters: UseExceptionHandler, UseHttpsRedirection, UseStaticFiles, UseRouting, UseAuthentication, UseAuthorization, UseEndpoints or MapControllers.
  • Middleware can short‑circuit and return a response without reaching MVC.

3. Routing and endpoint selection

  • Routing matches the request path and HTTP method to a route template and selects the controller and action.
  • Endpoint metadata (attributes, filters) becomes available after routing.

4. MVC entry: filters and model binding

  • Filters run in this order for incoming request: Authorization filters, Resource filters, Action filters.
  • Model binding maps route values, query string, form data, and JSON body into action parameters or model objects.
  • Model validation runs automatically for bound models and populates ModelState.

5. Action execution

  • Controller action executes with injected services via dependency injection.
  • Action code performs business logic, calls services, and decides the result to return.
  • Action filters can run before and after the action to modify inputs or outputs.

6. Result execution and view rendering

  • Action returns an IActionResult such as ViewResult, JsonResult, RedirectResult, or StatusCodeResult.
  • Result filters run around result execution.
  • If ViewResult: Razor view engine locates and compiles the .cshtml file, executes it with the model, and produces HTML.
  • Response flows back through middleware in reverse order and is sent to the client.

7. Cleanup and logging

  • Resource filters and middleware can perform cleanup.
  • Logs and traces should include a request id to correlate across services.

Simple MVC sequence diagram (text)

Client -> Kestrel: GET /products/42
Kestrel -> Middleware: pass request
Middleware -> Routing: match route "Products/Details/{id}"
Routing -> MVC: select ProductsController.Details(int id)
MVC -> AuthorizationFilter: check access
MVC -> ModelBinder: bind id -> 42
MVC -> ActionFilters: OnActionExecuting
MVC -> ControllerAction: Details(42)
ControllerAction -> Services: fetch product from DB
ControllerAction -> return View(product)
MVC -> ResultFilters: OnResultExecuting
MVC -> ViewEngine: render Razor view to HTML
MVC -> Middleware: response flows back
Kestrel -> Client: 200 OK + HTML

Minimal sample code and explanation

Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<AppDbContext>(...);
builder.Services.AddScoped<IProductService, ProductService>();

var app = builder.Build();
app.UseExceptionHandler("/Home/Error");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

Controller

public class ProductsController : Controller
{
    private readonly IProductService _svc;
    public ProductsController(IProductService svc) => _svc = svc;

    public async Task<IActionResult> Details(int id)
    {
        var product = await _svc.GetByIdAsync(id);
        if (product == null) return NotFound();
        return View(product);
    }
}

View (Razor)

@model Product
<h1>@Model.Name</h1>
<p>Price: @Model.Price</p>

Explanation

  • MapControllerRoute enables conventional routing.
  • Details action receives id via model binding.
  • Service fetches data from DB and returns a ViewResult.
  • Razor view renders HTML using the Product model.

Common pitfalls and best practices

Pitfalls

  • Wrong middleware order breaks auth, CORS, or error handling.
  • Large controllers with business logic make testing hard.
  • Missing model validation leads to runtime errors.
  • Not using idempotency or request ids for critical operations.

Best practices

  • Keep controllers thin and move logic to services.
  • Use DI for testability and single responsibility.
  • Validate models and check ModelState.IsValid.
  • Log a request id early and propagate it to downstream calls.
  • Write integration tests that exercise the full pipeline including middleware and routing.
  • Use filters for cross‑cutting concerns like caching, logging, and exception handling.

Quick checklist for debugging MVC flow

  • Confirm middleware order in Program.cs.
  • Verify route matches the expected controller/action.
  • Check model binding: are parameter names and types correct.
  • Inspect ModelState for validation errors.
  • Ensure filters are not short‑circuiting requests.
  • Verify view path and model type match the Razor view.
  • Run integration tests using TestServer or real Kestrel to reproduce issues.




This was part of Interview Preparation With Bipin — Let’s Crack It!

Comments

Popular posts from this blog

Angular Architecture

Why should I learn Angular?

Solid Principle