123

I am new to ASP.NET MVC. I have used PHP before and it was easy to create a session and select user records based on the current session variables.

I have looked everywhere on the Internet for a simple step-by-step tutorial that can show me how to create and use sessions in my C# ASP.NET MVC 4 application. I want to create a session with user variables that I can access from anywhere in my controllers and be able to use the variables in my LINQ queries.

Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
Thuto Paul Gaotingwe
  • 1,425
  • 4
  • 15
  • 15
  • 2
    possible duplicate of [How to maintain User-session with ASP.NET MVC](http://stackoverflow.com/questions/5769219/how-to-maintain-user-session-with-asp-net-mvc) – KV Prajapati Jan 03 '13 at 12:25
  • 2
    This article might be of interest: http://brockallen.com/2012/04/07/think-twice-about-using-session-state/ – Daniel Hollinrake Jan 03 '13 at 12:27

5 Answers5

170

Try

//adding data to session
//assuming the method below will return list of Products

var products=Db.GetProducts();

//Store the products to a session

Session["products"]=products;

//To get what you have stored to a session

var products=Session["products"] as List<Product>;

//to clear the session value

Session["products"]=null;
Jobert Enamno
  • 4,403
  • 8
  • 41
  • 63
  • 3
    Thanks Jobert! u gave me an idea! just wondering though.., it's is possible to add user variables to a session during login? and also will i have access to session variables (created only once) across different controllers in my application? – Thuto Paul Gaotingwe Jan 03 '13 at 12:44
  • 32
    You can store anything or any data of any type in a session. Once created you can access the value stored to it across all views and controllers. Take note also that session created is only accessible per user and per browser. Meaning the session created by User1 using Firefox cannot be accessed by the same user using IE. There are things also you should not do with session such as. DON'T store large data on it. This may slow the performance of your server. Lastly DON'T store sensitive data to a session such as Password or Credit card number – Jobert Enamno Jan 03 '13 at 12:53
  • 2
    Thanks once more again! Where do i create it to be able to access it across different controllers? – Thuto Paul Gaotingwe Jan 03 '13 at 13:14
  • I thought it was much more complicated, One happy developer here! thanks alot – Mathieu Spillebeen Jan 17 '13 at 13:12
  • 2
    @JobertEnamno is it safe to store the value which comes from `WebSecurity.CurrentUserId` so it doesn't pull it from database multiple times (I found it is very costly)? – Andrius Naruševičius Feb 07 '14 at 11:06
  • Very similar to the Asp.net sessions. – Sangram Nandkhile Mar 17 '14 at 08:55
  • 1
    Use TempData to share data between controllers http://www.gregshackles.com/asp-net-mvc-do-you-know-where-your-tempdata-is/ – Alexandr Jan 14 '15 at 21:22
  • 2
    There is no cross controller session so when you request another controller, for example from `Account/LogOn` to `Home/Index`, `Session["FirstName"]` is `null`. Developers have to create a parent controller (`BaseController`) and define a protected field (`internal protected HttpSessionStateBase SharedSession`) that may expose the shared Session variable in all sub controllers(this assumes that all your app controllers inherit from the `BaseController`) – Bellash Sep 09 '15 at 12:24
  • So, after creating a default ASP.NET application with individual user account authentication I don't feel I need most of the OWIN stuff. Is this a safe alternative to store whoevers logged into a site? – Murphybro2 Aug 31 '17 at 12:10
68

Due to the stateless nature of the web, sessions are also an extremely useful way of persisting objects across requests by serialising them and storing them in a session.

A perfect use case of this could be if you need to access regular information across your application, to save additional database calls on each request, this data can be stored in an object and unserialised on each request, like so:

Our reusable, serializable object:

[Serializable]
public class UserProfileSessionData
{
    public int UserId { get; set; }

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Use case:

public class LoginController : Controller {

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var profileData = new UserProfileSessionData {
                UserId = model.UserId,
                EmailAddress = model.EmailAddress,
                FullName = model.FullName
            }

            this.Session["UserProfile"] = profileData;
        }
    }

    public ActionResult LoggedInStatusMessage()
    {
        var profileData = this.Session["UserProfile"] as UserProfileSessionData;

        /* From here you could output profileData.FullName to a view and
        save yourself unnecessary database calls */
    }

}

