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 Differences Between Persistent and Non-Persistent Cookies in ASP.NET Core MVC Applications. Sessions are one of the several ways to manage state in an ASP.NET Core application. The HTTP protocol is, by default, stateless. But sometimes, it’s essential to hold user data while the user is browsing our website. This data can help us remember the user actions. For example, on an e-commerce website, this data can help to store products in a shopping cart.

What are Sessions in ASP.NET Core MVC?

A session is responsible for storing user data in the web server when browsing a web application. In general, web applications operate on the stateless HTTP Protocol, where each HTTP request is independent. The web server is unable to store anything on the server related to the client’s request. That means the server lacks the ability to retain values used in previous requests. To address this, ASP.NET Core provides the Session feature, which enables the storage and retrieval of user data on the server side.

In ASP.NET Core MVC, sessions are a mechanism for storing and managing user-specific data on the server side across multiple HTTP requests for a given session. Unlike cookies, which are stored on the client side, session data is stored on the server side, enhancing security and reducing the risk of exposing sensitive information.

How Does Session Work in Web Application?

The Session stores data in the Web Server Cache (To store the Session Data, the Server uses a Temporary Caching Mechanism) by creating the SessionId as the key. Then, the same SessionId is sent to the Client (Web Browser) using Cookies. That means the SessionId is stored as a Cookie on the client machine, and these SessionId cookies are sent with every request from client to server. For a better understanding, please have a look at the following diagram.

How Does Session work in Web Application?

Session work as Follows:
  1. First, the Client (Web Browser) will send the HTTP Request to the Server.
  2. Once the server receives the request, it will process it and generate the response. Along with the generated response, it will create a SessionId and then send that SessionId in the Response header using the Set-Cookie key. At the same time, the SessionId will also be stored on the server cache as a key with the required values. If this is not clear at the moment, don’t worry. Once we see the examples, you will understand,
  3. Once the client receives the response, from the next request onwards (as long as the session has not expired), the client will send the HTTP Request along with the cookie (cookie containing the SessionId) in the request header.
  4. Once the server receives the request, it will check the Cookie, get the SessionId from the Cookie, fetch the data from the server cache based on the SessionId, and process the request accordingly.

Note: Each browser has a unique SessionId that is deleted at the end of the session and not shared with other browsers. The default session timeout is 20 minutes but can be configured based on business requirements.

Two types of sessions are available: In-Memory or In-Proc and Distributed or Out-Proc Sessions. In our next article, we will discuss these two types of sessions, their differences, and when to use one over another in detail with examples. 

How To Use Session in ASP.NET Core MVC?

The package Microsoft.AspNetCore.Session offers a middleware component for managing the Session in ASP.NET Core Web Application. 

  1. The Microsoft.AspNetCore.Session Package is included implicitly by the Framework.
  2. The Microsoft.AspNetCore.Session Package Provides Middleware Component for Managing Session State.

To enable the Session Middleware Component in ASP.NET Core Web Application, the Main method of the Program class must contain the following:

  1. Any of the IDistributedCache Memory Cache Service. The IDistributedCache implementation stores user data in the server by creating a SessionId as the key. We will discuss Distributed Caching in detail in our upcoming articles.
  2. A call to the AddSession Service method where we need to configure the session time out, whether the session is essential or not, and whether we want to access the session using HTTP only or not.
  3. A call to the UseSession Middleware component to register the session into the application processing pipeline. It should be registered after the Routing and before the MVC Middleware component. This is because we want the session middleware component to be executed before executing the action method.

The following code snippet shows how to set up the in-memory session provider with a default in-memory implementation of IDistributedCache:

Sessions in ASP.NET Core MVC Applications with Examples

The order of middleware components is important. We must call the UseSession Middleware Component after the UseRouting and before the MapControllerRoute component in the ASP.NET Core MVC Web Application.

  1. HttpContext.Session is only available after the session state is configured.
  2. HttpContext.Session can’t be accessed before UseSession has been called.
Session Options:

In ASP.NET Core MVC, the SessionOptions class provides various properties to configure session behavior. Each of these properties serves a specific purpose, enhancing the functionality and security of your session management. Please have a look at the following AddSessions service:

