Sessions in ASP.NET Core MVC

Sessions in ASP.NET Core MVC

In this article, I will discuss Sessions in ASP.NET Core MVC Applications with Examples. Please read our previous article discussing the Differences Between Persistent and Non-Persistent Cookies in ASP.NET Core MVC Applications. In web development, sessions enable web applications to store user-specific information on the server side while maintaining a unique session identifier on the client. This enables the application to maintain state and continuity across multiple HTTP requests, despite the stateless nature of the HTTP protocol. ASP.NET Core MVC provides comprehensive, built-in support for managing sessions securely and efficiently.

Why Do We Need Sessions in Web Applications?

The core challenge in web development arises from the HTTP protocol’s stateless nature:

  • Each HTTP request from the client (browser) to the server is independent.
  • The server does not retain any memory or context from previous requests.
  • This makes it impossible to automatically track a user’s state, preferences, or ongoing interactions.

Sessions solve these problems by storing data on the server, with the browser carrying only a small session ID token (usually via a cookie). This approach is more secure and allows storing larger and more complex data compared to client-side cookies. This allows web apps to maintain data such as login status, shopping carts, user preferences, and other stateful information securely on the server.

Real-Time Use Cases of Sessions in Web Applications

The following are some of the real-time scenarios:

  • User Authentication: Track whether a user is logged in by storing authentication data in the session.
  • Shopping Cart: Store cart items for e-commerce users between page visits and browsing sessions.
  • Multi-Step Forms Data: Preserve multi-step form data temporarily as the user navigates pages.
  • User Preferences: Save temporary preferences, such as theme selection, for the current session.
  • Temporary Data Storage: Cache user-specific data that should not be persisted permanently.
How Does Sessions Work in Web Applications?

In web applications, a session is a mechanism for storing information about a user across multiple requests as they interact with a website. Since HTTP is stateless (meaning each request is independent), sessions enable the server to remember who the user is and maintain data such as login status, shopping cart contents, or preferences while the user browses the site. For a better understanding, please refer to the following diagram.

How Does Sessions Work in Web Applications?

Let’s understand how sessions work in web applications, step by step:

Step 1: Client Makes an Initial Request

When you open a website or click on a link, your browser sends a request to the web server to fetch that page. At this point, your browser has no information about a session with the server; it’s a brand-new interaction.

Step 2: Server Creates a Session

When the server receives this initial request, it checks whether a session already exists for this client. Since it’s the first time, no session is found. The server then creates a unique identifier called a session ID (a long, random string), which will be used to track your session across multiple requests.

Step 3: Server Stores Session Data

The server prepares a storage area, called a session store, where it will keep data related to your session. This data could include information such as whether you’re logged in, your shopping cart items, or other preferences. The data is stored on the server, indexed by the session ID created earlier. The session store may be stored in server memory, a database, or a distributed cache system, such as Redis, for larger applications.

Step 4: Server Sends Session ID to Client

The server sends the unique session ID back to your browser in the response, usually inside a cookie. This cookie contains the session ID and is configured with security features such as HttpOnly (preventing client-side scripts from accessing it) and Secure (sent only over HTTPS) to protect the user’s data.

Step 5: Client Stores the Session ID

Your browser receives this session cookie and stores it under the domain of the website. The cookie acts like a ticket that your browser carries to prove its identity to the server on future visits.

Step 6: Client Makes Subsequent Requests with Session ID

Whenever you browse the site further (by clicking links, submitting forms, or loading new pages), your browser automatically includes the session cookie with the session ID in the request headers. This allows the server to recognize that the requests originate from the same session.

Step 7: Server Retrieves Session Data Based on Session ID

Each time the server receives a request with a session ID, it looks up the session store using that ID to retrieve the data associated with your session. If the session ID is valid and the session hasn’t expired, the server loads your stored data to handle the request accordingly.

Step 8: Server Processes the Request

With your session data available, the server can personalize the response. For example, it can check if you are logged in, display your shopping cart items, or apply user-specific settings.

Step 9: Server Updates Session Data (if needed)

If your interaction changes something, like adding an item to your shopping cart, the server updates the session store with this new information, all linked to your session ID.

Step 10: Server Sends Response

