Cannot access session asp.net core

16,131

Solution 1

For VS2017, follow this MSDN official article regarding Session and Application state in ASP.NET Core. You can test your scenario in the following example I've created. Note: Although the code below looks lengthy, you will, in fact, only made some minor changes to the default app that gets created from default ASP.NET Core template. Just follow the steps below:

  1. Create an ASP.NET Core MVC app using default template on VS2017

  2. Modify the default Home controller as shown below

  3. Make sure the Startup.cs file has session related entries as shown in Startup.cs file below

  4. Run the app and click on Home link on top bar. This will store the session values shown below (Nam Wam, 2017, and current date)

  5. Click on the About link on the top bar. You will notice that session values were passed to About controller. But I know that was not your question as this only test the passing of session values to another action on the same controller. So, to answer your question, follow the next 3 steps.

  6. Create another controller AnotherController - as shown below - with a new action Test() and a View Test.cshtml inside a Views\Test folder

  7. In _Layout.cshtml add another link <li><a asp-area="" asp-controller="Another" asp-action="Test">Test View</a></li> right after <li>...Contact...</li> link as shown below

  8. Run the app again and first click on the Home link on the top bar. Then click on the Test link on the top bar. You will notice that the session values were passed from HomController to the AnotherController and were successfully displayed on the Test View.

HomeController:

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

namespace MyProject.Controllers
{
    public class HomeController : Controller
    {
        const string SessionKeyName = "_Name";
        const string SessionKeyFY = "_FY";
        const string SessionKeyDate = "_Date";

        public IActionResult Index()
        {
            HttpContext.Session.SetString(SessionKeyName, "Nam Wam");
            HttpContext.Session.SetInt32(SessionKeyFY , 2017);
            // Requires you add the Set extension method mentioned in the SessionExtensions static class.
            HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now);

            return View();
        }

        public IActionResult About()
        {
            ViewBag.Name = HttpContext.Session.GetString(SessionKeyName);
            ViewBag.FY = HttpContext.Session.GetInt32(SessionKeyFY);
            ViewBag.Date = HttpContext.Session.Get<DateTime>(SessionKeyDate);

            ViewData["Message"] = "Session State In Asp.Net Core 1.1";

            return View();
        }

        public IActionResult Contact()
        {
            ViewData["Message"] = "Contact Details";

            return View();
        }

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

    }

    public static class SessionExtensions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }
}

About.cshtml [Displaying session variable values from the same controller]

