Why Session objects are not removed after Timeout period?
I am using Asp.Net 4.0 and Session state is configured as shown below.
<sessionState mode="SQLServer" cookieless="false" timeout="5"
allowCustomSqlDatabase="true"
sqlConnectionString="data source=.\SqlExpress;initial catalog=App_SessionState;user id=sa;password=xxxxxxxx"/>
If I have not activity in browser for about 10 mins, shouldn't the Session object be removed. But after 10 mins I can still access the Session variable. Am I missing something here?
EDIT:
If I access a session variable after 10 mins as shown below shouldn't I get NULL
var myObj = Session["MyKey"] as MyClass;
mObj is not NULL after 10 mins.
There's a stored procedure installed called DeleteExpiredSessions, called from the job ASPState_Job_DeleteExpiredSessions, and is executed every minute (if I read the InstallSqlState.sql file correctly).
The procedure basically calls DELETE FROM ASPStateTempSessions WHERE Expires < GETUTCDATE()
So, if objects aren't removed, check the Expires column, and verify that you're comparing with the utc date. If in doubt, do a SELECT * FROM ASPStateTempSessions WHERE Expires < GETUTCDATE(). Also, make sure that your ASPState_Job_DeleteExpiresSessions is enabled and working.
A quick (and totally unconfirmed idea); do SQL Server Express come with the SQL Agent? Is it enabled and able execute scheduled jobs?
The "session" is never "null", but after the timeout has expired, the session object is emptied (or re-instantiated), another session is automatically started (you can check this by handling SessionEnd and SessionStart events), and you will always have a reference to a session object.
Does not happen? Still you see previous session's data?
To add onto what Simon said, If there is no SQL Server Agent running there will be no clearing of session values unless a stored procedure inside of the database is actually executed.
I don't think SQL Server express has the Agent so an automated job is not possible.
If you have control of the server then I would suggest setting up a scheduled task through windows that executes the stored procedure or job that clears your expired sessions. I don't know the exact name of the stored procedure right now but it should be named fairly obvious to it's purpose.
So your options are to upgrade to a version of SQL server that has the SQL Server Agent available or set something up to manually execute the stored procedure to clear expired sessions.
Alliteratively you can use InProc sessions, which are cleared automatically. But I assumed since InProc is the default there is a reason why you switched to SQL Server.
Related
I am researching and trying some things out with regards to the automatic saving of session variables into SQL Server. I have found this link discussing SQL Server session state (call it 'Option 1') and this link discussing Persistent SQL Server session state (call it 'Option 2').
The main difference seems to be that with Option 1, if the machine running SQL Server is turned off, the session data is lost, contrary to Option 2 which persists it. In Option 1 it seems that the process makes use of the tempdb, whereas, Option 2 seems to persist the session data through the use of the ASPState database.
I have a few questions that I can't seem to find any answers to:
In the first option, the article discusses the configuration required in the web config with regards to the < sessionState > tag. This is not added to the persistent case (Option 2). Should the < sessionState > be the same in both cases?
I have tried the second option as that seems to be more in-line to my case scenario. I started by downloading PersistSQLState.exe which simply self-extracts the InstallPersistSqlState.sql and UninstallPersistSqlState.sql scripts. I ran the InstallPersistSQLState.sql which completed successfully and created the 'ASPState' database in the SQL Server. I set the < sessionState > tag using the format stated in Option 2 as discussed in point 1) above.
Upon running the app I got the below error:
"Unable to use SQL Server because either ASP.NET version 2.0 Session State is not installed on the SQL server, or ASP.NET does not have permission to run the dbo.TempGetVersion stored procedure. If the ASP.NET Session State schema has not been installed, please install ASP.NET Session State SQL Server version 2.0 or above. If the schema has been installed, please grant execute permission on the dbo.TempGetVersion stored procedure to either the ASP.NET application pool identity, or the Sql Server user specified in the sqlConnectionString attribute."
This outlines 2 things: the Asp.Net Version 2.0 Session state potentially being not installed yet, and the process being unable to run the dbo.TempGetVersion stored procedure (for various reasons).
The stored procedure dbo.TempGetVersion does not exist in the ASPState database created by the InstallPersistSqlState.sql script. Is this stored procedure actually related to the tempdb (non-persistent) and therefore why the schema of the ASPState does not include it?
Is this the Asp.Net Version 2.0 Session state that needs to be installed? If so what is the process to be followed?! Should it be installed in the ASPState database after running the InstallPersistSQLState.sql script? If not, what is to be done exactly? There is nothing related to this ".exe" in either Option 1 or Option 2!
Finally, I have also tried uninstalling the persistent case instead run the scripts related to the Option 1 (non-persistent). In this case, the scripts provided in the first link above do not seem to work; returning 2 errors with jobs not being found ?!. Anyone has any idea why this would happen and do the correct scripts exist in some kind of online location?!
Any help would be appreciated as documentation seems poor on this subject.
The Option 1 and Option 2 articles as listed in my question are misleading, which is why I ended up wasting a whole day trying to make it work with the wrong info: I just did not have the right article at hand!
The below is what I ended up doing to implement persistent session state. Hope it can prove helpful to anyone wanting to implement the same thing.
On the machine open CMD in Administrator mode.
Change directory to .Net framework folder:
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
Run this command:
aspnet_regsql.exe -S "SQLServerInstanceName" -U "Username" -P "Password" -ssadd -sstype p
Small explanation of command in Point 2 above.
Aspnet_regsql.exe - is the .exe that installs Asp.Net Session state on the machine.
-S defines SQL Server instance name
-U defines Username -
-P defines Password
ssadd defines creating a new database for session state
sstype defines the type of session state. p is persistent.
Finally, in the web.config of the Asp.Net application where persistent session state is to be implemented, change the tag to look like the below:
< sessionState mode="SQLServer" sqlConnectionString="data source=127.0.0.1\sqltest;User ID=*****;Password=******" cookieless="false" timeout="20" / >
For full info visit this article and refer to the SQL Server mode.
I have a web server and its session state is stored in a Sql Server. I need to change the timeout to use an external time source. How would I do this?
Ok, it's not hard to do it. I suppose you're able to read that data from the table - related, as you said, to some User Preference - and to put this data in an int:
int myTimeout = [... read from DB];
It's enough to add this line after the login procedure has been completed (or even during the procedure):
Session.Timeout = myTimeout;
Note: the Timeout is in minutes.
I have the line:
<sessionState mode="SQLServer" sqlConnectionString="Data Source=localhost;User Id=sa;Password=test;" timeout="1" />
Which stores the session in a sql state server. However it does not timeout properly after one minute.
When I change the line to use InProc mode:
<sessionState mode="InProc" sqlConnectionString="Data Source=localhost;User Id=sa;Password=test;" timeout="1" />
It does timeout after one minute.
Any ideas why this is happening? How can I get it to timeout when using SqlServer?
If you're using SQL Server Express, it's because there is no SQL Server Agent to execute the DeleteExpiredSessions procedure.
Here is a possible workaround to the problem:
In the stored procedure that updates the session, I have added SQL
from the DeleteExpiredSessions procedure to the update session stored
procedure (I can't remember the name) so it checks for old sessions,
deletes the old session, and then updates the current sessions. The
stored procedure that updates the session runs on every click anyway,
so I added two more lines that remove old sessions before the session
is updated. This seems to work fine.
Make sure the SQL Server Agent service is running
Right-click on the SQL Server Agent job named ASPState_Job_DeleteExpiredSessions and click "View History" - Make sure this job is running successfully every 1 minute.
In my case, somehow (probably during one of multiple installs involving named instances) my SQL Server Agent had its property Connection -> Alias Localhost Server set to just the server name and not the servername\instancename.
When this change happened, the ASPState_Job_DeleteExpiredSessions appeared to run indefinitely and could not be stopped. So, I attempted to re-start the SQL Server Agent service, but it would not start back up. However, once I changed the Connection -> Alias Localhost Server property to servername\instancename, SQL Server Agent started right back up and the ASPState_Job_DeleteExpiredSessions job started running successfully once a minute like it should.....and this obviously solved my timeout problem.
You may be able to control the timeout of the session by setting the timeout of the forms authentication cookie:
FormsAuthenticationTicket authTicket =
new FormsAuthenticationTicket(1, // version
txtUserName.Text,
DateTime.Now,
DateTime.Now.AddMinutes(1),
false,#"\");
That way the user looses contact with the session after 1 min.
We're trying to get session state working using the following web.config line:
<sessionState
mode="SQLServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="Data Source=dbServer;User ID=stateUser;Password='thepassword'"
cookieless="false"
timeout="20"/>
On dbServer, we've run the following command to set up the ASPState db:
aspnet_regsql.exe -S localhost-E -ssadd -sstype p
On the webServer, we've started the ASP.Net state service, however, no records show up in tables ASPStateTempApplications or ASPStateTempSessions, and it seems very much like session is still being stored in process.
What's wrong? Should the state service be running on the DB server? Does it get installed with IIS, because it's not available on that machine, despite .net 3.5.1 being installed.
The IIS logs show no hint of failure. What's wrong?
If there's really quotes around the password, try to remove them:
sqlConnectionString="Data Source=dbServer;User ID=stateUser;Password=thepassword"
And remove the following line, it has no function for SQL session storage:
stateConnectionString="tcpip=127.0.0.1:42424"
And you might as well stop the state service; it's needed for out-of-process session state, not for SQL Server session state.
Also, SQL Server session state requires you to run InstallSqlState.sql on the database, not aspnet_regsql.exe. It should create a new ASPState database.
First, you don't need to start the State Service in order to use SQL Server session state. Forget about the ASP.NET State Service.
Are you sure that your site is creating a session variable? Just because you put these changes in your web.config, if you never use session variables, it won't be used.
How about writing a small HttpModule? You could drop it into place for the period of time when you need to transition users to the new codebase. The module could do some work on each page request to check the user's session and decide whether it needs to be abandoned. Perhaps you store an application version string in the user's session when the session is first created and compare the current app version string against that.
I use SQLServer SessionState mode to store session in my ASP.NET application. It stores certain objects that are serialized/deserialized every time they are used.
If I make any changes in code of the structure of those objects and I put a new version live, any logged user will get an error, as their session objects (the old version ones) do not match the structure that the new version expects while deserializing.
Is there a way to clear all sessions at once in DB so that all active sessions expire and users are forced to log in again (and therefore all session objects are created from scratch)?
Or... Is there any other way to solve this situation?
You may try using stored procedure in SQL Server to clear all the sessions:
CREATE PROCEDURE [dbo].[DeleteSessions]
AS
DELETE [ASPState].dbo.ASPStateTempSessions
RETURN 0
You can call Session.Abandon, or Clear for every user when they hit the invalid Session object.
You can also loop through the per-user Session collection, and clear the keys that can contain "old" objects. Maybe you have a login ticket and such that you don't want to clear.
foreach (string key in Session.Keys)
{
if (!key.Equals("login"))
{
Session.Remove(key);
}
}