How To Use Session in ASP.NET Core MVC

Let’s go through each of these properties:

IdleTimeout: The IdleTimeout indicates how long the session can be idle before its contents are abandoned. The session will end if the user does not interact with the session for this time period. Each session access resets the timeout. Example: options.IdleTimeout = TimeSpan.FromMinutes(30); (sets the idle timeout to 30 minutes).

IOTimeout: Determines the maximum amount of time allowed for input/output operations to complete when accessing the session state. Note this may only apply to asynchronous operations. This timeout can be disabled using InfiniteTimeSpan. Example: options.IOTimeout = TimeSpan.FromSeconds(10); (sets the IO timeout to 10 seconds).

Name: Sets the name of the session cookie. Example: options.Cookie.Name = “.MySampleMVCWeb.Session”; (names the session cookie as “.MySampleMVCWeb.Session”). By default, this cookie is named “.AspNetCore.Session”

HttpOnly: Indicates whether the cookie should be accessible only by the server. Setting this to true enhances security by preventing client-side scripts from accessing the cookie. Example: options.Cookie.HttpOnly = true; (makes the session cookie accessible only to the server).

IsEssential: Marks the session cookie as essential for the application to function correctly. This is important for compliance with certain privacy regulations like the EU’s GDPR, where users can reject non-essential cookies. If true, then consent policy checks may be bypassed. The default value is false. Example: options.Cookie.IsEssential = true; (marks the session cookie as essential).

Path: Defines the path for which the cookie is valid. By default, it’s set to /, which means the cookie is sent for all requests on the domain. Example: options.Cookie.Path = “/Home”; (limits the cookie to the specified path).

SecurePolicy: Determines the policy for transmitting the cookie over secure channels like HTTPS, and you can set the value of this property as follows:

  • options.Cookie.SecurePolicy = CookieSecurePolicy.Always; (cookie sent only over HTTPS).
  • options.Cookie.SecurePolicy = CookieSecurePolicy.None; (cookie sent over HTTP or HTTPS).
  • options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; (cookie sent using the same protocol as the request).

So, modify the Main method of the Program class as follows:

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

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

            //Configuring Session Services in ASP.NET Core
            builder.Services.AddDistributedMemoryCache();
            builder.Services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.IOTimeout = TimeSpan.FromSeconds(10);
                options.Cookie.Name = ".MySampleMVCWeb.Session";
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.Cookie.Path = "/";
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            });

            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.UseAuthorization();

            //Configuring Session Middleware in ASP.NET Core
            //It should and must be configured after UseRouting and before MapControllerRoute
            app.UseSession();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            app.Run();
        }
    }
}

Important Note: If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. When two requests seek to modify different session values, the last request may override session changes made by the first.

Set and Get Session Values in ASP.NET Core MVC

In ASP.NET Core, the ISession interface provides methods to work with session data in a key-value pair format. These methods allow us to get and set session values easily. These methods are implemented as extension methods provided for common data types like string and int. The following is the list of ISession extension methods:

  • Get(ISession, String): Retrieves a value from the session as a byte array. If the key does not exist, it returns null.
  • GetInt32(ISession, String): This method tries to read an integer value from the session. If the key is not found or the value cannot be converted to an int, it returns null.
  • GetString(ISession, String): This method retrieves a string value from the session. If the key does not exist, it returns null.
  • SetInt32(ISession, String, Int32): Sets an integer value in the session.
  • SetString(ISession, String, String): Sets a string value in the session.

When using these methods, keep in mind:

  • Session Start: The session must be started before you can set or get values. This is typically done automatically in ASP.NET Core MVC applications.
  • Serialization: The SetInt32 and SetString methods handle the serialization of the given values into the session. On the other hand, GetInt32 and GetString handle deserialization.
  • Types: These methods are convenient for working with simple data types like int and string. For more complex types, you would need to handle serialization and deserialization manually.
  • Lifetime: Session data is temporary and should not be used for long-term storage. It’s typically cleared at the end of the session or when the browser is closed.

