ASP.NET Custom SQLite DeleteExpiredSessions() - asp.net

The SQLiteSessionStateStoreProvider.DeleteExpiredSessions() is not running automatically on the IIS 7 at any interval. I understand that if my database for session state storage were on inProc, it would be managed automatically at runtime, and if it were on an actual SQL database, there would be a script that would be ran by the SQL agent on an interval to clear expired sessions. However, my issue is that despite having the function defined in the library supplied here: https://github.com/micahlmartin/SQLiteSessionStateStore (renamed to DeleteExpiredSessions() and made public) I am unsure how to have the IIS server call this function, or if I need to implement a scheduled function of my own on the back-end to call this. On the IIS server the session state is set to custom, at 20 minute intervals expiration. It is set to cookie mode, as is the same settings on the web.config for the server. The database is currently holding data from the past 7 days for session states, and I am unsure how to interact with it from the back-end, or if I am missing some service or implementation. Anyone with experience running a custom SessionStateProvider via SQLite through a C# MVC should know how to resolve this, thank you.

Try something like this from your Global.asax:
It runs DeleteExpiredSessions() after about 10 minutes. In the interim it checks every 0.25 seconds to see if the application is shutting down. If it is shutting down then it stops.
public class Global : System.Web.HttpApplication
{
public static Task SessionCleanup { get; private set; } = null;
public static bool ApplicationEnding { get; private set; }
public static void PeriodicallyRunSesssionCleanup()
{
int cleanupInterval = 600000;//10 minutes
int sleepInterval = 250;// 1/4 second
while(!ApplicationEnding && cleanupInterval > 0)
{
Thread.Sleep(sleepInterval);
cleanupInterval -= sleepInterval;
}
if(!ApplicationEnding)
{
throw new NotImplementedException("Place your code that cleans up sessions here to have it run every 10 minutes.");
SessionCleanup = new Task(PeriodicallyRunSesssionCleanup);
SessionCleanup.Start();
}
}
protected void Application_Start(object sender, EventArgs e)
{
SessionCleanup = new Task(PeriodicallyRunSesssionCleanup);
SessionCleanup.Start();
}
protected void Application_End(object sender, EventArgs e)
{
ApplicationEnding = true;
if (SessionCleanup != null) SessionCleanup.Wait();
}
}

Related

IIS turned off my application automatically?

I just noticed that IIS turned off my ASP.NET web application automatically after it idled 20 minutes. The website is hosted on Godaddy.com.
Below is the Global class which logs the Application_Start and Application_End methods. And the image I uploaded is the result that I saw.
It turned off at 2013-05-24 06:42:40 after the last call I did at 06:22:01. (20 minutes, hua...)
After one day, I did another call at 2013-05-25 03:05:27, the website was awakened.
Strange? I didn't want my website to sleep. Is there any way to keep it sane all the time?
public class Global : HttpApplication
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
log.Debug("Application_AuthenticateRequest -> " + base.Context.Request.Url);
}
protected void Application_End(object sender, EventArgs e)
{
log.Info("Application_End");
}
protected void Application_Start(object sender, EventArgs e)
{
log.Info("Application_Start");
}
}
The IIS/asp.net is turn off the application if you do not have any request for some time to save resource.
Now this usually handle on server side if you wish to avoid it, but in your case you can't interfere with the IIS setup, so one trick is to create a timer that reads every 10 minutes or so one page.
You start it when application starts, and do not forget to stop it when application is go off.
// use this timer (no other)
using System.Timers;
// declare it somewhere static
private static Timer oTimer = null;
protected void Application_Start(object sender, EventArgs e)
{
log.Info("Application_Start");
// start it when application start (only one time)
if (oTimer == null)
{
oTimer = new Timer();
oTimer.Interval = 14 * 60 * 1000; // 14 minutes
oTimer.Elapsed += new ElapsedEventHandler(MyThreadFun);
oTimer.Start();
}
}
protected void Application_End(object sender, EventArgs e)
{
log.Info("Application_End");
// stop it when application go off
if (oTimer != null)
{
oTimer.Stop();
oTimer.Dispose();
oTimer = null;
}
}
private static void MyThreadFun(object sender, ElapsedEventArgs e)
{
// just read one page
using (System.Net.WebClient client = new System.Net.WebClient())
{
client.DownloadData(new Uri("http://www.yoururl.com/default.aspx"));
}
}
One note, do not use this trick unless you needed because you create one more thread living for ever. Usually google reads the web pages and keep it "warm", the auto turn off usually occurs if you have a very new site that google and other search engines did not start to index, or if you have one two page only that never change.
So I do not recomended to do it - and is not bad to close your site and save resource, and your site is clear from any forgotten open memory and start fresh...
Similar Articles.
Keep your ASP.Net websites warm and fast 24/7
Application Initialization Module for IIS 7.5
Auto-Start ASP.NET Applications (VS 2010 and .NET 4.0 Series)