After processing, the server sends the response back to your browser. Sometimes it also sends updated session cookies, for example, to refresh expiration times so your session stays active as long as you keep interacting.

Step 11: Idle Timeout and Expiration

Sessions don’t last forever. If you stop interacting with the website for a defined period (typically 20 minutes), the session will expire. This means the server deletes your session data to free resources and for security reasons. When you return after expiration, the server creates a new session with a new session ID.

Important Notes:
  • Each browser gets its own unique session ID. If you open the same website in another browser or device, it will have a different session.
  • The session cookie is typically deleted when the browser closes, although this depends on the cookie settings.
  • The session timeout can be configured according to the application’s specific needs.
  • Proper security settings (like using HTTPS, setting HttpOnly cookies) are critical to protect session data from attacks like hijacking.
Types of Sessions in Web Applications

There are mainly two ways to store session data in web applications, depending on how and where the data is kept:

In-Memory or In-Proc Sessions:
  • This approach stores session data directly in the memory of the web server process handling the request. Because the data is in memory, access is very fast, making it suitable for smaller applications or those running on a single server.
  • However, this method has limitations; if the server restarts or crashes, all session data is lost. Additionally, in environments with multiple servers behind a load balancer, each server has its own separate memory, resulting in session data not being shared across servers and leading to inconsistent user experiences.
Distributed or Out-Proc Sessions:
  • To overcome the limitations of in-memory sessions, distributed session storage moves session data outside the web server process into external storage like databases or caching services (e.g., Redis, Memcached).
  • This allows multiple servers to share the same session data, which is essential in load-balanced or cloud environments where requests can go to any server. Distributed sessions improve scalability, reliability, and fault tolerance since the session data persists independently of any one server’s lifecycle.
How To Use Sessions in ASP.NET Core?

ASP.NET Core MVC offers built-in support for managing sessions with simple configuration and powerful APIs:

  • Enable Session Services and Middleware: To add session support to your application, you need to register the session services and middleware, which handle reading and writing session cookies and managing session data.
  • Store and Retrieve Data: ASP.NET Core sessions use a key-value storage model, allowing you to save and retrieve data using string keys. This is straightforward for managing user-specific data, such as shopping cart contents or login status.
  • Configure Session Options: You can customize how sessions behave by configuring options such as the idle timeout (the duration a session remains active after inactivity), cookie properties (including security flags), and whether the cookie is essential for the application.
Session Storage Mechanisms in ASP.NET Core MVC

ASP.NET Core supports different ways to store session data depending on the deployment environment and requirements:

In-Memory Cache (default):

This is the simplest option where session data is stored in the server’s memory. It’s very fast and easy to use, but only suitable for single-server setups or development purposes, as data is lost when the server restarts or if the app scales horizontally.

Distributed Cache:

In production environments with multiple servers or when high availability is needed,a  distributed cache is preferred. Session data is stored externally and shared by all servers. Common distributed cache providers include:

  • Redis: A fast, in-memory data structure store widely used for distributed caching.
  • SQL Server: Storing sessions in a database for persistence.
  • NCache: A commercial distributed cache for .NET applications.

Using a distributed cache allows your session data to persist even if a server goes down, and enables load balancing without losing session state.

How to Set and Get Session Values in ASP.NET Core MVC

In ASP.NET Core, the ISession interface provides methods for easily working with session data as key-value pairs. These methods are designed for common data types. The following are the common methods you can use:

  • Get(ISession, String): Retrieves the session value as a byte array for a given key. Returns null if the key is not found.
  • GetInt32(ISession, String): Attempts to retrieve an integer value stored under the specified key. If the key doesn’t exist or can’t be converted to an integer, it returns null.
  • GetString(ISession, String): Gets a string value from the session by key. Returns null if the key is missing.
  • SetInt32(ISession, String, Int32): Stores an integer value in the session under the specified key.
  • SetString(ISession, String, String): Stores a string value in the session under the specified key.

For complex objects, you typically serialize them to JSON strings and use SetString and GetString, or use helper extension methods (such as SetObjectAsJson and GetObjectFromJson) to simplify this process.

Example: Implementing Session-Based Shopping Cart in ASP.NET Core MVC:

Let us create a complete, real-world example of implementing a Shopping Cart feature in an ASP.NET Core MVC E-Commerce application using Session. Let us first understand the following about the application.

Product Listing Page:

The Product Listing Page serves as the primary catalog, where users can browse all available products in the store. This page displays product images, names, categories, prices, stock status, and the date the product was added. It gives the user an overview of what is available for purchase. From here, users can click on any product’s “View Details” button to navigate to that product’s detailed page, where they can learn more and decide whether to add it to their cart.

Sessions in ASP.NET Core MVC

Product Details Page:

The Product Details Page focuses on a single product selected by the user. It provides comprehensive information to help the user understand the product better before making a purchase decision. This page is where users make the buying decision.

How To Use Session in ASP.NET Core MVC?

Here,

  • An Add to Cart button that allows users to add the product directly to their shopping cart if it is in stock.
  • A Back to Catalog button to return to the product listing page.
Cart Page:

The cart page displays all the products that the user has added to their shopping cart. This page allows users to review, modify, or finalize their shopping selections before proceeding to checkout.

Sessions in ASP.NET Core MVC Applications with Examples

Let us proceed and implement this application step by step.

Create New ASP.NET Core MVC Project
  1. Open Visual Studio 2022 (or the latest).
  2. Click Create a new project.
  3. Choose the ASP.NET Core Web App (Model-View-Controller) template. Click Next.
  4. Project Name: ECommerceSessionCart
  5. Choose .NET 8.0 (or latest).
  6. Authentication: None.
  7. Create the project.
Product Model

Create a class file named Product.cs within the Models folder and then copy and paste the following code. The Product model defines the structure of your products. It contains fields such as ID, Name, Description, Price, Category, and Stock Quantity. This model holds all the information about each product that you will show to users on the product listing and details pages.

namespace ECommerceSessionCart.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; } = null!;
        public string? Description { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; } = null!;
        public int StockQuantity { get; set; }
        public string? ImageUrl { get; set; }
        public DateTime CreatedDate { get; set; }
        public bool IsActive { get; set; }
    }
}
CartItem Model

Create a class file named CartItem.cs within the Models folder and then copy and paste the following code. The CartItem model represents each item added to the shopping cart. It includes only essential information: product ID, name, description, price, quantity, and image URL. This keeps the cart lightweight and easy to store in session.

namespace ECommerceSessionCart.Models
{
    public class CartItem
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; } = null!;
        public string? Description { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
        public string? ImageUrl { get; set; }
    }
}
Add Session Extensions

Since session storage only supports simple types, you need helper methods to save and retrieve complex objects like lists. The session extension methods serialize objects into JSON strings when storing them and deserialize JSON back into objects when reading from the session.

Create a folder named Helpers at the project root directory. Then, inside the Helpers folder, create a class file named SessionExtensions.cs and copy and paste the following code.

using System.Text.Json;

namespace ECommerceSessionCart.Helpers
{
    public static class SessionExtensions
    {
        public static void SetObjectAsJson(this ISession session, string key, object value)
        {
            session.SetString(key, JsonSerializer.Serialize(value));
        }

        public static T? GetObjectFromJson<T>(this ISession session, string key)
        {
            var json = session.GetString(key);
            return json == null ? default : JsonSerializer.Deserialize<T>(json);
        }
    }
}
Add a Product Service (In-Memory Store)

Create a folder named Services at the project root directory. Then, inside the Services folder, create a class file named ProductService.cs and copy and paste the following code. This service acts as a fake database by holding an in-memory list of products. It provides methods to retrieve all products or get a single product by ID. The controllers use this service to access product data without requiring a physical database.

