mikeb
mikeb

Reputation: 1

Asp.net Core 3.1 HttpContext.Session.GetString("Index")

I have just started with asp.net Core 3.1 and ran into a problem with using the Session variable(s) to store user login data, basically it returns 'null' randomly when switching between pages or doing an ajax post. I have spend hours on this googling and trying everything I have seen, to no avail. I eventually created a new Razor page web app and I still get the problem with the session variables returning null. To re-produce this, click on the 'Save Changes' button, it will do the HTTP Post, and the session variable 'Index' is null.

I hope someone can help here.

<HTML>

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}


    <script type="text/javascript">
        $("body").on("click", ".Save", function (e) {

            if (confirm("Do you want to Save all your changes?")) {

                var bd = ["test:", "mike"];
                

                $.ajax({
                    type: "POST",
                    url: "/Index?handler=Fred",
                    cache: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN",
                            $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    data: JSON.stringify(bd),
                    contentType: "application/json; charset=utf-8",
                    success: function (r) {
                        $("body").html(r);
                        alert("Update Completed");
                    },
                    error: function (result) { alert("error " + result.statusText) }
                });
            }
        });
     </script>

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>first time to this page [ @ViewData["firsttime"].]</p>
    <p>times to the page [ @ViewData["count"].]</p>
    <p>session ID [ @HttpContext.Session.Id]</p>
    <br />
    <p>times posted [ @ViewData["post"].]</p>
    <a class="Save btn btn-outline-danger btn-sm" href="javascript:;">Save Changes</a>
</div>

<HTML>
```     
        Startup.cs
        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
                services.AddDistributedMemoryCache();
                services.AddSession(o =>
                {
                    o.IdleTimeout = TimeSpan.FromMinutes(60);
                    o.Cookie.HttpOnly = true;
                    o.Cookie.IsEssential = true;
                });
                services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
                services.AddRazorPages();
        }

                public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                
                app.UseHsts();
            }

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

            app.UseRouting();

            app.UseAuthorization();

            app.UseSession();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
```

```Index.chtml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using System.Data;

namespace Grid.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
            if (HttpContext.Session.GetString("Index") == null)
            {
                ViewData["firsttime"] = "yes";
                ViewData["count"] = 1;
                HttpContext.Session.SetInt32("Index", 1);
                HttpContext.Session.SetInt32("Count", 1);
                HttpContext.Session.SetInt32("Post", 0);
                ViewData["post"] = 0;
            }
            else
            {
                ViewData["firsttime"] = "no";
                int? i = HttpContext.Session.GetInt32("Count");
                ViewData["count"] = i++;
                ViewData["post"] = 0;
                HttpContext.Session.SetInt32("Count", (int)i);
            }
        }
        public void OnPostFred([FromBody] object bd)
        {
            if (HttpContext.Session.GetString("Index") == null)
            {
                int? i = HttpContext.Session.GetInt32("Post");
                ViewData["post"] = i++;
                HttpContext.Session.SetInt32("Post", (int)i);
            }
            else
            {
                ViewData["firsttime"] = "session gone";
            }
        }
    }
}
```

Upvotes: 0

Views: 7688

Answers (2)

mikeb
mikeb

Reputation: 1

I did exactly what you said. So I start the project in visual studio in debug mode. On the index page I click on the privacy page, then back to the index page. The Session remains intact. See the HTML taken from F12

````
<HTML>

    <html lang="en"><head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Home page - Grid</title>
        <link href="/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="/css/site.css" rel="stylesheet">
        <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="></script>
    
    </head>
    <body>
        <header>
            <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
                <div class="container">
                    <a class="navbar-brand" href="/">Grid</a>
                    <button class="navbar-toggler" aria-expanded="false" aria-controls="navbarSupportedContent" aria-label="Toggle navigation" type="button" data-target=".navbar-collapse" data-toggle="collapse">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                        <ul class="navbar-nav flex-grow-1">
                            <li class="nav-item">
                                <a class="nav-link text-dark" href="/">Home</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-dark" href="/Privacy">Privacy</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>
        </header>
        <div class="container">
            <main class="pb-3" role="main">
    
                
    
        <script type="text/javascript">
            $("body").on("click", ".Save", function (e) {
    
                if (confirm("Do you want to Save all your changes?")) {
    
                    var bd = ["test:", "mike"];
                    var i = 0;
    
                    $.ajax({
                        type: "POST",
                        url: "/Index?handler=Fred",
                        cache: false,
                        beforeSend: function (xhr) {
                            xhr.setRequestHeader("XSRF-TOKEN",
                                $('input:hidden[name="__RequestVerificationToken"]').val());
                        },
                        data: JSON.stringify(bd),
                        contentType: "application/json; charset=utf-8",
                        success: function (r) {
                            $("body").html(r);
                            alert("Update Completed");
                        },
                        error: function (result) { alert("error " + result.statusText) }
                    });
                }
            });
         </script>
    
    <div class="text-center">
       
        <h1 class="display-4">Welcome</h1>
        <p>first time to this page [ no.]</p>
        <p>times to the page [ 3.]</p>
        <p>session ID [ 33b3e934-206d-0aa8-3db4-0cee6d41a5cf]</p>
        <br>
        <p>times posted [ 0.]</p>
        <a class="Save btn btn-outline-danger btn-sm" href="javascript:;">Save Changes</a>
    </div>
    
            </main>
        </div>
    
        <footer class="border-top footer text-muted">
            <div class="container">
                © 2020 - Grid - <a href="/Privacy">Privacy</a>
            </div>
        </footer>
    
        <script src="/lib/jquery/dist/jquery.min.js"></script>
        <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
        <script src="/js/site.js?v=dLGP40S79Xnx6GqUthRF6NWvjvhQ1nOvdVSwaNcgG18"></script>
        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8GWv3jmnhshAiL19koM-TGi70Yrjt9_nk_EMCmtKd31IWu5kaP9L9bTKTJSNa0M0YxwaUcmaK2pyZBJ9HDIEebyG7OtRRXZAPkWZ-Jxkj3lcmiAFTl1E3R5TOo1taZRzKJbYP-HwcNasWbPwRdv5Uds">
        
    
    
    </body></html>