How to Prevent Session Value Reset of Global.asax file in asp.net?

I have about 10 Session variable for storing the File Download Counts of each different 10 Categories wise. I dont know why? but my session variable that is set into Global.asax get RESET automatically.
Since, the Machine is not restarted. Still the Counter of File Downloads get Reset. Any Idea? Plz Suggest me any solution.
In Global.asax:
void Application_Start(object sender, EventArgs e)
{
Application.Add("MGM",0);
Application.Add("PC",0);
Application.Add("NC",0);
Application.Add("TC",0);
Application.Add("PGC",0);
}
The *shortCode* parameter is name of Global Session from Global.asax file. that i am passing to get the counter and increment accordingly.
In Download.aspx.cs Page:
private int GetCount(string shordCode)
{
int count=0;
count = Convert.ToInt32(Application[shortCode]);
lock (Application[shortCode])
{
Application[shortCode] = ++count;
}
return count;
}
Shall i store value in textfile and update accordingly after certain count say 500. if yes how to do? Our colleague says that if suppose many users downloading file and if both access the same value from textfile then cuncurency may occurs.I am Confused...!Help Appreciated.
Please refer to the MSDN page for ASP.NET Application State
Excerpt:
Because application state is stored in server memory, it
is lost whenever the application is stopped or restarted. For example,
if the Web.config file is changed, the application is restarted and
all application state is lost unless application state values have
been written to a non-volatile storage medium such as a database.
By default, ASP.NET applications running on IIS will have their application pool shut down during periods of inactivity. I believe the default value for this is 20 minutes. Also by default, applications pools are recycled every 1740 minutes (29 hours).
When this happens you will lose anything in the Application[] collection that you haven't stored in a more permanent location, such as a database.
Both of the above-mentioned values can be modified by right-clicking on the specific application pool in inetmgr and clicking on Advanced Properties to bring up the appropriate window.
ok good!,
Please try my simple app,four you problem:
protected void Application_Start(object sender, EventArgs e)
{
Application.Add("MGM", 0);
}
protected void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["MGM"] = System.Convert.ToInt32(Application["MGM"]) + 1;
Application.UnLock();
}
protected void Session_End(object sender, EventArgs e)
{
Application.Lock();
Application["MGM"] = System.Convert.ToInt32(Application["MGM"]) - 1;
Application.UnLock();
}
protected void Application_End(object sender, EventArgs e)
{
Application.Clear();
}
and you method i changed:
private int GetCount(string shordCode)
{
return Convert.ToInt32(Application[shortCode]);
}
Ok,great i answer this Q,and try change your method:
Startup your web app:
protected void Application_Start(object sender, EventArgs e)
{
Application.Add("MGM",0);
Application.Add("PC",0);
Application.Add("NC",0);
Application.Add("TC",0);
Application.Add("PGC",0);
}
and changed your get count method logics:
private int GetCount(string shordCode)
{
//current app instance
var currentApp = HttpContext.Current.ApplicationInstance.Application;
//get item count
var count = Convert.ToInt32(currentApp[shordCode]);
//locking app for your asking count insrement
currentApp.Lock();
currentApp[shordCode] = ++count;
//unlock app
currentApp.UnLock();
return count;
}

Static class member is not shared between different users on different IP

I have written a static class and suppose to share it's members between all sessions. it works for all the browsers running on the same cumputer but the data is not shared between different users from different location. my website is written with ASP.NET
this is my class
public static class GlobalPool
{
public static List<string> OnlineUsers;
}
and I instantiate the OnlineUSers property in Global.asax as
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
GlobalPool.OnlineUsers = new List<string>(100);
}
I add username whenever a user logs into my website:
public void Login(int aMemberSerial)
{
User = new MemberDataAccess().Read(aMemberSerial);
new MemberDataAccess().Login(User);
GlobalPool.OnlineUsers.Add(User.Username);
Message = PostBusiness.NewPost(User);
}
This is not robust code. ASP.NET application routinely recycle (the App Pool) and so all your data will go away.
The best way to approach this is to store the list in a database, and when a Session expires, remove that user from the data store.

