The MVC Pattern and Request Life Cycle

This section documents ASP.NET MVC 5.3.x, ASP.NET Web API 2.2, ASP.NET Web Pages 3, OWIN/Katana, SignalR 2, and ASP.NET Identity 2 — all running on .NET Framework 4.8.1 — the System.Web-hosted MVC framework, its routing, Razor views, HTML helpers, model binding, filters, and the OWIN-based authentication/Identity stack — as described by the official documentation at Microsoft Learn (plus Web API, Web Pages, SignalR, and Identity), which are the reference these pages are written and verified against.

This is not ASP.NET Core MVC. ASP.NET MVC 5 is the pre-Core, System.Web-hosted MVC framework; it is functionally frozen and receives only security fixes. For the current, cross-platform MVC framework see MVC Controllers and Views under ASP.NET Core (Blazor).

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

This page documents ASP.NET MVC 5.3.x on .NET Framework 4.8.1 — not ASP.NET Core MVC. It traces one request end to end and explains where each extensibility point sits.

Model, View, Controller as applied here

  • Model — plain C# classes (POCOs), commonly EF6 entities or dedicated view models — see Data Access with EF6. MVC imposes no base class on a model.

  • View — a .cshtml Razor template that renders a model to HTML (or another format). See Razor Syntax.

  • Controller — a class deriving from System.Web.Mvc.Controller, grouping related action methods that handle requests, manipulate the model, and choose a view. See Controllers and Actions.

Unlike Web Forms, where a page’s markup and code-behind are tightly coupled to a Control tree and view state, MVC deliberately separates these three concerns so each can be tested and replaced independently — this is the central architectural difference covered in the table below.

The request pipeline, step by step

sequenceDiagram participant C as Client participant URM as UrlRoutingModule participant MRH as MvcRouteHandler participant MH as MvcHandler participant CF as IControllerFactory participant Ctl as Controller participant AI as IActionInvoker participant AR as ActionResult participant VE as IViewEngine C->>URM: HTTP request URM->>URM: match RouteTable.Routes -> RouteData URM->>MRH: route's IRouteHandler MRH->>MH: GetHttpHandler() -> new MvcHandler(RequestContext) MH->>CF: CreateController(controllerName) CF->>Ctl: new HomeController(...) MH->>Ctl: Controller.Execute(RequestContext) Ctl->>AI: ActionInvoker.InvokeAction(...) AI->>AI: select action, bind parameters, run filters AI->>AR: invoke action -> ActionResult AR->>VE: ExecuteResult(ControllerContext) VE->>VE: FindView() -> RazorViewEngine renders .cshtml VE-->>C: HTTP response (HTML)
  1. UrlRoutingModule — an IHttpModule registered in web.config that hooks PostResolveRequestCache and matches the incoming URL against RouteTable.Routes (populated by RouteConfig.RegisterRoutes; see Routing and Areas). A match produces RouteData carrying the route’s IRouteHandler.

  2. MvcRouteHandler — the IRouteHandler that every MapRoute call implicitly wires up; its GetHttpHandler returns an MvcHandler for the matched RequestContext.

  3. MvcHandler — the IHttpHandler (async, via IHttpAsyncHandler) that is MVC’s actual entry point in the System.Web pipeline. It resolves an IControllerFactory (ControllerBuilder.Current.GetControllerFactory) and asks it to create the controller named in the route.

  4. IControllerFactory  — DefaultControllerFactory locates a Controller-derived type by naming convention ({name}Controller) and instantiates it, optionally through IControllerActivator so a DI container can supply constructor dependencies.

  5. IActionInvoker — ControllerActionInvoker (via Controller.ActionInvoker) selects the action method using action selectors, binds its parameters via model binding (see Model Binding and Validation), and runs the filter pipeline around the call (see Filters).

  6. The action returns an ActionResult; ActionResult.ExecuteResult is then called with the current ControllerContext. For ViewResult this locates and renders a view through the view engine (RazorViewEngine, resolved via the ViewEngines.Engines collection — see Views, Layouts, and Partials).

See Lifecycle of an ASP.NET MVC 5 Application and ASP.NET Application Life Cycle Overview for IIS 7.0 for the underlying System.Web request pipeline that hosts all of this.

Extensibility at each step

Step Substitute by

Route matching

A custom RouteBase (rarely needed; attribute routing and MapRoute cover almost every case).

IRouteHandler

A custom IRouteHandler in place of MvcRouteHandler (uncommon).

IControllerFactory

ControllerBuilder.Current.SetControllerFactory(…​) — the classic seam for wiring a DI container (Ninject, Autofac, Unity) into controller construction.

IActionInvoker

Controller.ActionInvoker per controller, or a custom IActionInvoker for cross-cutting action-selection logic.

ActionResult

Any custom ActionResult subclass overriding ExecuteResult (e.g. a CSV or PDF result).

IViewEngine

ViewEngines.Engines.Add(new MyViewEngine()) — see Views, Layouts, and Partials.

MVC vs. Web Forms

ASP.NET MVC 5 ASP.NET Web Forms

Request entry point

MvcHandler via UrlRoutingModule

A Page-derived IHttpHandler per .aspx file

UI unit

Action method returning an ActionResult

A Page with a server-side control tree

State model

Stateless per request; explicit TempData/Session

ViewState, postbacks, control events

Markup

Razor .cshtml, no code-behind coupling

.aspx + code-behind, runat="server" controls

Testability

Controllers/actions unit-testable in isolation

Requires the ASP.NET runtime or heavy mocking

HTML control

Full — you own every tag

Partial — server controls render their own markup

Next: Controllers and Actions covers what happens inside step 5-6 above in detail.