using ECommerceSessionCart.Models;
namespace ECommerceSessionCart.Services
{
    public class ProductService
    {
        // In-memory product list stored here
        private static List<Product> _products = new()
        {
                new Product
                {
                    Id = 1,
                    Name = "Laptop",
                    Description = "High performance laptop with 16GB RAM and 512GB SSD.",
                    Price = 90000,
                    Category = "Electronics",
                    StockQuantity = 15,
                    ImageUrl = "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?auto=format&fit=crop&w=600&q=80",
                    CreatedDate = DateTime.Now.AddDays(-35),
                    IsActive = true
                },
                new Product
                {
                    Id = 2,
                    Name = "Smartphone",
                    Description = "Latest model smartphone with OLED display and great camera.",
                    Price = 35000,
                    Category = "Electronics",
                    StockQuantity = 40,
                    ImageUrl = "https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?auto=format&fit=crop&w=600&q=80",
                    CreatedDate = DateTime.Now.AddDays(-18),
                    IsActive = true
                },
                new Product
                {
                    Id = 3,
                    Name = "Headphones",
                    Description = "Noise-cancelling over-ear headphones with Bluetooth connectivity.",
                    Price = 7000,
                    Category = "Accessories",
                    StockQuantity = 0,
                    ImageUrl = "https://images.unsplash.com/photo-1511367461989-f85a21fda167?auto=format&fit=crop&w=600&q=80",
                    CreatedDate = DateTime.Now.AddDays(-25),
                    IsActive = true
                },
                new Product
                {
                    Id = 4,
                    Name = "Wireless Mouse",
                    Description = "Ergonomic wireless mouse with adjustable DPI and silent clicks.",
                    Price = 1500,
                    Category = "Accessories",
                    StockQuantity = 25,
                    ImageUrl = "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?auto=format&fit=crop&w=600&q=80",
                    CreatedDate = DateTime.Now.AddDays(-10),
                    IsActive = true
                }
        };

        public List<Product> GetAllProducts()
        {
            return _products;
        }

        public Product? GetProductById(int id)
        {
            return _products.FirstOrDefault(p => p.Id == id);
        }
    }
}
Creating Product Controller:

Create an empty MVC Controller named ProductController within the Controllers folder and then copy and paste the following code. The ProductController manages product-related pages. It fetches all products for the catalog page and details of a specific product for the details page. It passes this data to the respective views for display.

using ECommerceSessionCart.Models;
using ECommerceSessionCart.Services;
using Microsoft.AspNetCore.Mvc;
namespace ECommerceSessionCart.Controllers
{
    public class ProductController : Controller
    {
        private readonly ProductService _productService;

        // Inject ProductService via constructor
        public ProductController(ProductService productService)
        {
            _productService = productService;
        }

        // Show all products
        public IActionResult Index()
        {
            List<Product> products = _productService.GetAllProducts();
            return View(products);
        }

        // Show details of a product by id
        public IActionResult Details(int id)
        {
            Product? product = _productService.GetProductById(id);
            if (product == null)
                return NotFound();

            return View(product);
        }
    }
}
Creating Product Views

First, right-click the Views folder. Click Add > New Folder. Name it Product, where we will create Product Controller-related views.

Add Index.cshtml to List All Products.

Right-click on the new Product folder. Click Add > Razor View. Name it Index.cshtml. Add the following code. The Index.cshtml page lists all products in a table, displaying images, names, categories, prices, and stock status.

@model IEnumerable<ECommerceSessionCart.Models.Product>

@{
    ViewData["Title"] = "Product Catalog";
}

<h2 class="mb-4">@ViewData["Title"]</h2>

<table class="table table-striped table-hover align-middle">
    <thead class="table-dark">
        <tr>
            <th scope="col">Image</th>
            <th scope="col">Name</th>
            <th scope="col">Category</th>
            <th scope="col">Price (₹)</th>
            <th scope="col">Stock</th>
            <th scope="col">Created Date</th>
            <th scope="col">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var product in Model)
        {
            <tr>
                <td style="width: 100px;">
                    <img src="@product.ImageUrl" alt="@product.Name" class="img-thumbnail" style="max-height: 75px; object-fit: contain;" />
                </td>
                <td>@product.Name</td>
                <td>@product.Category</td>
                <td>₹@product.Price.ToString("N2")</td>
                <td>
                    @if (product.StockQuantity > 0)
                    {
                        <span class="badge bg-success">@product.StockQuantity in stock</span>
                    }
                    else
                    {
                        <span class="badge bg-danger">Out of stock</span>
                    }
                </td>
                <td>@product.CreatedDate.ToString("dd MMM yyyy")</td>
                <td>
                    <a asp-action="Details" asp-route-id="@product.Id" class="btn btn-primary btn-sm">View Details</a>
                </td>
            </tr>
        }
    </tbody>
</table>
Add Details.cshtml to Show Product Details.