Note: Don’t store sensitive data in the session state. The user might not close the browser and clear the session cookie. Some browsers maintain valid session cookies across browser windows. A session might not be restricted to a single user. The next user might continue to browse the app with the same session cookie.

Modifying the Home Controller:

Next, modify the HomeController as follows. As you can see, we have created two constant variables to store the session keys. We store user data in the session object within the Index Action method. Further, if you notice, we are accessing the session data from the About action method.

using Microsoft.AspNetCore.Mvc;
namespace SampleMVCWeb.Controllers
{
    public class HomeController : Controller
    {
        const string SessionUserId = "_UserId";
        const string SessionUserName = "_UserName";
        public IActionResult Index()
        {
            //Let assume the User is logged in and we need to store the user information in the session
            //Storing Data into Session using SetString and SetInt32 method
            HttpContext.Session.SetString(SessionUserName, "pranaya@dotnettutotials.net");
            HttpContext.Session.SetInt32(SessionUserId, 1234567);
            return View();
        }

        public string About()
        {
            //Accessing the Session Data inside a Method
            string? UserName = HttpContext.Session.GetString(SessionUserName);
            int? UserId = HttpContext.Session.GetInt32(SessionUserId);

            string Message = $"UserName: {UserName}, UserId: {UserId}";
            return Message;
        }

        public IActionResult Privacy()
        {
            return View();
        }
    }
}

Note: After 10 seconds, the cookie expires, and you will not get the data once the cookie expires.

How do you Access the Session Object in a View?

To use the Session inside a View, we need to inject the IHttpContextAccessor object into our view, and then we need to use the IHttpContextAccessor object to get the HttpContext and Session. For this, we need to add the following two statements in our view. The first statement adds the namespace and the second statement injects the IHttpContextAccessor, and using this HttpContextAccessor; we can access the HttpContext and Session object.
@using Microsoft.AspNetCore.Http;
@inject IHttpContextAccessor HttpContextAccessor

Modifying the Index.cshtml view:
@using Microsoft.AspNetCore.Http;
@inject IHttpContextAccessor HttpContextAccessor

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-left">
    <b>User Name:</b> @HttpContextAccessor?.HttpContext?.Session.GetString("_UserName")
    <br />
    <b>User Id:</b> @HttpContextAccessor?.HttpContext?.Session.GetInt32("_UserId")
</div>
Modifying the Privacy.cshtml view:
@using Microsoft.AspNetCore.Http;
@inject IHttpContextAccessor HttpContextAccessor

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<div class="text-left">
    <b>User Name:</b> @HttpContextAccessor?.HttpContext?.Session.GetString("_UserName")
    <br />
    <b>User Id:</b> @HttpContextAccessor?.HttpContext?.Session.GetInt32("_UserId")
</div>

You will get the following exception if you run the application with the above changes. This is because we use the HttpContextAccessor service but have not yet configured this service into the built-in IOC container.

Sessions in ASP.NET Core MVC Applications with Examples

Now, we need to configure the HttpContextAccessor service within the Main method of the Program class. The following piece of code does the same.

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

So, modify the Main method of the Program class as follows:

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

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

            //Configuring Session Services in ASP.NET Core
            builder.Services.AddDistributedMemoryCache();
            builder.Services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.IOTimeout = TimeSpan.FromSeconds(10);
                options.Cookie.Name = ".MySampleMVCWeb.Session";
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.Cookie.Path = "/";
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            });

            builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            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.UseAuthorization();

            //Configuring Session Middleware in ASP.NET Core
            //It should and must be configured after UseRouting and before MapControllerRoute
            app.UseSession();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            app.Run();
        }
    }
}

Now, run the application, and by default, it will execute the Index Action Method of the Home Controller and set the session values. Then, it will render the Index view where you can see the session data, as shown in the image below.

Sessions in ASP.NET Core MVC Applications with Examples

When it returns the response to the client (Web Browser), the Web Server also includes the generated SessionId in the response header using the Set-Cookie. To confirm this, open a different web browser, open the developer tool, and then issue a request to the Index action method. Then, go to the Network tab, inspect the request, and go to the Response header. You will see the Set-Cookie property where the web server sends the SessionId and its unique value. This SessionId value is going to be unique per session.

