ASP.NET MVC 5 (.NET Framework) — Folder Structure, Request Life Cycle and Features
In short: An architectural pattern separating concerns: the Model holds data and business rules, the View renders the UI (Razor templates), and the Controller receives requests, works with the model/services and chooses the response.
- Benefits: testable controllers, clean URLs, full HTML control, parallel work on UI and logic.
In short: Request → IIS/ASP.NET pipeline → UrlRoutingModule matches a route → MvcRouteHandler → MvcHandler → controller factory creates the controller → ControllerActionInvoker selects the action → authentication and authorization filters → model binding and validation → action filters (before) → action executes and returns an ActionResult → action filters (after) → result filters → result executes (ViewResult → Razor view engine finds and renders the view) → response.
- Exception filters handle errors along the way.
Controllers (classes ending in Controller), Models, Views/<Controller>/<Action>.cshtml with Views/Shared for layouts/partials and _ViewStart.cshtml, App_Start (RouteConfig, FilterConfig, BundleConfig, IdentityConfig), Areas for modules with their own MVC folders, Content (CSS), Scripts (JS), App_Data, Global.asax for startup, Web.config (plus Views/web.config for Razor settings).
In short: ViewData is a string-keyed dictionary and ViewBag a dynamic wrapper over the same data — both live only for the current request (controller → view).
- TempData survives until it is read in a subsequent request (stored in session by default), so it's used for messages after a redirect;
Keep/Peekretain it longer. - Prefer strongly typed view models for real data.
In short: ViewResult (View), PartialViewResult, RedirectResult/RedirectToRouteResult (Redirect, RedirectToAction), JsonResult, ContentResult, FileResult (File), JavaScriptResult, HttpStatusCodeResult/HttpNotFoundResult, EmptyResult.
- Actions can also return plain types, which are converted to ContentResult.
In short: Attributes/classes that run logic before or after stages of action execution: authentication filters, authorization filters ([Authorize]), action filters (OnActionExecuting/Executed), result filters (OnResultExecuting/Executed) and exception filters ([HandleError]).
- Order: authentication → authorization → action → result, with exception filters on errors; they can be applied globally, per controller or per action.
In short: Conventional routes are defined centrally (MapRoute("{controller}/{action}/{id}")) and matched in order.
- Attribute routing (MVC 5,
routes.MapMvcAttributeRoutes()) puts[Route]/[RoutePrefix]on controllers/actions — clearer for REST-style or custom URLs, with inline constraints ({id:int}). - Both can be combined; attribute routes are usually registered first.
In short: The DefaultModelBinder uses value providers (form, route, query string, files) to fill action parameters by name, including complex and nested objects and collections.
- Data annotations and
IValidatableObjectvalidate the model; errors go intoModelState, checked withModelState.IsValid. - Unobtrusive jQuery validation mirrors the rules on the client.
- Use view models to avoid over-posting.
In short: A partial view is a reusable template rendered with data you pass (Html.Partial).
- A child action (
Html.Action) invokes a controller action that loads its own data and returns a partial — for self-contained widgets. - ASP.NET Core removed child actions in favour of view components, which are lighter (no full action pipeline).
In short: Use a container (Unity, Autofac, Ninject, Simple Injector), register services with lifetimes (per-request for DbContext), and set it as the MVC DependencyResolver (and a separate resolver for Web API 2).
- The controller factory then constructs controllers with their dependencies through constructor injection.
In short: After a successful POST, redirect (302) to a GET action instead of returning a view.
- It prevents duplicate submissions when the user refreshes, gives a clean URL, and pairs with TempData for success messages.
In short: CSRF: @Html.AntiForgeryToken() in forms and [ValidateAntiForgeryToken] on POST actions (plus SameSite cookies).
- XSS: Razor encodes
@output by default — avoidHtml.Rawon user input, validate input, use Content Security Policy. - Also
[Authorize], HTTPS, parameterised queries, and view models against over-posting.
Register a global exception filter (HandleErrorAttribute or a custom IExceptionFilter) for errors inside controllers/views, override OnException where needed, use Application_Error in Global.asax for everything else (including 404s from routing), log with a logging framework, and configure customErrors/httpErrors for friendly error pages with correct status codes.
In short: Areas divide a large MVC application into functional sections (Admin, Billing, Reports), each with its own Controllers, Models and Views and route registration (AreaRegistration).
- They keep large projects organised and allow same-named controllers in different areas.
- In ASP.NET Core they work similarly with
[Area("Admin")].
In short: Incremental migration: create an ASP.NET Core app in front with YARP proxying unmigrated routes to the MVC 5 app;
- share authentication (shared cookie/data protection or a common identity provider) and session via System.Web adapters;
- move shared logic into netstandard libraries;
- migrate controller by controller (largely copy with small changes), replace child actions with view components, bundling with a build tool,
HttpContext.Currentusages with injected services; - delete old routes as they move.
[OutputCache]. How do you fix it while keeping performance?In short: Review the cache key: vary by the right parameters (VaryByParam, VaryByCustom for user/culture), shorten the duration, use Location = Client/None for per-user data, or move to data caching in the service layer with explicit invalidation when data changes (remove the cache entry on update).
- Never cache personalised pages server-side without varying by user.