Right-click the Product folder again. Add another Razor View named Details.cshtml. Add the following code. The Details.cshtml view displays detailed information about a single product, with an “Add to Cart” button that allows users to add it to their cart.

@model ECommerceSessionCart.Models.Product

@{
    ViewData["Title"] = "Product Details";
}
@if (TempData["CartSuccess"] != null)
{
    <div class="alert alert-success alert-dismissible fade show" role="alert">
        <i class="bi bi-check-circle-fill me-2"></i>
        @TempData["CartSuccess"]
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
    </div>
}

<div class="card mb-4 shadow-sm" style="max-width: 900px; margin: auto;">
    <div class="row g-0">
        <div class="col-md-5 d-flex align-items-center bg-light">
            <img src="@Model.ImageUrl" class="img-fluid p-4" alt="@Model.Name" style="max-height: 350px; object-fit: contain; width: 100%;" />
        </div>
        <div class="col-md-7">
            <div class="card-body">
                <h2 class="card-title fw-bold">@Model.Name</h2>
                <h6 class="text-muted">@Model.Category</h6>

                <p class="mt-4">@Model.Description</p>

                <h4 class="text-success my-4">Price: ₹@Model.Price.ToString("N2")</h4>

                <p>
                    @if (Model.StockQuantity > 0)
                    {
                        <span class="badge bg-success fs-6">@Model.StockQuantity in stock</span>
                    }
                    else
                    {
                        <span class="badge bg-danger fs-6">Out of stock</span>
                    }
                </p>

                <p class="text-muted">Added on: @Model.CreatedDate.ToString("dd MMM yyyy")</p>

                <div class="d-flex gap-3 mt-4">
                    <a asp-action="Index" class="btn btn-outline-secondary">Back to Catalog</a>

                    <form asp-controller="Cart" asp-action="AddToCart" method="post" class="m-0">
                        <input type="hidden" name="productId" value="@Model.Id" />
                        @if (Model.StockQuantity > 0)
                        {
                            <button type="submit" class="btn btn-primary px-4">Add to Cart</button>
                        }
                        else
                        {
                            <button type="button" class="btn btn-secondary px-4" disabled>Out of Stock</button>
                        }
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
Creating Cart Controller:

Create an empty MVC Controller named CartController within the Controllers folder and then copy and paste the following code. This controller manages the shopping cart functionality. It reads the cart from the session, allowing the addition of products to the cart, the removal of products, and the clearing of the entire cart. It updates the session data accordingly. The cart data is stored as a JSON string in the session using the extension methods.

using ECommerceSessionCart.Models;
using Microsoft.AspNetCore.Mvc;
using ECommerceSessionCart.Helpers;
using ECommerceSessionCart.Services;
namespace ECommerceSessionCart.Controllers
{
    public class CartController : Controller
    {
        private const string SessionCartKey = "CartSession";
        private readonly ProductService _productService;

        public CartController(ProductService productService)
        {
            _productService = productService;
        }

        // Show cart items
        public IActionResult Index()
        {
            var cart = HttpContext.Session.GetObjectFromJson<List<CartItem>>(SessionCartKey) ?? new List<CartItem>();
            return View(cart);
        }

        // Add product to cart by productId
        [HttpPost]
        public IActionResult AddToCart(int productId)
        {
            var product = _productService.GetProductById(productId);
            if (product == null)
                return NotFound();

            var cart = HttpContext.Session.GetObjectFromJson<List<CartItem>>(SessionCartKey) ?? new List<CartItem>();

            var existingItem = cart.FirstOrDefault(c => c.ProductId == product.Id);
            if (existingItem == null)
            {
                cart.Add(new CartItem
                {
                    ProductId = product.Id,
                    ProductName = product.Name,
                    Description = product.Description,
                    Price = product.Price,
                    Quantity = 1,
                    ImageUrl = product.ImageUrl
                });
            }
            else
            {
                existingItem.Quantity++;
            }

            HttpContext.Session.SetObjectAsJson(SessionCartKey, cart);

            // Store success message in TempData
            TempData["CartSuccess"] = $"{product.Name} has been added to your cart!";

            // Redirect back to product details page to stay on the same page
            return RedirectToAction("Details", "Product", new { id = productId });
        }