Sessions in ASP.NET Core MVC Applications with Examples

From the next HTTP Request onwards, the Client (Browser) will send the SessionId in the request header using Cookie. Within 10 seconds, if you visit the Privacy page, it will also render the session data, as shown in the image below.

Sessions in ASP.NET Core MVC Applications with Examples

If you check the Network tab and inspect the request, you will see that one cookie is being sent from the client to the web server using the Request header, as shown in the image below. This happens in each and every request from the client to the server as long as the session has not expired.

Sessions in ASP.NET Core MVC Applications with Examples

Again, within 10 seconds, if you visit the About page, it will also render the session data, as shown in the image below.

Sessions in ASP.NET Core MVC Applications with Examples

Now, if you visit the Privacy page (Not the Index page where we store the session data) after 10 seconds, you will not get the session data as shown in the image below.

Sessions in ASP.NET Core MVC Applications with Examples

In this case, it also sends the cookie in the HTTP request header, which is expired. If you want, access the Index Action method, reset the Session timeout, and then the same SessionId will be used.

Advantages and Disadvantages of using Sessions in ASP.NET Core MVC

Sessions have advantages and disadvantages that you should consider when deciding whether to use sessions in your application.

Advantages of Using Sessions in ASP.NET Core MVC:
  1. User State Management: Sessions allow us to manage and maintain user-specific data throughout their interactions with your application. This is useful for scenarios like maintaining user authentication status, shopping carts, and user preferences.
  2. Server-Side Storage: Session data is stored on the server, reducing the risk of exposing sensitive information to clients or tampering.
  3. Flexibility: Sessions can store various types of data, including complex objects and custom data, providing flexibility in the types of information you can manage.
  4. Large Data: Sessions are not as limited in size as cookies, allowing you to store more data.
  5. Centralized Management: ASP.NET Core provides built-in session management mechanisms, including configuration options and different session storage providers.
  6. Scalability: ASP.NET Core supports various session storage options, such as in-memory storage, distributed caches, and external databases, allowing you to scale your application as needed.
  7. Security: Session data is less susceptible to tampering or attacks than client-side storage options like cookies.
Disadvantages of Using Sessions in ASP.NET Core MVC:
  1. Server Resources: Storing session data on the server consumes server memory and resources, which might impact the performance of your application.
  2. Persistence: Session data is typically stored in memory, which means it will lost if we restart the server or in case of server failures.
  3. Complexity: Implementing and managing sessions can introduce complexity to your application architecture, particularly when using distributed session storage.
  4. Data Serialization: Session data often needs to be serialized and deserialized, which can impact performance, especially for complex objects.
When should Sessions be used in ASP.NET Core MVC?

Here are some situations where using sessions is appropriate:

  1. User Authentication and Authorization: Sessions are commonly used to manage user authentication and authorization status. You can store information about the user’s identity and roles in a session to maintain their logged-in state.
  2. User Preferences: Sessions can store and manage user preferences, such as language settings, theme choices, or display preferences. This allows you to provide a customized experience for each user.
  3. Shopping Carts: Sessions are often employed to manage shopping cart data. You can store information about items added to the cart and their quantities, ensuring that the cart contents are retained between page views and interactions.
  4. Form Data Persistence: Sessions can temporarily store form data between multiple steps of a multi-page process. This is useful for scenarios like multi-step forms or wizards.
  5. Temporary Data: Sessions can store temporary data that needs to persist for a short period, such as alerts, notifications, or messages.
  6. User-Specific Data: When you need to maintain user-specific data that doesn’t belong to a database, sessions provide a convenient way to store and access this information.
  7. Cross-Request Communication: Sessions allow you to share data between different requests from the same user, enabling interactions between different parts of your application.
  8. Caching: Sessions can be used for caching frequently accessed data to improve performance and reduce the need for repeated data retrieval.
  9. Single Sign-On (SSO): Sessions can be used for implementing single sign-on across multiple applications, allowing users to authenticate once and access multiple services without repeated logins.

In the next article, I will explain In-Memory or In-Proc and Distributed or Out-Proc 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.

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

Leave a Reply

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