I am trying to retrieve some data from db and store it some Session variable in order to have it in _Layout.cshtml on all pages, no matter what page the user will access from the start.
Global.asax:
protected void Application_Start()
{
...
Manager mng = new Manager();
HttpContext.Current.Session["company-cellphone"] = mng.GetContacts().CompanyCellphone;
}
Error: Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
you are trying to access the session from Application_Start but there is no live Session yet.
session is not available in all events of global.asax
as a workaround try this:
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
HttpContext context = HttpContext.Current;
...
Manager mng = new Manager();
HttpContext.Current.Session["company-cellphone"] = mng.GetContacts().CompanyCellphone;
}
}
I'm not sure about your requirement but I would recommend to access the session in controller.initialize method
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
//// access session here
requestContext.HttpContext.Session["company-cellphone"]=mng.GetContacts().CompanyCellphone;
}
Application_Start runs before any sessions can be created. And a session is specific to a single client connecting to your application.
You can create a static class and store the company-cellphone value in it.
In your Models folder create a new class file named Global.cs in that file create a static class with properties that will hold your application level information.
public static class Global
{
static string companyCellPhone;
public static string companyCellPhone
{
get
{
return this.companyCellPhone;
}
set
{
this.companyCellPhone= value;
}
}
Then your Application_Start method would look something like this:
protected void Application_Start()
{
...
Manager mng = new Manager();
Global.companyCellPhone = mng.GetContacts().CompanyCellphone;
}
I'm going to go out on a limb and guess that this is a single global value to be viewed by all users. In that case you could store the value in HttpApplicationState rather than HttpSessionState:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
Application["YourValue"] = "SomeValue";
}
}
I'm not necessarily advocating its use. But just as Session can store user-specific values, Application stores values that are global to the application.
Related
My purpose here is to make sure that all the logged in users should not get logged out if application pool stops or restarts.
One way is that i can use out prox sessions and directly store them in database but this is going to impact application performance so i dont want to do that.
Another way i found is that, i can register a "IRegisteredObject" implemented class object in hosting environment.
public class SessionTracker : IRegisteredObject
{
//I created this class as singleton and exposed GetInstance method
public void Stop(bool immediate)
{
//Here i want to get all the sessions and store them in database
}
}
Register it in global object
public class Global : System.Web.HttpApplication
{
protected void Application_Start(Object sender, EventArgs e)
{
HostingEnvironment.RegisterObject(SessionTracker.GetInstance());
}
}
I want to get all the active session of application so that i can store them in database at the time of application pool restarts or stops suddenly.
Now when my application starts, at that time i will load all the database stored session states again and all the session states will be valid.
Also i found that i can use Session start and Session end events and add sessions in a list object. I am not sure how efficient it will be as it can take more memory in server side.
Please suggest a approach by which i can get all the sessions at once. Or Is it okay if i use session start and session end event of global.ascx.cs file? Is it going to impact memory utilization?
I did further investigation and created a POC to check if it creates copy of Sessions by reference or by value.
What i found is that it creates copy by reference. So technically there is no memory utilization issue if i add their reference in SessionTracker class. Here the complete implementation of SessionTracker class if somebody is interested to know about it
public class SessionTracker : IRegisteredObject
{
static readonly SessionTracker Tracker = new SessionTracker();
private static readonly Dictionary<string, HttpSessionState> _sessions = new Dictionary<string, HttpSessionState>();
private static readonly object padlock = new object();
private SessionTracker()
{
}
public void Stop(bool immediate)
{
try
{
//store them in database
}
catch (Exception ex)
{
throw;
}
}
public void AddSession(HttpSessionState session)
{
lock (padlock)
{
_sessions.Add(session.SessionID, session);
}
}
public void RemoveSession(HttpSessionState session)
{
lock (padlock)
{
_sessions.Remove(session.SessionID);
}
}
public static SessionTracker GetInstance()
{
return Tracker;
}
}
Quick Question...
In MVC5, are variables in the Global.asax accessible via all sessions or does MVC create and instance of Global for each session?
Example
public class Global : System.Web.HttpApplication
{
public static string Current_UserName = "";
protected void Session_Start(object sender, EventArgs e)
{
Current_UserName = User.Identity.Name;
}
}
So would user A Current_UserName change when user B loads the application?
Current_UserName would essentially be the last user that initialized their session. So user B who accesses the app after user A would show "B" in the static variable.
As Current_UserName user is static, the last assigned user will remain in that variable. I mean, the last session initiated user.
According to this guide:
https://github.com/mspnp/azure-guidance/blob/master/Retry-Service-Specific.md
They say:
Note that the StackExchange.Redis client uses multiplexing through a single connection. The recommended usage is to create an instance of the client at application startup and use this instance for all operations against the cache. For this reason, the connection to the cache is made only once, and so all of the guidance in this section is related to the retry policy for this initial connection—and not for each operation that accesses the cache.
Right now I have something like this:
public static Models.UserProfile GetUserProfile(string identityname)
{
/// It needs to be cached for every user because every user can have different modules enabled.
try
{
var cachekeyname = "UserProfileInformation|" + identityname;
IDatabase cache = CacheConnectionHelper.Connection.GetDatabase();
Models.UserProfile userProfile = new Models.UserProfile();
object obj = cache.Get(cachekeyname);
I can move the connection line to global.asax
protected void Application_Start()
{
IDatabase cache = CacheConnectionHelper.Connection.GetDatabase();
}
If I move that line, then how can I get that instance on the other methods where I need to use it?
this is the cache connection helper
public class CacheConnectionHelper
{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(SettingsHelper.AzureRedisCache);
});
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
}
You can make it static inside the global.asax file
public class Global : HttpApplication {
public static IDatabase Cache = CacheConnectionHelper.Connection.GetDatabase();
void Application_Start(object sender, EventArgs e) {
}
.....
}
Now you can access the database object in any class by simply accessing Global.Cache which is your single instance of the database.
I have read that an effective way to use enable session in web api 2 is like so:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
I have also created a class that inherits from AuthorizationFilterAttribute and overrides the OnAuthorization method.
But this event is never called - what am I doing wrong?
You could try creating a HttpModule:
public class WebApiSessionModule : IHttpModule
{
protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (this.IsWebApiRequest(context))
{
context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
}
}
You'll need to add this to your web.config in
<system.web>
<httpModules>
I have an ASP.NET application and dll which extends IHttpModule. I have used the below method to save the session variables in httpcontext through
public class Handler : IHttpModule,IRequiresSessionState
{
public void Init(HttpApplication httpApp)
{
httpApp.PreRequestHandlerExecute += new EventHandler(PreRequestHandlerExecute);
}
public void PreRequestHandlerExecute(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
context.Session["myvariable"] = "Gowtham";
}
}
and in my asp.net Default.aspx page I have used code to retrive value as
public partial class _Default : System.Web.UI.Page, IRequiresSessionState
{
protected void Page_Load(object sender, EventArgs e)
{
String token = Context.Session["myvariable"].ToString();
}
}
I am getting error response as
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
In order to ensure whether the variables store in session I have crossed check by following method in class handler after storing the value in session as
string ss = context.Session["myvariable"].ToString();
it well executed and retrieved the value from session.
Why do you need to use Context and not Session directly? From the code I can only assume that you are going to set a value in the Session, and then read the value on page load. Rather than you do something like that, you can do this:
Add a Global Application Class, Right click on your project, Add > New Item, choose Global Application Class, and on that file, insert the following code to initialize the value
protected void Session_Start(object sender, EventArgs e)
{
Session["myvariable"] = "Gowtham";
}
On the Page_Load, you can access by:
if ( Session["myvariable"] != null ) {
String token = Context.Session["myvariable"].ToString();
}
Hope this help..
use System.Web.HttpContext.Current.Session["myvariable"] in both parts