        // Remove product from cart
        public IActionResult Remove(int productId)
        {
            var cart = HttpContext.Session.GetObjectFromJson<List<CartItem>>(SessionCartKey) ?? new List<CartItem>();

            var item = cart.FirstOrDefault(c => c.ProductId == productId);
            if (item != null)
            {
                cart.Remove(item);
                HttpContext.Session.SetObjectAsJson(SessionCartKey, cart);
            }

            return RedirectToAction("Index");
        }

        // Clear all items in cart
        public IActionResult Clear()
        {
            HttpContext.Session.Remove(SessionCartKey);
            return RedirectToAction("Index");
        }
    }
}
Creating Cart View.

First, right-click the Views folder. Click Add > New Folder. Name it Cart, where we will create Cart Controller-related views.

Add Index.cshtml View to List All Cart Items

Right-click on the new Cart folder. Click Add > Razor View. Name it Index.cshtml. Add the following code. The cart page displays all items in the user’s cart in a responsive table. It shows product images, descriptions, unit prices, quantities, line totals, and a grand total at the bottom. The page also provides buttons to clear the cart, continue shopping, or proceed to checkout.

@model List<ECommerceSessionCart.Models.CartItem>

@{
    ViewData["Title"] = "Shopping Cart";
}

<h1 class="mb-4">Shopping Cart</h1>

@if (!Model.Any())
{
    <div class="alert alert-info" role="alert">
        Your cart is empty. <a asp-action="Index" asp-controller="Product" class="alert-link">Continue shopping</a>.
    </div>
}
else
{
    <div class="table-responsive">
        <table class="table table-hover align-middle">
            <thead class="table-light">
                <tr>
                    <th scope="col" style="min-width: 150px;">Product</th>
                    <th scope="col">Description</th>
                    <th scope="col" class="text-end" style="width: 120px;">Unit Price</th>
                    <th scope="col" class="text-center" style="width: 100px;">Quantity</th>
                    <th scope="col" class="text-end" style="width: 140px;">Total</th>
                    <th scope="col" class="text-center" style="width: 100px;">Action</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var item in Model)
                {
                    <tr>
                        <td class="d-flex align-items-center gap-3">
                            <img src="@item.ImageUrl" alt="@item.ProductName" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: contain;" />
                            <div>
                                <strong>@item.ProductName</strong>
                            </div>
                        </td>
                        <td>@item.Description</td>
                        <td class="text-end">₹@item.Price.ToString("N2")</td>
                        <td class="text-center">@item.Quantity</td>
                        <td class="text-end fw-semibold">₹@((item.Price * item.Quantity).ToString("N2"))</td>
                        <td class="text-center">
                            <a asp-action="Remove" asp-route-productId="@item.ProductId" class="btn btn-outline-danger btn-sm" title="Remove item">
                                <i class="bi bi-trash"></i>
                            </a>
                        </td>
                    </tr>
                }
            </tbody>
            <tfoot>
                <tr>
                    <th colspan="4" class="text-end fs-5">Grand Total:</th>
                    <th class="text-end fs-5 fw-bold">₹@Model.Sum(i => i.Price * i.Quantity).ToString("N2")</th>
                    <th></th>
                </tr>
            </tfoot>
        </table>
    </div>

    <div class="d-flex justify-content-between mt-4">
        <a asp-action="Clear" class="btn btn-warning">
            <i class="bi bi-trash3 me-1"></i> Clear Cart
        </a>
        <div>
            <a asp-action="Index" asp-controller="Product" class="btn btn-secondary me-2">
                <i class="bi bi-arrow-left me-1"></i> Continue Shopping
            </a>
            <a asp-controller="Checkout" asp-action="Index" class="btn btn-success">
                <i class="bi bi-credit-card me-1"></i> Proceed to Checkout
            </a>
        </div>
    </div>
}
Modify Layout View:

Please modify the _Layout.cshtml view as follows. The layout includes common UI elements, such as the navigation bar and footer. The navbar includes links to products, the cart (with a dynamic item count), home, and privacy pages. It uses Bootstrap for a clean and responsive design.

