Reputation: 15
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
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:
Note: You should see above infomration while you navigate to your browser application console.
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