I am writing a program recording service calls and treatment done. We have a number of users who open and close calls and I want to show at all times the total number of calls opened today and the total number closed today and the difference between them. I thought of doing it with an application variable. I have to reset these variables to 0 every day. Where would I do that? I thought in the Global.asax but in which event could that be done? The application is running all the time so I suppose Application_Start wouldn't be appropriate. So where? Thank you.
You could configure the Periodic Restart Settings for Application Pool Recycling in IIS:
The element contains configuration settings that allow you to control when an application pool is recycled. You can specify that Internet Information Services (IIS) 7 recycle the application pool after a time interval (in minutes) or at a specific time each day. You can also configure IIS to base the recycle on the amount of virtual memory or physical memory that the worker process in the application pool is using or configure IIS to recycle the application pool after the worker process has processed a specific number of requests.
But this has a side-effect of putting the application offline during the time the pool is restarting, so if you have any user connected at that time it will lose its session. This can be minimized by restarting the application at a time you have no users connected, like at dawn.
The following config snippet set the application pool to daily recycle at 3:00 A.M.:
<add name="Example">
<recycling logEventOnRecycle="Schedule">
<periodicRestart>
<schedule>
<clear />
<add value="03:00:00" />
</schedule>
</periodicRestart>
</recycling>
<processModel identityType="NetworkService" shutdownTimeLimit="00:00:30" startupTimeLimit="00:00:30" />
</add>
I'd have a date variable with the last time the counter was reset, and check the date is "today" on every access to the counter.
Unless you have critical performance problems, I guess that'd be the way to go.
Sample easy-lazy code to call whenever you are updating the counter:
lock(myCounter)
{
if(DateTime.Now.Date != lastDateCounterWasReset)
{
lastDateCounterWasReset = DateTime.Now.Date;
myCounter = 0;
}
myCounter++;
}
Now we'd need to know more about how you'd like to be storing those variables (myCounter and lastDateCounterWasReset), but could be basically anywhere (database, filesystem, etc.)
I would store the calls to a database and do a select which groups by the current day to get the total calls, etc. for display.
That way it will automatically reset for you when a new day starts, and you don't need to worry about IIS Resets destroying your in memory data.
If you don't want the performance hit of querying too often, there are a number of caching options available.
I suppose you could use the Application_BeginRequest method. Use a boolean to see if it's already run that day.
Another option is a scheduler with a hidden URL to reset.
Related
In my webapplication, I have set a timeout for the session so that if the user stays inactive for more an hour, they will be logged out.
this is set in the startup.auth.cs file and works perfectly running locally thanks to the Nuget packages of Windows.Owin...
Though, after publishing the project and putting it on the webserver, the timeout is suddenly set to 20 minutes instead of the 1 hour I had initially set and thus this forces users out of my application after 20 minutes because it takes some default setting.
when searching through my published files, I can no longer find the startup.auth.cs
nor can I find anything connected to it or even something that looks like it.
how do I change this? how do I include my startup.auth.cs into the publish or do something so that the session stays open for the complete hour that I requested instead of the default 20 minutes.
the file "startup.auth.cs" is included in the project so it's not like it should be ignoring it when running the publish.
unfortunately I can not show you any code today; it is confidential.
fortunately I should not have to show code for this question.
Change the session state configuration in Web.config (Default: 20 minutes)
<sessionState timeout="120">
And is IIS you can change idle timeout value
IIS Manager > Application Pools > DefaultAppPool > Properties > Performance
Go to this form and you can change the session timeout as per your requirement
I have a .NET MVC web app which requires time to be properly shutdown and so whenever the IIS app domain is recycled (i.e. a new instance is spun up and receives all new requests while the old instance shuts down waiting for outstanding requests to complete) I need to block this app shutdown until my app's current async background work (containing no outstanding requests) has completed. IRegisteredObject (see http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html) offers this blocking ability, though, my processes always seem to die at times inconsistent with my blockage time and IIS settings.
I saw this post (IRegisteredObject not working as expected) which explained the importance of the IIS Shutdown Time Limit but, while IRegisteredObject seems to block for a period of time, I cannot get the recycle to block for the desired time of 2 hours (nor can I generally get results which make sense based off various settings).
Below is a simple implementation of IRegisteredObject with a background thread that I've been using for tests:
public class MyRegisteredObject : IRegisteredObject
{
public void Register()
{
HostingEnvironment.RegisterObject(this);
Logger.Log("Object has been registered");
}
// the IRegisteredObject.Stop(...) function gets called on app domain recycle.
// first, it calls with immediate:false, indicating to shutdown work, then it
// calls 30s later with immediate:true, and this call 'should' block recycling
public void Stop(bool immediate)
{
Logger.Log("App domain stop has been called: "
+ (immediate ? "Immediate" : "Not Immediate")
+ " Reason: " + HostingEnvironment.ShutdownReason);
if (immediate)
{
// block for a super long time
Thread.Sleep(TimeSpan.FromDays(1));
Logger.Log("App domain immediate stop finished");
}
}
// async background task to track if our process is still alive
public async Task RunInBackgroundAsync()
{
Logger.Log("Background task started");
var timeIncrement = TimeSpan.FromSeconds(5);
var time = TimeSpan.Zero;
while (time < TimeSpan.FromDays(1))
{
await Task.Delay(timeIncrement).ConfigureAwait(false);
time += timeIncrement;
Logger.Log("Background task running... ("
+ time.ToString(#"hh\:mm\:ss") + ")");
}
Logger.Log("Background task finished");
}
}
public static class Logger
{
private static readonly string OutputFilename = #"C:\TestLogs\OutputLog-" + Guid.NewGuid() + ".log";
public static void Log(string line)
{
lock (typeof(Logger))
{
using (var writer = new StreamWriter(OutputFilename, append: true))
{
writer.WriteLine(DateTime.Now + " - " + line);
writer.Close();
}
}
}
}
In app start, I start the IRegisteredObject component:
var recycleBlocker = new MyRegisteredObject();
recycleBlocker.Register();
var backgroundTask = recycleBlocker.RunInBackgroundAsync();
Finally, when testing, I have sparked app domain recycles through 3 separate means:
(1) Web.config file change (yields a HostingEnvironment.ShutdownReason value of ConfigurationChange)
(2) Manual recycle through clicking the app's Application Pool and then Recycle in IIS Manager (yields a HostingEnvironment.ShutdownReason value of HostingEnvironment)
(3) Allowing the app to automatically recycle based off of the IIS setting under Process Model - "Idle Time-out (minutes)" (also yields a HostingEnvironment.ShutdownReason value of HostingEnvironment)
I would not have expected this, but the manner in which the recycle is triggered seems to play a drastic role... below are my findings through tests where I modified the means of recycle and IIS settings (Shutdown limit and Idle time-out).
Findings:
---- Web.config change recycle (ShutdownReason: ConfigurationChange) ----
After the IRegisteredObject(immediate: true) call occurs, I see in my logs that the background task lasts almost exactly the time set for IIS Idle Time-out, while Shutdown Time Limit plays no role whatsoever. Further, with this recycle, assuming I set the Idle time-out high enough, the recycle blocking is always respected. I blocked for a full day in one test by setting the Idle time-out to 0 (i.e. off).
---- IIS Manager manual recycle (ShutdownReason: HostingEnvironment) ----
After the IRegisteredObject(immediate: true) call occurs, the logs show the exact opposite behavior compared to Web.config change. No matter what the Idle Time-out is, the blockage seems unaffected. Conversely, the Shutdown Time Limit dictates how long to block the recycle (up to a point). From 1 second up through 5 minutes, the recycle will be blocked based on this Shutdown Limit. However, if the setting is set higher or turned off, blockage seems to remain at the ceiling of around 5 minutes.
---- Idle time-out automatic recycle (ShutdownReason: HostingEnvironment) ----
Finally something predictable... the automatic recycle does actually get triggered based on the Idle Time-out setting, which then causes a situation similar to the Manual Recycle case: Shutdown Time Limit respected up to about 5 minutes but no longer than that. Presumably this is because the automatic and manual recycles each have the same HostingEnvironment.ShutdownReason: HostingEnvironment.
Ok... I apologize for the length of this! As you can see, the combination of recycle methods and IIS settings simply do not seem to yield expected results. Further, my goal of this all is to be able to block for a max of two hours, which does not seem possible from my tests outside of the web.config recycle case, no matter the settings I choose.... Can someone please shed light onto what exactly is going on under the hood here? What role does ShutdownReason play? What role do these IIS settings play?
Fundamentally, what am I missing here, and how can I use IRegisteredObject to block for longer periods of time caused from automatic recycles??
There are two different concepts in play here-
Application domain
Application pool
Application domains provide an isolation boundary for security, reliability, and versioning, and for unloading assemblies. Application pools define a set of Web applications that share one or more worker processes. Each application pool could be hosting one or more application domains.
Application pool can be recycled in the following ways
Triggering IIS Manager manual recycle
Invoking IIS reset from command prompt
Setting idle timeout or shutdown time limit on your Application pool
Application domain is recylced when you touch the Web.config, Global.asax or any dll in the bin folder of an application.
IRegisteredObject is able to intercept the process of application domain unloading, however, it does not have any control over the application pool recycle. When application pool recycle is triggered, it kills and restarts the w3wp.exe process and ends up killing all the application domains associated with the application pool.
This should explain why your IRegisteredObject was working as expected when you touched your Web.config but would not perform the expected actions when you recylced the application pool. If your idle-timeout or shut down timeout are less than the time window that your IRegisteredObject keeps the application domain alive, after a Application domain recycle is triggered, the IRegisteredObject will try to keep the application domain alive but when the idle-timeout or the shut-down timeout is reached, the application pool will recycle and application domain will be killed regardless of the IRegisteredObject.
A solution to your problem will be to turn the idle timeout and shut down time limit settings off for the application pool and rely on some alternate method to recycle your application pool. In that case, your application pool will not be recycled automatically and you can rely on your IRegisteredObject to keep the application domain alive.
I am trying to save a simple int on the server side then any user can log in and update it. I thought this would be a simple task and began trying to use the settings designer however i couldn't change the scope from "application" to "user" as application settings are read only.
I know i could save and change the variable in an XML file but i thought there must be a more simple way.
I have tried to use user profiles, however it isn't working any ideas? (I have also used Context.Profile.)
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
<properties>
<add name="FilmNumber" type="int" allowAnonymous="true" defaultValue="2"/>
</properties>
</profile>
Code:
//********Get poster Number*******
int LastPosterNumber=0;
LastPosterNumber = (int)HttpContext.Current.Profile.GetPropertyValue("FilmNumber");
string strFileName;
strFileName = FileField.PostedFile.FileName;
string c = (LastPosterNumber + 1).ToString();
string dirPath = System.Web.HttpContext.Current.Server.MapPath("~") + "/Images/FilmPosters/" + c + ".jpg";
FileField.PostedFile.SaveAs(dirPath);
//******Save new poster number*******
HttpContext.Current.Profile.SetPropertyValue("FilmNumber", int.Parse(c));
HttpContext.Current.Profile.Save();
Try to avoid Settings because they require your config file to be modifiable, also the concept of "user settings" in ASP.NET does not exist because the application always runs under the user context of W3C's worker process - the .NET Settings API is not aware of ASP.NET Membership or other concepts of "Users".
Your best option is to use a DBMS, Application state or a static field in your application (if it doesn't need to be persisted beyond the lifespan of w3wp.exe) or a file on disk, you don't have to use XML serialization, you can write it out manually (just be sure to lock the file first because ASP.NET applications are multi-threaded).
In my applications, I only store the connection string and the bare minimum of initialization settings in web.config, per-user settings I store in a database table and write a simple API layer for this (usually with application-settings and inheritance or "EffectiveSettings"). Note that this is completely different (as far as the implementation is concerned) from .NET's Settings API which I avoid completely for various reasons, including those already promulgated in this answer.
Notes on IIS w3wp.exe lifespan:
IIS will terminate or "recycle" w3wp.exe at any time for a variety of reasons, which is why your ASP.NET application must persist to long-term storage at the nearest opportunity and any in-memory state will be lost. Reasons for this include:
Inactivity. If an application pool worker process has not handled a request in at least 45 minutes (or so) IIS will shut down the process.
Recycling. IIS takes pre-emptive measures against worker processes leaking resources by terminating and restarting them every 90 minutes or so (or it might be 29 hours, I'm not sure).
Unresponsiveness. IIS gives worker processes a strict timeout to respond to incoming requests, I think the default is 60 seconds. If no response is sent to the client then the process will be restarted.
Reaching a memory limit. Similar to the automatic time-based recycling described above, IIS will restart a worker process if it reaches a memory limit (which is why it's important to manage your resources).
Reaching a request limit. Again, similar to the automatic time-based recycling, IIS will restart a worker process after its odometer reads X many requests. This is disabled by default but your ISP might have enabled it.
I create several temporary files in my asp.net app, and I need to delete them when the user is done using them.
I tried
void Session_End(object sender, EventArgs e)
{
System.IO.File.Delete(#"C:\Temp\test.doc");
}
but it's not working.
Any ideas?
you must grant permissions to iisuser at this folder
1) Set mode variable on web.config
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>
2) Start a Session variable.
3) Put some code on Session_End and then check if that code is executed when the user click [X] on the browser.
Taken from the following
http://www.tek-tips.com/viewthread.cfm?qid=742667
Hope this helps
There is no good reliable (works 100% of the time) way to determine when a user leaves a web application. While conventional means will work when all is running as expected, there are edge cases that can happen that will orphan data, e.g.
The user's computer freezes or crashes...
The server freezes or crashes...
The user's internet connection fails...
The server's internet connection fails...
You get the idea. For this reason, I personally prefer to do all processing in memory instead of writing temporary files to the web server's hdd. That way the .Net garbage collector will handle cleaning up any orphaned data.
If, however, you are processing data in sufficiently large quantities to make keeping it in memory not a viable option, set up a Windows Service or scheduled task to perform cleanup once enough time has passed to ensure that the files are stale. Continue to attempt cleanup at runtime, but the alternate method should allow you to handle any data which becomes orphaned over time.
My situation is this:
was created a page that will run a long process . ... This process consists in:
- Read a file. Csv, for each row of the file wil be created an invoice...in the end of this process shows a successful message.
for this it was decided to use an updatepanel so that the process is asynchronous and can display an UpdateProgress while waiting to finish the process ... for this in the property of scriptmanagment was added the AsyncPostBackTimeout = 7200 (2 hours) and also timeout was increased in the web.config of the app as in qa and production servers.
Tests were made in the localhost as a qa server and works very well, the problem arises when testing the functionality on the production server.
that makes:
file is loaded and starts the process ... during this period is running the UpdateProgress but is only taking between 1 or 2 min and ends the execution without displaying the last message, as if truncated the process. When reviewing the invoices created are creating only the top 10 records of the file.(from a file with 50,100 or + rows)
so I would like to help me with this, because i don't know what could be wrong.
asp.net is not suited for long running processes.
The default page timeout for IIS is 110 seconds (90 for .net 1.0). You can increase this, but it is not recommended.
If you must do it, here is the setting:
<system.web>
...
<httpRuntime executionTimeout="180"/>
...
<\system.web>
Refer httpRuntime
Pass on this work to a windows service, WCF or a stand alone exe.
Use your page to get the status of the process from that application.
Here is an example that shows how to use workflows for long running processes.
You move the bulk of the processing out of asp.net, and free its threads to handle page requests.