@using ECommerceSessionCart.Helpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>@ViewData["Title"] - ECommerceSessionCart</title>

    <link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" />
    <link href="~/css/site.css" rel="stylesheet" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom shadow-sm">
            <div class="container">
                <a class="navbar-brand fw-bold fs-4" asp-area="" asp-controller="Home" asp-action="Index">
                    ECommerceSessionCart
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
                        aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarNav">
                    <ul class="navbar-nav ms-auto align-items-center">
                        
                        <li class="nav-item">
                            <a class="nav-link text-primary fw-semibold d-flex align-items-center" asp-controller="Product" asp-action="Index" style="gap: 0.25rem;">
                                <i class="bi bi-grid-fill"></i> Products
                            </a>
                        </li>

                        <li class="nav-item ms-3">
                            @{
                                var cart = Context.Session.GetObjectFromJson<List<ECommerceSessionCart.Models.CartItem>>("CartSession");
                                int count = cart?.Sum(i => i.Quantity) ?? 0;
                                string countDisplay = count > 0 ? $"({count})" : "";
                            }
                            <a class="nav-link text-success fw-semibold d-flex align-items-center" asp-controller="Cart" asp-action="Index" style="gap: 0.25rem;">
                                <i class="bi bi-cart-fill fs-5"></i>
                                <span>Cart</span>
                                <span class="text-muted" style="font-weight: 600;">@countDisplay</span>
                            </a>
                        </li>

                        <li class="nav-item ms-3">
                            <a class="nav-link text-info fw-semibold" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>

                        <li class="nav-item ms-3">
                            <a class="nav-link text-warning fw-semibold" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>

    <main class="container my-4">
        @RenderBody()
    </main>

    <footer class="border-top py-3 text-muted text-center">
        &copy; 2025 - ECommerceSessionCart - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </footer>

    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Register Services & Enable Session

Please modify the Program class as follows. This file configures your application’s services and middleware. It enables session state with a timeout, registers the product service for dependency injection, and sets up routing to direct users to the product listing page by default.

using ECommerceSessionCart.Services;
namespace ECommerceSessionCart
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllersWithViews();

            // Add Memory Cache & Session support
            builder.Services.AddMemoryCache();

            // Distributed caching
            // builder.Services.AddDistributedMemoryCache();

            builder.Services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(30);
                options.Cookie.Name = "ECommerceSessionCart.Session"; //Default Name is .AspNetCore.Session
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            });

            //Register Product Service as Singleton
            builder.Services.AddSingleton<ProductService>();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseSession(); // Add session middleware

            app.UseAuthorization();

            //Home Page will be Index action method of Product Controller
            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Product}/{action=Index}/{id?}");

            app.Run();
        }
    }
}
How to verify the Session Data in a Google Chrome Browser?

To verify session data in Google Chrome, note that session data is stored on the server side, while the session ID is stored in the browser as a cookie. Here’s how you can check session-related info:

  • Step 1: Open Developer Tools: Press F12 or right-click the page and select Inspect to open Chrome DevTools.
  • Step 2: Go to the Application Tab: In DevTools, click the Application tab at the top.
  • Step 3: Locate Cookies: On the left sidebar under Storage, click Cookies. Select your website’s domain from the list.
  • Step 4: Find the Session Cookie: Look for a cookie named similar to .YourAppName.Session (.ECommerceSessionCart.Session). This cookie contains the Session ID, a unique identifier that links your browser to the server-side session data.
Implementing Distributed (Out-Proc) Sessions using SQL Server:

Distributed session management enables your session data to be stored outside the web server process, specifically in a SQL Server database. This approach allows for multiple web servers in a load-balanced environment to share the same session data, ensuring consistency and reliability even when servers restart or fail. This method is essential for scalable, production-ready applications.

Install the Required Package

Install the distributed SQL Server cache provider, which enables your app to store session data in SQL Server. Please execute the following command in the Package Manager Console to install the Packages:

  • Install-Package Microsoft.Extensions.Caching.SqlServer
Prepare SQL Server Database for Session Storage
Create a Database:

First, we need to create a database in your SQL Server instance where session data will be stored. Please execute the following SQL Script to create the SessionDB database.

CREATE DATABASE SessionDB;

Create the Session Table:

Next, we need to create a table to store session data. You can use the .NET CLI tool (dotnet SQL-cache command) which is specifically designed for this purpose. To install it, please run the following command in the command prompt:

dotnet tool install –global dotnet-sql-cache

Then, run the command below in the command prompt to create a session table (e.g., named MySessions) in your database (replace the connection string accordingly):

dotnet sql-cache create “Data Source=LAPTOP-6P5NK25R\SQLSERVER2022DEV; Initial Catalog=SessionDB; Integrated Security=True; TrustServerCertificate=True” dbo MySessions

This creates the table with the necessary structure for storing session data. Once the above command is executed successfully, the MySessions table must be created in the SessionDB database with the following structure:

Implementing Distributed (Out-Proc) Sessions using SQL Server

Understanding the Session Table Structure

The created table (e.g., MySessions) has columns:

  • Id: Unique string identifying each session — this is the session key.
  • Value: Stores serialized session data in binary format.
  • ExpiresAtTime: Timestamp indicating when the session expires. Sessions beyond this time are considered invalid.
  • SlidingExpirationInSeconds: If sliding expiration is enabled, this field shows the time in seconds to extend the session from the last access.
  • AbsoluteExpiration: Defines a fixed expiration time regardless of access.

This structure allows ASP.NET Core to manage the session lifecycle and expiration efficiently.

Storing Connection String in App Settings:

Please, modify the appsettings.json file as follows.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=LAPTOP-6P5NK25R\\SQLSERVER2022DEV;Database=SessionDB;Trusted_Connection=True;TrustServerCertificate=True;"
  }
}
Configure Distributed SQL Server Cache in the Program.cs:

Please modify the Program class as follows. The following setup ensures all session data is stored in your SQL Server MySessions table and shared across servers.

using ECommerceSessionCart.Services;

namespace ECommerceSessionCart
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllersWithViews();

            // Add Distributed SQL Server Cache
            builder.Services.AddDistributedSqlServerCache(options =>
            {
                options.ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection");
                options.SchemaName = "dbo";
                options.TableName = "MySessions";
            });

            //Add Session service
            builder.Services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(30);
                options.Cookie.Name = "ECommerceSessionCart.Session"; //Default Name is .AspNetCore.Session
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            });

            //Register Product Service as Singleton
            builder.Services.AddSingleton<ProductService>();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseSession(); // Add session middleware

            app.UseAuthorization();

            //Home Page will be Index action method of Product Controller
            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Product}/{action=Index}/{id?}");

            app.Run();
        }
    }
}
Running the Application:

Run your application and use the “Add to Cart” functionality or other session-dependent features. You can check the MySessions table in the SessionDB database to see serialized session data entries being created and updated:

Sessions in ASP.NET Core MVC Applications with Examples

Managing Expired Session Data

SQL Server doesn’t automatically clean up expired sessions. Therefore, we need to implement a mechanism to periodically remove old session data. You can create an SQL Server Agent Job or a scheduled task that runs an SQL script to delete expired sessions. The following is an example SQL script that you could run:

DELETE FROM [YourSessionTable] WHERE ExpiresAt < GETUTCDATE();

Replace [YourSessionTable] with the name of your session table. This script deletes all sessions that have expired, as indicated by the ExpiresAt column.

Sessions in ASP.NET Core MVC provide a secure, server-side mechanism to maintain user state and data across HTTP requests. They solve the statelessness problem inherent in HTTP by associating a unique session ID cookie with server-stored data, enabling features such as authentication, shopping carts, form data preservation, and personalized user experiences.

In the next article, I will explain the Differences Between Cookies and Sessions in ASP.NET Core MVC with Examples. In this article, I try to explain Sessions in ASP.NET Core MVC Applications with Examples. I hope you enjoy this Session in the ASP.NET Core MVC Application article.

Registration Open – Microservices with ASP.NET Core Web API

New Batch Starts: 7th July 2025
Session Time: 6:30 AM – 8:00 AM IST

Advance your career with our expert-led, hands-on live training program. Get complete course details, the syllabus, registration, and Zoom credentials for demo sessions via the links below.

Contact: +91 70218 01173 (Call / WhatsApp)

2 thoughts on “Sessions in ASP.NET Core MVC”

Leave a Reply

Your email address will not be published. Required fields are marked *