ASP.NET MVC · Security & State

Session Management

HTTP forgets you between requests. Session state gives each visitor a private locker on the server — perfect for a shopping cart, dangerous if you fill it with everything.

Intermediate 6 min Lesson 21 of 37Covers ASP.NET MVC 5.2 on .NET Framework 4.8.
0/37 in ASP.NET MVC
On this page · 6 min · Intermediate

Learning objectives#

  • Store and read per-user data with Session
  • Explain how the session cookie links requests
  • Choose a session mode for one server or a web farm
  • Clear a session on logout

Explanation#

Session["Cart"] = cart stores an object for the current visitor. ASP.NET gives each browser a random id in the ASP.NET_SessionId cookie and keeps the data on the server under that id.

Values come back as object, so cast them: var cart = Session["Cart"] as List<CartLine> ?? new List<CartLine>(). A missing key returns null.

Sessions expire after 20 minutes without requests by default (sessionState timeout in Web.config). Session.Remove("Cart") removes one value; Session.Abandon() ends the whole session, for example on logout.

InProc mode (the default) keeps data in the web server’s memory: fast, but lost when the app pool recycles and not shared between servers. StateServer and SQLServer modes store it outside the process, so objects must be [Serializable].

Session requests from the same user are processed one at a time (session locking). Long requests make other tabs wait; mark read-only controllers with [SessionState(SessionStateBehavior.ReadOnly)].

Syntax#

C# Illustrative
Session["Cart"] = cart;                           // store
var cart = Session["Cart"] as List<CartLine>;     // read (null if missing)
Session.Remove("Cart");                           // remove one value
Session.Abandon();                                // end the session

Code example: A session-based shopping cart#

C#CartController.cs Illustrative
// Models/CartLine.cs
using System;


namespace ShopSite.Models
{
    [Serializable]                         // required for StateServer / SQLServer modes
    public class CartLine
    {
        public string Product { get; set; }
        public int Quantity { get; set; }
    }
}


// Controllers/CartController.cs
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ShopSite.Models;


namespace ShopSite.Controllers
{
    public class CartController : Controller
    {
        private const string CartKey = "Cart";


        private List<CartLine> GetCart()
        {
            var cart = Session[CartKey] as List<CartLine>;
            if (cart == null)
            {
                cart = new List<CartLine>();
                Session[CartKey] = cart;
            }
            return cart;
        }


        [HttpPost]
        public ActionResult Add(string product)
        {
            var cart = GetCart();
            var line = cart.FirstOrDefault(l => l.Product == product);
            if (line == null) cart.Add(new CartLine { Product = product, Quantity = 1 });
            else line.Quantity++;
            return RedirectToAction("Index");
        }


        public ActionResult Index()
        {
            var cart = GetCart();
            var lines = cart.Select(l => 
quot;
{l.Product} x{l.Quantity}");
return Content(
quot;Cart (
{cart.Sum(l => l.Quantity)} items): {string.Join(", ", lines)}", "text/plain");
} [HttpPost] public ActionResult Clear() { Session.Abandon(); return RedirectToAction("Index"); } } }
Expected output
POST /Cart/Add product=Gel+Pen
302 Found → /Cart

POST /Cart/Add product=Notebook
302 Found → /Cart

POST /Cart/Add product=Gel+Pen
302 Found → /Cart

GET /Cart
200 OK
Cart (3 items): Gel Pen x2, Notebook x1

POST /Cart/Clear
302 Found → /Cart

GET /Cart
200 OK
Cart (0 items):

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. The first POST creates a session: the response sets the ASP.NET_SessionId cookie and the cart list is stored under "Cart".
  2. The browser sends the cookie back with every request, so later requests find the same cart and add to it.
  3. Adding Gel Pen again increases its quantity because the stored list object is updated in place.
  4. Clear calls Session.Abandon(); at the end of that request the session data is thrown away, and the next request starts with an empty cart.

Real-world use case#

A small online bookshop on a single IIS server keeps carts in InProc session. When it grows to two load-balanced servers, carts randomly vanish — the fix is moving session to SQL Server mode (or storing carts in the database keyed by user).

Common mistakes#

Storing large objects

Whole product lists or DataTables in session use memory for every visitor and slow down out-of-process modes. Store ids and small DTOs.

InProc session behind a load balancer

Each server has its own memory, so a user bouncing between servers loses their session. Use StateServer, SQLServer or sticky sessions.

Using session for authentication

Session["UserId"] is not a login system: it has no protection against fixation and no expiry rules of its own. Use Forms or OWIN cookie authentication.

Best practices#

  • Wrap session access in one helper with constant keys
  • Keep session data small and [Serializable]
  • Use out-of-process modes on web farms
  • Call Session.Abandon() on logout

Remember this#

Session = per-visitor server locker, keyed by a cookie.

InProc is fast but lost on recycle and not shared.

Cast on read; null means missing.

Practice exercise#

Your task: Count how many pages a visitor has viewed in this session and show “Page views: N”.

Need a hint?
Read Session["Views"] as int?, add 1 and store it back.
Show solution
C# Illustrative
// Controllers/VisitsController.cs
using System.Web.Mvc;


namespace ShopSite.Controllers
{
    public class VisitsController : Controller
    {
        public ActionResult Index()
        {
            var views = (Session["Views"] as int? ?? 0) + 1;
            Session["Views"] = views;
            return Content(
quot;Page views:
{views}", "text/plain");
} } }
Expected output
GET /Visits
200 OK
Page views: 1

GET /Visits
200 OK
Page views: 2

GET /Visits
200 OK
Page views: 3

Mini quiz#

Session Management quizMultiple choice Question 1 of 3

How does ASP.NET know which session belongs to a request?

Score so far: 0/0

Want more? Practise all ASP.NET MVC MCQs · ASP.NET MVC interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.