Polling an access database inside a non-dedicated windows server

We have a website that runs on ASP.NET. I would like to run a service that checks the database table every XX hours and do an action ( send mail ) if some conditions are not met.
We cannot use
Windows Service as the hosted server is not a dedicated server. (We just have the control panel)
SQL Service for sending mail as we are using Access 2003 (mdb) as our database. It resides at App_Data
IIS is also not available
Its very critical that we need some kind of polling in the server.
We are kind of stuck now. What are the alternatives we have?
its mentioned here
Easy Background Tasks in ASP.NET
here are some snippets from that link
private static CacheItemRemovedCallback OnCacheRemove = null;
protected void Application_Start(object sender, EventArgs e)
{
AddTask("DoStuff", 60);
}
private void AddTask(string name, int seconds)
{
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(name, seconds, null,
DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, OnCacheRemove);
}
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
// do stuff here if it matches our taskname, like WebRequest
// re-add our task so it recurs
AddTask(k, Convert.ToInt32(v));
}
Works well in my testing; badges are awarded every 60 seconds like clockwork for all >users - Jeff Atwood
There's a trick you can use to simulate a windows service using just your ASP.NET web service.
The gist of it goes as follows:
Place an item in your cache with an expiry period that is equal to how often you would like to poll your database.
Add a callback that is fired when the item is removed from the cache. In the callback method, add your polling code to do the thing you want to do (call access database, send mails, etc.)
so: in your global asax, something like this:
private const string DummyCacheItemKey = "pollingCacheKey";
protected void Application_Start(Object sender, EventArgs e)
{
RegisterCacheEntry();
}
private bool RegisterCacheEntry()
{
if( null != HttpContext.Current.Cache[ DummyCacheItemKey ] ) return false;
HttpContext.Current.Cache.Add( DummyCacheItemKey, "Test", null,
DateTime.MaxValue, TimeSpan.FromMinutes(1),
CacheItemPriority.Normal,
new CacheItemRemovedCallback( CacheItemRemovedCallback ) );
return true;
}
public void CacheItemRemovedCallback( string key,
object value, CacheItemRemovedReason reason)
{
Debug.WriteLine("Cache item callback: " + DateTime.Now.ToString() );
// Do the service works
DoWork();
ReregisterCacheItem();
}
Whilst it's not ideal, it fits your constraints.
Full details of the technique can be found here: http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc

using a static member in WebApp

I have this code
//file Globals.cs in App_Code folder
public class Globals
{
public static string labelText = "";
}
and a simple aspx page which has textbox, label and button. The CodeFile is:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = Globals.labelText;
}
protected void Button1_Click1(object sender, EventArgs e)
{
Globals.labelText = TextBox1.Text;
}
}
That is when I click on the button the Globals.labelText variable initializes from the textbox; the question is: why when I open this page in another browser the label has that value, which I set by the first browser, that is the static member is common for the every users. I thought that the every request provides in the individual appDomain which created by the individual copy of IIS process. WTF?
Yes you may use static variable to store application-wide data but it is not thread-safe. Use Application object with lock and unlock method instead of static variables.
Take a look at ASP.NET Application Life Cycle Overview for IIS 7.0 and ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0
No, static in this case is static in that manner only for the lifecycle of the process the request lives on. So this variable will be static the entire time you're processing a single request. In order to have a "static" variable in the manner you describe, you'd have to make it an application variable. Something like this:
//file Globals.cs in App_Code folder
public class Globals
{
// I really recommend using a more descriptive name
public static string LabelText
{
get
{
return Application("LabelText") ?? string.Empty;
}
set
{
Application("LabelText") = value;
}
}
}
By making it an application variable it should survive multiple page requests. A vulnerability it has though is that it will not survive an application pool recycle, and for large applications this can be problematic. If you truly want this variable to behave in a static manner reliably you're probably better off storing its state in a database somewhere.

Resources