I build web-site and want to count clicks on some button. I create and try this class of counter:
public static class Counter
{
public static int counter = 0;
}
Every time I click on the button the counter is increament (counter++) ans I see it in my site, But, if I close the chrome and enter again to my site the counter starts from zero.
How can I save the counter? "Static" dont need to do that?
My bet is that it happens because the application space is flushed - it shouldn't reset just because you closed your browser window, thus abandoning the current session (if the session cookie isn't persistent, that is.)
Visual Studio may republish your files (if using a remote IIS) or just plainly restart a local IIS Express instance, depending on how you set your development environment; I do believe setting a specific content as Static would cause it to be available to all current sessions.
That said, you may want to keep it under the current session (using the Session object).
Optionally, if you want to persist information in between server restarts, you may try reading and writing to a local storage, such as a plaintext or XML file. You can find a very nice article about this on the following link:
http://www.codeproject.com/Articles/544839/Implement-ASP-NET-custom-XML-file-configuration
A more sophisticated version would use a local (or remote) database, for example.
Hope it works for you.
static fields are unique per-process. Depending on your application pool configuration, you could have 2, 20 or 100 copies of that.
They're also not thread safe. There are very, very few instances (pun) where a static member is appropriate.
Just off the top of my head, a particular "instance" of a static will disappear when:
The application pool is recycled. On IIS, this defaults to 20 minutes of inactivity.
The application process exits (you may have multiple processes running within your app pool). This happens as part of (1), but will also happen if, say, you're using the Visual Studio debug web server (Cassini), have your project configured to launch the site for debugging, and close the browser that was launched initially. (This happens because VS considers closing the browser that it launched equivalent to saying "I'm done playing. Back to coding now," or hitting the stop button.)
Another thread overwrites the value you've stored (google "race condition.")
You really, really should be storing this in a database. If you're building a website, you need a database anyway. ANYTHING related to application state should be stored in the database.
ALSO, this really, really shouldn't be happening server-side. Are you really performing a postback every time someone clicks anywhere on a page? If so, you have JavaScript in place to handle that, so just skip this insanity, have said script fire off an AJAX request, and have the target handler log it in the database.
Looks like your using a web site so presuming ASP.net. There are a number of ways to store the information. Database could be one or a persistent cookie could be the way to do it. See this article on how to create cookies: How do I set/unset cookie with jQuery?
You can try save it in session and then it will stay until the session is time out(20 minutes) if you want it to long time just write it to file in known location and when you close the web write the value to the file and when the web is up again take the vakue from the file.
Related
I have written some code in the application_start() method in my global.asax file. It does not get called when I deploy my application on IIS server. The code is accessible when I run it in the .NET framework.
I've tried to restart the application many times, but it's still not working.
I've also tried the suggestion from the following link.
Application_Start not firing?
There are few things you need to know before you are trying to debug Appplication_Start. There are -
One : When the code executes and why it is almost impossible to debug by attaching to it.
The application start method is executed when the application pool starts and your website is being started up for the first time. If you deploy new deliverables to IIS, then IIS might restart it itself, but there is no guarantee that it will. So, deploying new codes does not guarantee that it will restart the pool and he execution of application start. You should restart your application pool to guarantee execution of application start.
While debugging IIS applications, Visual Studio attaches itself to a process something named w3wp.exe or similart (I forgot the actual executable name), which is the worker process and only available after, remember after, your application pool is up and your site is up. So, in other words, if you are seeing this in service list, then the application start has already been executed and attaching to it will not give you a chance to debug it. It is kind of a tug of war with time.
So, in other words, it is kind of impossible to debug application start unless you are very very quick.
Two, the solution 1 - With Dev Server
Launch your application in visual studio with Asp.net development server or IIS express, then you will be able to debug. But if you really want to debug on IIS, then check the next section
Two, the solution 2 - With IIS
There is a library in the name System.Diagnostics, Debuggerand it has a nice way to call debugger in code. You can read it here - http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break(v=vs.110).aspx
Modify you application start with this -
public void Application_Start(){
....... //other codes
Debugger.Break() or Debugger.Launch()
}
When this line executes, IIS will halt execution, and will show you a debugger selector window (similar to the one attached), keep your solution open in vs and select that vs from the list, will be able to debug as usual... :)
In case you are using windows 8 and the debugger does not launch, read this article to enable it -
http://blogs.msdn.com/b/mapo/archive/2013/11/07/debugger-launch-not-displaying-jit-debugger-selection-popup-on-windows-8-8-1.aspx
Three: A very important thing
I noticed that you said, you are adding db entries in Application_Start. You should keep in mind that, Application_Start does not have a HttpContext, ViewContext, So your db access code may fail for so many others reasons.
Make sure that the Global.asax file is actually deployed to the destination folder in the root. If the file is not present then the code behind you have written for Application_Start will never be called.
Also make sure the signature is correct
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {/*do something here like logging so you know it was called*/}
}
If you are running Server 2008R2 (or earlier) and/or IIS 7.5, you might want to look into the Application Initialization module. This can be downloaded here:
www.iis.net/downloads/microsoft/application-initialization
With IIS versions prior to 8.0, the application start is not called until the first web request arrives. I'm reading your question as you want your application start to be fired before the first web request, yes?
Here is a fantastic guide to configuring this module (if it applies to you):
https://blogs.msdn.microsoft.com/benjaminperkins/2014/01/07/configure-the-iis-application-initialization-module/
The key takeaways is that you need to set your app pool to 'AlwaysRunning' instead of 'OnDemand'. You also need to set a preloadEnabled flag for your website. Once both of these are done, fire off an iisreset and you should see the results of your application start (look in the database since it's writing there).
Other answers are relevant as well, in that this is tough to debug and you're missing all the niceties you're used to such as a httpcontext in app start.
If you are running IIS 8.0 - you should still read the above link to configure preloading.
This did work for me:
Menu -> Build -> Clean Solution
Menu -> Build -> Rebuild Solution
Then, Application_Start() was fired only for the first time.
In my case in production environment App_global.asax.compiled was missing and all content of global.asax not fired.
I have developed an Asp.Net MVC Web Application and deployed it on IIS 8 Server and in my application I am using a list to store online users and display them in a page using the following code
if (HttpRuntime.Cache["LoggedInUsers"] != null)
{
List<string> loggedInUsers = (List<string>)HttpRuntime.Cache["LoggedInUsers"];
if (loggedInUsers.Contains(model.UserName))
{
}
else
{
loggedInUsers.Add(model.UserName);
HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
}
}
For some reason, the list gets cleared every night and when I look for the active users, I see it empty.
Is it something that has to be dealt on IIS 8 or is there any better way to implement the Online users using a database table may be..
IIS can recycle your application pool (for several reasons, including idling and no requests, too much memory use, etc...) At that point your application will be unloaded, and then loaded again later. Hence your cache values are gone.
Second, do you have any code that at some point prunes and removes old entries from cache? If not, it means you got a memory leak as it'll continue to grow indefinitely (and thereby trigger application pool recycle).
If you do have prunning code (so the cache is actively managed to avoid indefinite growth), and you need its contents to survive past pool restarts, then you have few options:
Use database. Simply have a table of active users and add/delete there.
Pro: survives even unexpected crashes of app, iis, and even machine itself.
Con: Slow due to db access and db contention point possibilities.
Put code in your application start / end event handlers to serialize contents to a file on end, and deserialize on start.
Pro: faster than db. works during graceful shutdowns.
Con: will not work due to unexpected crash.
Your site probably shuts down after a certain amount of time when there is no activity. Look at IIS settings for Application Pools (more specifically "Set idle-timeout to never in IIS") on google...
I know (and it works) that in C#, this property tells me if the current session is a RDP one:
System.Windows.Forms.SystemInformation.TerminalServerSession
Now, I have a service that receives logon/logoff and lock/unlock events, and I need a way to tell this service if the session being started is rdp or local.
Problem: the service runs as SYSTEM user, and the property above always returns false (I think because SYSTEM is always considered a local connected user)
I've tried to search in the register for the Volatile Environment subkey to check if there is the subkey that identify the RDP Session Name: this works in lock/unlock handler, but in the logon handler the subkey doesn't exists yet (subkey is created after login completes).
Any idea about how to work around this problem?
While a wait for the key creation for a limited amount of time works, I would like a less "kludgy" way to do it.
You can detect whether a session is a local or remote session by calling WTSQuerySessionInformation with the WTSInfoClass parameter set to WTSClientProtocolType. If you'd prefer to avoid the P/Invokes, you can use the Cassia library: new TerminalServicesManager().GetLocalServer().GetSession(sessionId).ClientProtocolType.
Caveats: This won't help you when processing session logoff messages because you will not (reliably) be able to fetch information about the session, since it's in the process of being destroyed (but that seems relatively easy to work around). Also, the ClientProtocolType Cassia property mentioned above has not yet been released, but you can grab a trunk build from the build server by logging in as a guest and using the artifacts link.
I am hosting an Asp.Net website in IIS 6.0
We have to reset the session timeout in web.config
My client want me to reset it only if no session is running (no one is using the site).
We have not used Membership and SessionState is set to InProc
How I get to know if anybody using the site or any session is running.
I can't make change in source code or any other file except web.config in the hosted website.
I'm not great at PowerShell, so hopefully you can look up the proper syntax. But ...
One option is to run a Powershell script and check the count of the session like this:
UPDATE: Changed 'Sessions Total' to 'Sessions Active'
write-host Getting performance counters ...
$perfCounterString = "\asp.net applications(__total__)\sessions active"
$counter = get-counter -counter $perfCounterString
$rawValue = $counter.CounterSamples[0].CookedValue
write-host Session Count is $rawValue
if( $rawValue -gt 0)
{
write-host Session are active - will not stop IIS
exit
}
write-host Stopping IIS
stop-service "IISAdmin"
# Set values
$webConfig = "d:\web.config"
$newTimeout = "20"
# Open file and change value
$doc = new-object System.Xml.XmlDocument
$doc.Load($webConfig)
$doc.SelectSingleNode("//sessionState").timeout = $newTimeout
$doc.Save($webConfig)
write-host Starting IIS
start-service "IISAdmin"
write-host Done!
Save this on the desktop as "ChangeIIS.ps1".
Now Powershell doesn't like you just running scripts like .bat files. You have to grant access to the process or your user for security reasons. So do the following:
Open a command prompt and Run As Administrator
Type powershell
Type Set-ExecutionPolicy -scope process Bypass
Type sl <path to directory of .sp1 file> . sl [set-location] is like cd in command prompt
Type $ '.\ChangeIIS.ps1'
It will run now and reset the value.
Here is a link to my blog on how I created the PowerShell script
in a more Step-by-step fashion
Check the IIS log files for your site and see when the last hit was made (by actual users, rather than search bots).
If the last hit was older than the current session timeout, then no active sessions exist. That is what you are actually looking for, rather than a count.
No programming or hacks required.
Hey Session timeout its not execuate if some one is using site..
so no need to worry
(The Timeout property specifies the time-out period assigned to the Session object for the application, in minutes. If the user does not refresh or request a page within the time-out period, the session ends.
)
Session WIth IIS
http://msdn.microsoft.com/en-us/library/ms525473(v=vs.90).aspx
Session with Config File
http://msdn.microsoft.com/en-us/library/ms178586.aspx
I think the simple answer here is "not possible".. You live you learn, see answer on ASP.NET Performance counters. I'm very interested on how that goes (if it works for you), and if it gives you application specific data (vs. aggregate of all applications on the box?).
Even the suggestion to look at log files will not get you what you want - as you're looking at the log file, how would you know there isn't a user starting a session?
Sessions are cookies to a browser. So if visit 1 page in your web site, I leave your website and go to some other web site, and then come back (before whatever timeout value you set)? How would you define that? At the point I left your web site, you will not see "any" activity (whatever monitor you use), but that doesn't mean my session is "expired".
It doesn't even have to be that complicated - I visit your web site, and start reading your content (not navigating, not doing anything that can be measure/monitored).
I guess there's more clarity needed on the "goal" - as in what are you after? The objective of resetting isn't the real "goal" of what you want to achieve.
Update:
I know you said you can't modify the source code, so you can hope that it implements Google Analytics. If so, you can look at the real time activity of your web site. This at least gets you "somewhere" in some trivial fashion. BUT just the same, the "magic" is based on cookies (which therefore means its still subject to the questions I posed above)
Keep increesing and decreesing an application variable at session start and session end events. then you will have the session count. if sesson count is zero, then you can reset the thing. all the best.
The title pretty much says it all. Some caveats are:
I need to be able to do it in C#
It needs to be able to be done from a remote server (ie, running on one server, checking IIS on another)
Needs to be close to real-time (within 1 second)
Can use WMI calls
I've tried watching the log file, but it turns out that isn't nearly close enough to real-time.
Thanks!
EDIT: I put this in a comment on Tom's answer, but it's more visible here:
I was able to look for changes using this counter:
var perf = new PerformanceCounter("ASP.NET Apps v2.0.50727", "Requests Total", "_LM_W3SVC_[IIS-Site-ID]_ROOT", "[Server-Name]");
How about reading the ASP.NET requests/sec performance counter on the remote machine?
The System.Diagnostics.PerformanceCounter class has a constructor which takes a machine name.