@{
    ViewData["Title"] = "ASP.Net Core !!";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>


<table class="table table-responsive">
    <tr>
        <th>Name</th>
        <th>Fiscal Year</th>
    </tr>
    <tr>
        <td>@ViewBag.Name</td>
        <td>@ViewBag.FY</td>
    </tr>
</table>

<label>Date : @(ViewBag.Date.ToString("dd/MM/yyyy") != "01/01/0001" ? ViewBag.Date.ToString("dd/MM/yyyy") : "")</label>

AnotherController [A different controller than HomeController]:

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;

public class AnotherController : Controller
{
    const string SessionKeyName = "_Name";
    const string SessionKeyFY = "_FY";
    const string SessionKeyDate = "_Date";

    // GET: /<controller>/
    public IActionResult Test()
    {
        ViewBag.Name = HttpContext.Session.GetString(SessionKeyName);
        ViewBag.FY = HttpContext.Session.GetInt32(SessionKeyFY);
        ViewBag.Date = HttpContext.Session.Get<DateTime>(SessionKeyDate);

        ViewData["Message"] = "Session State passed to different controller";
        return View();
    }
}

Test.cshtml: [Displaying session variable values passed from Home controller to Another controller]

@{
    ViewData["Title"] = "View sent from AnotherController";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>


<table class="table table-responsive">
    <tr>
        <th>Test-Name</th>
        <th>Test-FY</th>
    </tr>
    <tr>
        <td>@ViewBag.Name</td>
        <td>@ViewBag.FY</td>
    </tr>
</table>

<label>Date : @(ViewBag.Date.ToString("dd/MM/yyyy") != "01/01/0001" ? ViewBag.Date.ToString("dd/MM/yyyy") : "")</label>

_Layout.cshtml:

....
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
                    <li><a asp-area="" asp-controller="Another" asp-action="Test">Test View</a></li>
                </ul>
            </div>
....

Startup.cs: [Make sure you have some session related entries included. Most likely when you created an ASP.NET Core MVC app in VS2017, these entries will already be there. But just make sure.]

....
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    //In-Memory
    services.AddDistributedMemoryCache();
    services.AddSession(options => {
        options.IdleTimeout = TimeSpan.FromMinutes(1);//Session Timeout.
    });              
    // Add framework services.
    services.AddMvc();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseSession();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}
....

Solution 2

To use Session in your MVC App, you have to: Install Microsoft.AspNetCore.Session NuGet package.

In Startup.cs ConfigureServices add the AddSession():

services.AddMvc();
services.AddSession(options => {
         options.IdleTimeout = TimeSpan.FromHours(1);
});

In Startup.cs configure add the UseSession():

app.UseSession();
app.UseMvc();

And now you can use it in the controller:

Set the Session

string token="xx";    
HttpContext.Session.SetString("UserToken", token);

Get the stored value

var token = HttpContext.Session.GetString("UserToken");

Additionally, ASP.NET Core 2.1+ introduced some additional extension points like a cookie consent dialog. So we require consent to store cookies from the user.

If you click "Accept" on the privacy banner, then ASP.NET Core is able to write the session cookie.

Share:
16,131
Jeinz Hernandez
Author by

Jeinz Hernandez

Updated on June 17, 2022

Comments

  • Jeinz Hernandez
    Jeinz Hernandez almost 2 years

    Hi please help me im trying to test sessions in asp.net core but when i set the session and get it from other controller it appears to be null

    heres my startup

    public class Startup
    {
    
        public IConfigurationRoot Configuration { get; }
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
    
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc().AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
    
            // Adds a default in-memory implementation of IDistributedCache.
            services.AddDistributedMemoryCache();
    
            services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                options.IdleTimeout = TimeSpan.FromSeconds(600);
                options.CookieHttpOnly = true;
            });
    
    
            services.AddSingleton<IConfiguration>(Configuration);
            services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
            services.AddTransient<IApiHelper, ApiHelper>();
    
    
    
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseSession();
            app.UseDeveloperExceptionPage();
            if (env.IsDevelopment())
            {
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
                    HotModuleReplacement = true,
                    ReactHotModuleReplacement = true
                });
            }
    
            //var connectionString = Configuration.GetSection("ConnectionStrings").GetSection("ClientConnection").Value;
    
    
            app.UseStaticFiles();
            loggerFactory.AddConsole();
    
    
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });
        }
    
        public static void Main(string[] args) {
            var host = new WebHostBuilder()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseKestrel()
                .UseStartup<Startup>()
                .Build();
    
            host.Run();
        }
    }
    

    and here is how i set the session

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
    
            HttpContext.Session.SetString("Test", "Ben Rules!");
    
            return View();
        }
    
        public IActionResult Error()
        {
            return View();
        }
    }
    

    and here my sample code of getting the session again but it appears to be null

        [HttpGet("[action]")]
        public IEnumerable<JobDescription> GetJobDefinitions()
        {
            //this is always null
            var xd = HttpContext.Session.GetString("Test");
    
    
            var x = _apiHelper.SendRequest<Boolean>($"api/JobRequest/GetJobRequest",null);
            var returnValue = new List<JobDescription>();
            returnValue = jobDescriptionManager.GetJobDescriptions();
            return returnValue;
    
    
        }
    

    Thanks for the help

    • Ilya Chumakov
      Ilya Chumakov almost 7 years
      Make sure you provided a session cookie to your GET GetJobDefinitions request. The cookie should sent to the server with each request. The server uses the session ID from the cookie to fetch the session data.
    • Jeinz Hernandez
      Jeinz Hernandez almost 7 years
      Hi illya thanks for answering, can you give me raw example thanks
    • Ilya Chumakov
      Ilya Chumakov almost 7 years
      Make a GET request in browser and look for a cookie named .AspNet.Session in devtools. Browser adds it to next requests automatically within a browser session. docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state
    • nam
      nam almost 7 years
      @JeinzHernandez Please see my example below that shows how you can pass session values from one controller to another controller in ASP.NET Core. Although example looks long, in reality you will only be making minor changes to the default ASP.NET Core MVC app that is created when we use default ASP.NET Core MVC template in visual studio. Just follow the steps described below.