keyvan
keyvan

Reputation: 15

ASP.NET Core 6 session get returns null

I am using ASP.NET Core 6 with razor pages.

I can set the session like the code below but when I stop and run the project, the session get is returning null, but if I set the session again in a post request through a form and button it appears again!

I changed the options in program.cs but nothing seems to be working.

I am confused about this problem! I have an example project in .NET 3 and it keeps the session but mine is not working

This is how I set the session:

HttpContext.Session.SetInt32(Constants.ShoppingCart, count);

And I get it like this in my Layout.cs:

@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor HttpContextAccessor
@if (HttpContextAccessor.HttpContext.Session.GetInt32(Constants.ShoppingCart) != null)
{
    <a href="~/cart/Index" class="btn btn-primary navbar-btn">
        @{
            var count = HttpContextAccessor.HttpContext.Session.GetInt32(Constants.ShoppingCart);
        }

        <i class="fa fa-shopping-cart"></i>
        <span>@count items in cart</span>
    </a>
}

My program.cs file:

using AspDotNetApps.Core.Middleware;
using AutoMapper;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using System.Text.Json.Serialization;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost
   .CaptureStartupErrors(true)
   .UseSetting("detailedErrors", "true");

builder.Services.AddControllersWithViews()
                .AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

var keysDirectoryName = "mydir";

var keysDirectoryPath = Path.Combine(builder.Environment.ContentRootPath, keysDirectoryName);
if (!Directory.Exists(keysDirectoryPath))
{
    Directory.CreateDirectory(keysDirectoryPath);
}
builder.Services.AddDataProtection()
  .PersistKeysToFileSystem(new DirectoryInfo(keysDirectoryPath))
  .SetApplicationName("store")
  .SetDefaultKeyLifetime(TimeSpan.FromDays(30));


builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy(Constants.AdminRole, policy => policy.RequireRole(Constants.AdminRole));
});

builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
    options.Cookie.Name = ".JewelryStore.Session";
    options.IdleTimeout = TimeSpan.FromHours(24);
    options.Cookie.IsEssential = true;
    options.Cookie.HttpOnly = true;
});

builder.Services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => false;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromDays(2);
    options.SlidingExpiration = true;
    options.LoginPath = $"/Admin/Login";
    options.LogoutPath = $"/Admin/Logout";
    options.AccessDeniedPath = $"/Areas/Admin/AccessDenied";
});

builder.Services.AddRazorPages();

builder.Services.AddCors(options => options.AddPolicy("Cors", builder =>
{
    builder
    .AllowAnyHeader()
    .AllowAnyMethod()
    .WithHeaders("accept", "content-type", "origin")
    .AllowAnyOrigin();
}));



builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();


 
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
Mapper.Initialize(x =>
{
    x.AddProfile<MappingProfile>();
});


builder.Services.AddMvc()
             .AddRazorPagesOptions(options =>
             {
                 options.Conventions.AuthorizePage("/Admin", "Main");
             });

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var context = services.GetRequiredService<ApplicationDbContext>();
     context.Database.Migrate();
}

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error/500");
    app.UseStatusCodePagesWithRedirects("/Error/{0}");
    app.UseHsts();
}
app.UseCors("Cors");
app.UseSecurityHeadersMiddleware(
      new SecurityHeadersBuilder()
     .AddDefaultSecurePolicy());

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

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();
 
app.UseSession();

app.MapRazorPages();

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
    endpoints.MapControllers();
    // redirects the admin when using /admin route to the admin area
    endpoints.MapAreaControllerRoute(
        "admin",
        "admin",
        "Admin/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllerRoute(
        "default", "{controller=Home}/{action=Index}/{id?}");

});
 
app.Run();

Upvotes: 0

Views: 1171

Answers (1)

Md Farid Uddin Kiron
Md Farid Uddin Kiron

Reputation: 22495

I can set the session like the code below but when I stop and run the project, the session get is returning null, but if I set the session again in a post request through a form and button it appears again!I am confused about this problem! I have an example project in .NET 3 and it keeps the session but mine is not working

Well, I think you are certainly misunderstanding between session and cookie concept. Session of course has nothing to deal with browsers and while application stops or shutdown session must not retain at all. So the project in .NET 3 you are referring definitely something dealing with cookies.

In addition, If you want to keep some value on browser and want to retrieve it even the browser closed and if cookies doesn't expire you would like it to get back in that scenario, you must need to deal with cookie for sure.

So far, I have gone through your requirement, you can only implement using cookie not session.

Razor Page cshtml.cs

public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
       

        private readonly IHttpContextAccessor _contextAccessor;
        public IndexModel(ILogger<IndexModel> logger, IHttpContextAccessor contextAccessor)
        {
            _logger = logger;
            _contextAccessor = contextAccessor;
        }

        public void OnGet()
        {
            var count = HttpContext.Request.Cookies["_count"];

           
            if (count == null)
            {
                CookieOptions options = new CookieOptions();
                options.Expires = DateTime.Now.AddHours(1);
                _contextAccessor.HttpContext?.Response.Cookies.Append("_count", "600", options);
            }
            

        }

    }

Razor Page cshtml

@page
@model IndexModel
@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor HttpContextAccessor
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>


<h1>Current Count: @HttpContextAccessor.HttpContext.Request.Cookies["_count"]</h1>

program.cs

builder.Services.AddRazorPages();
builder.Services.AddHttpContextAccessor();

Output:

enter image description here

Note: You should see above infomration while you navigate to your browser application console.

enter image description here

Note: Your implementation and the behavior are correct in regards of session as it wouldn't keep anyting once the server or app restarted. However, if you would like to keep some value and want to retrieve it from browser side, you must need to use cookie. If you will need more information, please have a look on our official document here

Upvotes: 1

Related Questions