MVC Session loses value - c#

On my localhost server Session["Culture"] variable always store the proper value.
But on my external server, the same session variable (Session["Culture"]) sometimes lose value and become null. Why it is happen? And how to resolve it?
Part of a global.asax.cs file:
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
CultureInfo ci = (CultureInfo)this.Session["Culture"];
if(ci == null){
//breakpoint
}
}
}
EDIT:
It is obvious that session cannot be shared between server A and server B. My problem is rather different - in a nutshell- the same application, but:
1) on server A (localhost) Session["Culture"] works properly and it always store some information.
2) on server B (external) Session["Culture"] work nice but always after random time lose value and become null

In-process session state is subject to being cleared any time, as sessions are ended when the appdomain is recycled.
You can mitigate this some by using an external session storage mechanism, such as the state service, or a database provider. You can also build your own session state provider.
However; you should still treat session state as only somewhat less volatile than cache, if you want it to be robust; always check for null, and reset the values if so.
If sessions are expiring that quickly on one server, I would look into why that might be. Something may be causing recycles improperly.
Addition: I see you are using multiple servers; in-process session state also cannot handle this. The above advice can help there, too.

Related

How to prevent Asp.Net MVC session mixing?

Our ASP.Net MVC application is hosted on Azure. recently, one of our user reported issue that he is able to see data related to other user. we tested this on our 3-4 laptops and could able to replicate. this scenario happened 2-3 times but not frequently. It is strange. we were still not able to find out root cause of this issue. we are not using output caching technique. we are using Forms Authentication and session timeout kept open for 30 minutes only. we also didn't use any static variable to store session.
On Azure, we have traffic manager profiles implemented. there 2 instances of these application exists and priority was set accordingly so as to up one instance when other gets down.
when checked code, We found below code from Global.asax but don't know exact usage of this code. it could be issue but not sure 100%. when debugged, this gets called every time when action is executed.
void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Cache["RecycleCheck"] == null)
{
HttpContext.Current.Cache.Insert("RecycleCheck", "1", null, DateTime.UtcNow.AddDays(2), System.Web.Caching.Cache.NoSlidingExpiration);
appendLogFile("Recycle Took Place");
}
if (HttpContext.Current.Session == null || Session["CurrentUser"] == null) return;
HttpContext.Current.User = (CustomPrincipal)Session["CurrentUser"];
}
How session gets mixed? is there bug in Azure IIS Server or we are missing something in our code? how to avoid session mixing?

Setting a MySql session variable for every single connection in a pool

I'm connecting to MySql using mysqlconnector.net (https://github.com/mysql-net/MySqlConnector/) and want to set some session variables for every single session: SET SESSION wait_timeout = 60 and SET SESSION information_schema_stats_expiry = 15. I would like to always set these session variables, but not have the overhead of executing an additional query when a pooled connection is used (since it's a game server and throughput matters). The user does not have permission to set global variables.
I understand session variables are valid for the lifetime of a MySqlConnection object, and if the connection is created with the ConnectionReset = false option, then session variables will persist when the connection is pooled.
The problem: I don't know whether a connection is being truly created or is coming from the pool, since the same constructor can do either. I would like to set the session variables only when the connection is new.
One solution I can see is to modify the MySql connection library to add an API that would tell me whether a connection object has been newly created or was taken from the pool.
The workaround I will be using is to set the global variables when the DB is created using Ansible--the mysql_variables module seems to do what I need (actually since I'm using AWS it'll have to be the rds_param_group module), however this question is still valid, since there are other MySql users that are not in control of the database they're using.
A request similar to yours has already been discussed at https://github.com/mysql-net/MySqlConnector/issues/519, with an answer similar to this one: attach an event handler to MySqlConnection.StateChange to set the session variables.
If your performance needs are such that you cannot incur the overhead of resetting the session (the default behaviour of ConnectionReset=true) and setting the session variables each time, then it might make sense to implement your own connection pool.
By setting Pooling=false; in the connection string, MySqlConnector's pooling will be bypassed and calling MySqlConnection.Open(Async) will immediately open a new connection. You would have to keep the connection open and not Close/Dispose it (which might impose an awkward programming pattern), or wrap it in an IDisposable wrapper that returns it to your custom pool.

MemoryCacheEntryOptions cache is not cleared after AbsoluteExpirationRelativeToNow is expired

