I'm in the process of migrating a huge project from .net4.8 to .net7.
The solution is basically a tiny web core project called Investo, but it references a huge project called General. 99% of the logic is in General.
in General I have loads of calls to a function called GetUserID, this function (in asp.net 4.8) returns a parameter stored in the HttpContext.Current.Session
. works great for 10 years.
But now when I call it from .net7, which removed the HttpContext.Current
, I can't figure out how to access the state in arbitrary code.
I tried storing it in a global shared variable, but it seems to randomly get disposed or other random errors.
Here is the relevant part of my program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpContextAccessor();
builder.Services.AddSession();
builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<WebData>();
builder.Services.AddScoped<WebData>();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
Core.Options.PersonID = () =>
{
var ses = WebData.CurSession();
if (ses == null) return null;
var sessionData = ses.GetString("WebSession");
if (sessionData == null) return null;
var ws = JsonConvert.DeserializeObject<WebSession>(sessionData);
return ws.PersonID;
};
app.MapGet("/Global/InvokeFunction", (string Name, string JsonInput, HttpContext httpContext) =>
{
//return WebFunctions.InvokeFunction(Name, JsonInput);
//var a = new WebData();
WebData.WebContext = httpContext;
//if(WebData.WebContext ==null) WebData.WebContext = httpContext;
var uid = Core.Functions.GetUserID();
var ret = Web.WebFunctions.InvokeFunction(Name, JsonInput);
var json = Utils.Extensions.ToSafeJson(ret);
return Results.Content(json, "application/json");
});
app.Run();
Here is WebData:
public class WebData
{
private readonly IHttpContextAccessor _httpContextAccessor;
public WebData(IHttpContextAccessor httpContextAccessor) {
_httpContextAccessor = httpContextAccessor; // never fires
}
static public HttpContext WebContext { get; set; }
static public ISession? CurSession() {
var cx = WebContext;
if (cx == null) return null; //OK. maybe background threads etc.
try {
var ses = cx.Session; //this often fails with "object reference not set to instance of an object". even if its a try-catch.
return ses;
}
catch (Exception ex) {
if (!ex.Message.StartsWith("IFeat")) {
var b = 1;//happens often can figure out rhyme or reason why and when it happens. sometimes works sometimes not
}
var a = ex;
}
return null;
}
}
The first 3 lines (regarding IHttpContextAccessor
) I added since I read that it somehow is supposed to help, though in fact it never fires.
Please advise how I can access current session information down the pipeline of MapGet
> InvokeFunction> my whole code base.
If necessary, I'd be glad to provide any additional information.
Thanks in advance!
Update 1
Removing AddSingleton
and AddScoped
seem to have no effect. To the contrary, I think I now have more errors.
My solution for this was
Web Data
to a Static
class & methods so the WebData looks:public static class WebData
{
private static IHttpContextAccessor _httpContextAccessor;
public static void Init(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public static HttpContext? WebContext()
{
if (_httpContextAccessor != null)
return _httpContextAccessor.HttpContext;
return null;
}
public static ISession? CurSession()
{
//var cx = _httpContextAccessor.HttpContext;
var cx = WebContext();
if (cx == null) return null;
try
{
var ses = cx.Session;
return ses;
}
catch (Exception ex)
{
//if (!ex.Message.StartsWith("IFeat"))
//{
// var b = 1;
//}
//var a = ex;
}
return null;
}
}
WebData.Init(builder.Services.BuildServiceProvider().GetRequiredService<IHttpContextAccessor>());
to Program.cs.