Search code examples
c#asp.netasp.net-corewebformssession-state

Session is Null in .net standard class library when passed from .NET 8 WebApp


I have .NET 8 WebApp, and .NET Standard 2.0 class library. I am using System.WebAdapters 1.4 so that I can do incremental migration from ASP.NET 4.8 WebApp to .NET 8 WebApp.

My .NET 8 WebApp Program.cs

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.SystemWebAdapters;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddSystemWebAdapters()
    .AddJsonSessionSerializer(options =>
    {
        // Serialization/deserialization requires each session key to be registered to a type
        options.RegisterKey<int>("IncidentID");
    });

builder.Services.Configure<KestrelServerOptions>(options =>
{
    options.AllowSynchronousIO = true;
});

// If using IIS:
builder.Services.Configure<IISServerOptions>(options =>
{
    options.AllowSynchronousIO = true;
});

// Add configuration services to access settings
var configuration = builder.Configuration;


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

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

app.UseSystemWebAdapters();

app.UseAuthorization();

app.MapRazorPages().RequireSystemWebAdapterSession();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
         name: "ashxRoute",
                    pattern: "uicomponents/handlers/{*path}",
                    defaults: new { controller = "LegacyHandler", action = "ProcessRequest" }).RequireSystemWebAdapterSession();
});

app.Run();

My Controller File,

using Microsoft.AspNetCore.Mvc;
using company.SharedHandlers.Handlers;
using Microsoft.AspNetCore.SystemWebAdapters;

namespace SampleWebApp
{
    public class NoiseWordsController : Controller
    {
        //private readonly IHttpContextAccessor _httpContextAccessor;

        //public NoiseWordsController(IHttpContextAccessor httpContextAccessor, ISessionManager)
        //{
        //    _httpContextAccessor = httpContextAccessor;
        //}
        [Session]
        [Route("uicomponents/handlers/NoiseWords.ashx")]
        public IActionResult Index()
        {
            NoiseWords noiseWords = new NoiseWords();
            System.Web.HttpContext.Current.Session["IncidentID"] = "200";
            noiseWords.ProcessRequest(HttpContext);
            return View();

        }
    }
}

After running the project, I get

InvalidOperationException: No service for type 'Microsoft.AspNetCore.SystemWebAdapters.ISessionManager' has been registered.
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider)
Microsoft.AspNetCore.SystemWebAdapters.SessionLoadMiddleware.ManageStateAsync(HttpContext context, ISessionStateFeature feature)
Microsoft.AspNetCore.SystemWebAdapters.PreBufferRequestStreamMiddleware.InvokeAsync(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

When I remove Session attribute from controller, and also remove RequireSystemWebAdapterSession(). Then I get NULL Session at System.Web.HttpContext.Current.Session["IncidentID"] = "200";

My goal is to pass this session to my class library.

using System.Web;
using System.Xml.Linq;

namespace company.SharedHandlers.Handlers
{
    public class NoiseWords : BaseHandler
    {
        public string cleanString = null;

        protected override void DoProcess(HttpContext context)
        {
            // list of potential operations.
            switch (RequestParam("sp"))
            {
                case "NoiseWords":
                    context.Response.ContentType = "text/xml";
                    context.Response.Headers["CacheControl"] = "no-cache";
                    context.Response.AddHeader("Pragma", "no-cache");
                    context.Response.Headers["Expires"] = "-1";
                    context.Response.Write("NoiseWords operation");

                    break;
             
            }
        }
    }
}

Here, in the above method I should be able to access the Session info (IncidentID).

What should I do?


Solution

  • Create an interface for example ISessionStore. Put it in a common place so that any project can have access to it.

    Implement it in the net core project like so:

    public class SessionStore:ISessionStore
    {
     private readonly HttpContextAccessor _context;
     public SessionStore(HttpContextAccessor context)
     {
       _context = context
     }
      //Implement methods for getting and setting session data
    }
    

    Then register with the net core DI and pass the interface between net standard and netcore libraries.

    Hope this helps.