I have sample webapp deployed to Azure. The app cached a variable using MemoryCacheEntryOptions to store a value (from database) which expire in 5 minutes.
However after 5 minutes via Chrome debugging tool, I still can query the cache, the cache value expected to be empty or whatever the new value which currently stored updated in the database.
I even tried to clear cache in the web browser, but cache seem still retain the previous value.
However when I restart the web site, and open the web app again the cache value is no longer exist.
Would any setting in Azure might affect the cache expiry?
private readonly MemoryCacheEntryOptions _cacheEntryOptions;
protected CacheService(IMemoryCache memoryCache)
{
_ memoryCache = memoryCache;
_cacheEntryOptions = new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300)
};
}
Debugging the behavior of a web application is notoriously hard, as all you got to control it is the Browser - and you never get exclusive access.
Even if you did not refresh the page, any number of things might have queried the server. The culprits start around "any search engines webcrawler" and end around "somewhat aggressive security tools" (because some viruses might use web servers). You could try a way shorter timeout. But ideally you want to have both the Server and the client you access it with run in separate virtual machines, which are only connected via the Hypervisor. That way you can be certain nobody is interfering.

Where do I store an object that that needs to be initialized once for a user then needs to be available on all pages?

I have an object that contains a connection to an external service. The connection needs to be initialized once when a user logins, otherwise the service will throw an error when the connection is re-initialized.
The connection then needs to be open all the time and should available to multiple controllers that will call the service.
I am using ASP MVC & C#. I am currently initializing the variable when a user session starts and stores it in the user session as well. I am wondering if there are other alternatives to this approach.
Initializing the session variable
protected void Session_Start(object sender, EventArgs e)
{
HttpContext.Current.Session.Add("SomeConnection", new SomeConnection());
}
Then I use an extension method that retrieves the connection from the session
public static SomeConnection GetSomeConnection(this HttpSessionStateBase session)
{
return (SomeConnection) HttpContext.Current.Session["SomeConnection"];
}
Another approach is:
If you are deploying on load balanced servers, to make this approach work you have to ensure session stickiness.
Otherwise you can use AppFabric to store your object in an independent server and make it available to all your servers. This way you will also be initializing your object only once.
Use GetExistingOrSet method.

Losing session values

I have a process that involves a few .aspx pages. Fill out some info in one, hang on to it, move to another page that has an iframe on it, upload some documents in the iframe via a web service to a server, hang on to the list of documents and the status of the upload and then, on a third page, do something else that involves saving all the data to a database.
Before moving from page 1 to page 2, I put some data in Session variables. On page 2, the data is retrieved and displayed, some more data is put into Session variables during the process of uploading the files from within the page in the iframe on page 2 then, on page 3 the data is retrieved from Session and written to the database.
On a test server this all works perfectly. On a live server, I keep getting (random) 'object not set to a reference' errors - which seem to be reporting that the session variables have disappeared.
My understanding is that, within .aspx pages ...
HttpContext.Current.Session["myvariable"]
Session["myvariable"]
are, effectively, the same thing. I am setting my session variable just using ...
Session["Variable1"] = "fred";
Any ideas why (randomly, sometimes the process works fine on the live server) I seem to be losing my Session variables?
This is a web site as opposed to a web application. Developed in VS2010 using Framework 4.0
There can be various reasons why you are loosing the session.
Some of them are:
Your sessionState timeout has expired
You update your web.config or other file type that causes your Application Domain to recycle like files in folder App_Data
Your Application Pool gets recycled
You update your site with a lot of files just by doing copy and paste physically, and ASP.NET will automatically recycles the session.
If you are not sure of the reason you can do event logging why application pool is getting recycled. May be you will come to know about the reason and depending upon that you can take preventive measures.
For Logging you can write following code block on Application_End
public void Application_End()
{
HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null, CultureInfo.InvariantCulture);
if (runtime == null)
return;
string shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null, CultureInfo.InvariantCulture);
string shutDownStack = (string)runtime.GetType().InvokeMember("_shutDownStack", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null, CultureInfo.InvariantCulture);
//Do Logging as per your need and implementation
//Logging.Write(TraceEventType.Error, shutDownMessage, shutDownStack);
}
The is a good posiblity you save non serializable objects in you session variables and keep your session out of proc on your production server (load balancing?). Check if you objects are seriablizable and if not make them serializable.
What happens is your live server is recycling its application pools, which basically resets the memory used for applications. Normally a timeout can be set, but if the application pool recycles, this will reset your session.
The solution is to use SQL server for your session state.
Try this: http://support.microsoft.com/kb/317604
Supplemental Link: http://www.codeproject.com/Articles/104082/Configuring-ASP-session-state-on-SQL-server
If you are hosting with a larger public host, they have probably already prepped their SQL to handle session states, and you should be able to just make the change in your web.config file to use SQL session state.
Ciao
There is one more condition where sessions can lose its value.
You can use Fiddler tool to trace out this problem.
The most condition can be found when you some element like source not found in solution. At that moment server will try to reload that unfounded or lost object by restarting the project. Restarting the project will result in resetting all session objects.
Thanks.

Categories