Maarten
Maarten

Reputation: 497

System.InvalidOperationException when using HttpContext.Session with use.Session(); set

I am developing a .NET Core 3.0 application using Razor pages for a project in my studies. The application is going to use a login feature and I am want to use sessions to send data and verify what user is logged in.

For this I have decided to use HttpContext.Session to get and set strings during post.

When I use the line: HttpContext.Session.SetString("username", "test");

I get the error: System.InvalidOperationException: 'Session has not been configured for this application or request.'

After some extensive googling and using a Microsoft doc I cannot seem to find a solution. Everywhere I get the answer that I need to include services.AddSession and app.UseSession(); in my Startup.cs file which I do, These are all added before the 'UseMvc();' lines.

I have run out of options and my software teacher does not want to give me any help aside from "are you using the correct version" which I think I do according to the Microsoft docs.

What am I missing that causes this error? How can I get sessions to work? Am I implementing it wrong?

Below is my Startup.cs class:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        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.AddRazorPages();
            services.AddSession(options =>
            {
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.IdleTimeout = TimeSpan.FromSeconds(10);
            });
            services.AddMvc(option => option.EnableEndpointRouting = false);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

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

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

            app.UseMvc();
        }
    }

Notable is when I use app.UseHttpContextItemsMiddleware(); between app.UseSession(); and app.UseMvc(); I get an Intellisense error that says IApplicationBuilder does not have this method. In the Microsoft docs it is show that this string is included in Startup.cs.

Upvotes: 2

Views: 5001

Answers (1)

itminus
itminus

Reputation: 25360

Everywhere I get the answer that I need to include services.AddSession and app.UseSession(); in my Startup.cs file which I do, These are all added before the 'UseMvc();' lines.

Yes, you're right. However, either invoke UseMvc() or invoke UseRouting()+ UseEndpoints(), but don't invoke them both. As of ASP.NET 3.0, I would suggest you should use UseRouting()+ UseEndpoints() instead of the UseMvc().

In your original codes, the UseEndpoints() is triggered before UseSession() which makes the MVC/Razor Page execute before UseSession(). To fix that issue, change your code as below:

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

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    // put UseSession before the line where you want to get the session. 
    // at least, you should put it before `app.UseEndpoints(...)`
    app.UseSession();     

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        // if you need mvc, don't forget to 
        //      add `services.AddControllersWithViews` 
        //      and add this line
        endpoints.MapControllerRoute(
            name: "default-controller",
            pattern: "{controller=Home}/{action=Index}/{id?}"); 
    });

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

    app.UseMvc();    
}

Upvotes: 3

Related Questions