Once this object has been serialised, we can use it across all controllers without needing to create it or query the database for the data contained within it again.

Inject your session object using Dependency Injection

In a ideal world you would 'program to an interface, not implementation' and inject your serializable session object into your controller using your Inversion of Control container of choice, like so (this example uses StructureMap as it's the one I'm most familiar with).

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
    }

    public static IUserProfileSessionData GetUserProfileFromSession()
    {
        var session = HttpContext.Current.Session;
        if (session["UserProfile"] != null)
        {
            return session["UserProfile"] as IUserProfileSessionData;
        }

        /* Create new empty session object */
        session["UserProfile"] = new UserProfileSessionData();

        return session["UserProfile"] as IUserProfileSessionData;
    }
}

You would then register this in your Global.asax.cs file.

For those that aren't familiar with injecting session objects, you can find a more in-depth blog post about the subject here.

A word of warning:

It's worth noting that sessions should be kept to a minimum, large sessions can start to cause performance issues.

It's also recommended to not store any sensitive data in them (passwords, etc).

Community
  • 1
  • 1
Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63
  • Where would you put the class definition though? I am pretty new to everything still, but I am just curious about how other controllers will see the the class and know what it is. Do you just add it to the top of the controller? I was thinking on SessionStart in global.asax I would initialize things but maybe that's not the best way to do it. – Shaun314 Apr 23 '14 at 17:48
  • @Shaun314 Ideally you'd use an IoC container to inject the object into your controller via dependency injection (see edit). – Joseph Woodward Apr 23 '14 at 21:32
  • 1
    I'm storing some session information after logging in user using Identity 2. I'm not able to retrieve those information in other actions and controllers else than the first action that I redirect the user to. Any idea? – Akbari Jul 27 '15 at 05:00
18

This is how session state works in ASP.NET and ASP.NET MVC:

ASP.NET Session State Overview

Basically, you do this to store a value in the Session object:

Session["FirstName"] = FirstNameTextBox.Text;

To retrieve the value:

var firstName = Session["FirstName"];
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 10
    There is no cross controller session so when you request another controller, for example from `Account` to `Home`, Session["FirstName"] is null. Developers have to create a `BaseController` and define a protected field (`internal protected HttpSessionStateBase SharedSession`) that may expose the shared `Session` variable in all sub controllers(this assumes that all your app controllers inherit from the `BaseController`) – Bellash Sep 26 '14 at 08:03
  • 5
    Umm, sure there is? There's a Session variable in Controller (the base controller provided by MVC). – aeliusd Dec 01 '15 at 08:48
  • 8
    @Bellash this is completely wrong. Sessions are available across controllers I just set Session["test"] in HomeController then read it in my AccountController. – niico Feb 06 '17 at 10:45
0

You can store any kind of data in a session using:

Session["VariableName"]=value;

This variable will last 20 mins or so.

Pang
  • 9,564
  • 146
  • 81
  • 122
Ulyses
  • 101
  • 1
  • 10
-8

U can store any value in session like Session["FirstName"] = FirstNameTextBox.Text; but i will suggest u to take as static field in model assign value to it and u can access that field value any where in application. U don't need session. session should be avoided.

public class Employee
{
   public int UserId { get; set; }
   public string EmailAddress { get; set; }
   public static string FullName { get; set; }
}

on controller - Employee.FullName = "ABC"; Now u can access this full Name anywhere in application.

mjyazdani
  • 2,110
  • 6
  • 33
  • 64
  • 10
    Storing data on static fields, especially user data like Employee name will cause severe problems in multi-user environments. When two different user logged in the system, they will see the same Employee.EmailAddress since static field on Employee is same for each instance. – Gökçer Gökdal Aug 08 '16 at 04:44