<HTML>

````

I then click on 'save changes' which does the ajax post and the session("Index") is null. So this is the problem. See the HTML after the ajax post

````
<html lang="en"><head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home page - Grid</title>
    <link href="/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/site.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="></script>

</head>
<body>



    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home page - Grid</title>
    <link href="/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/site.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="></script>



    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" href="/">Grid</a>
                <button class="navbar-toggler" aria-expanded="false" aria-controls="navbarSupportedContent" aria-label="Toggle navigation" type="button" data-target=".navbar-collapse" data-toggle="collapse">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main class="pb-3" role="main">

            

    <script type="text/javascript">
        $("body").on("click", ".Save", function (e) {

            if (confirm("Do you want to Save all your changes?")) {

                var bd = ["test:", "mike"];
                var i = 0;

                $.ajax({
                    type: "POST",
                    url: "/Index?handler=Fred",
                    cache: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN",
                            $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    data: JSON.stringify(bd),
                    contentType: "application/json; charset=utf-8",
                    success: function (r) {
                        $("body").html(r);
                        alert("Update Completed");
                    },
                    error: function (result) { alert("error " + result.statusText) }
                });
            }
        });
     </script>

<div class="text-center">
   
    <h1 class="display-4">Welcome</h1>
    <p>first time to this page [ session gone.]</p>
    <p>times to the page [ .]</p>
    <p>session ID [ 33b3e934-206d-0aa8-3db4-0cee6d41a5cf]</p>
    <br>
    <p>times posted [ .]</p>
    <a class="Save btn btn-outline-danger btn-sm" href="javascript:;">Save Changes</a>
</div>

        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            © 2020 - Grid - <a href="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="/lib/jquery/dist/jquery.min.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="/js/site.js?v=dLGP40S79Xnx6GqUthRF6NWvjvhQ1nOvdVSwaNcgG18"></script>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8GWv3jmnhshAiL19koM-TGilawv_ADn2Bqy2OpVOX7UV3GoyvfC_Nk8KhmRUSvic3XHPq3ID73pBHt5s_UchzAooDOM9IvyyMX2fHn-sV8_n_26OLNgvNmJrukJyQPDJg4ICpAbMdqBoRDsIsk6lXI4">
    


</body></html>

````

Upvotes: 0

Raju Melveetilpurayil
Raju Melveetilpurayil

Reputation: 471

In .Net Core, You can access the session through IHttpContextAccessor. To enable that, you need to add HttpContextAccessor in your service collection in ConfigureServices method in Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddHttpContextAccessor();

            services.AddDistributedMemoryCache();
            services.AddSession(o =>
            {
                o.IdleTimeout = TimeSpan.FromMinutes(60);
                o.Cookie.HttpOnly = true;
                o.Cookie.IsEssential = true;
            });
            services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
            services.AddRazorPages();
        }

Now in your IndexModel page constructor, you can inject the dependencies

private readonly IHttpContextAccessor httpContextAccessor;
        public IndexModel(ILogger<IndexModel> logger,IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            this.httpContextAccessor = httpContextAccessor;
        }

You can Set/Get Session on any page like this

public void OnGet()
        {
            if (httpContextAccessor.HttpContext.Session.GetString("Index") == null)
            {
                ViewData["firsttime"] = "yes";
                ViewData["count"] = 1;
                httpContextAccessor.HttpContext.Session.SetInt32("Index", 1);
                httpContextAccessor.HttpContext.Session.SetInt32("Count", 1);
                httpContextAccessor.HttpContext.Session.SetInt32("Post", 0);
                ViewData["post"] = 0;
            }
            else
            {
                ViewData["firsttime"] = "no";
                int? i = httpContextAccessor.HttpContext.Session.GetInt32("Count");
                ViewData["count"] = i++;
                ViewData["post"] = 0;
                httpContextAccessor.HttpContext.Session.SetInt32("Count", (int)i);
            }
        }

Upvotes: 1

Related Questions