I have been developing an ASP.Net 4.0 web application, and I have used the HttpApplicationState class with its Contents property to set some variables in the Application_Start event of the Global_asax file.
While the application runs as expected on my development machine, when it is deployed on the production server running IIS7 the values returned for the application state variables are null. I have tried various code techniques, like using the HttpContext,Runtime.Cache, the Application["key"], and the Application.Contents.Add["key",Value], all with no success. I am wondering now whether there should be a special configuration on IIS7 on this; researching the topic I see that people say that the application pool in which the application is executed must be served by only a single worker process; I am no IIS7 expert, but selecting the application pool, and viewing its advanced properties, I can see that the pool is configured to have a maximum of 1 worker process, so I believe this should cover it. I have spent a good 2 days on this, so if anyone has any knowledge of this issue, please help!
thanks
chris
HttpContext.Current.Application is available in both IIS 6 and 7, integrated mode or classic.
The Application_Start event in global.asax is also called in all environments.
When running IIS 7+ in integrated mode, event handlers in global.asax are only applied to requests that are mapped to the ASP.NET handler (objects derived from the Page class). Custom HttpModules are applied to all requests.
Application state, or any other static variables, are not shared from one instance of IIS to another -- so settings in one AppPool or worker process aren't visible in others.
Application state and post-init static variables settings are lost across AppPool resets (though you will also get a new Application_Start event). This is true whether the resets are due to the worker being idle or for the usual daily resets.
Instead of using HttpApplicationState, it's better to create your own static class, with static properties for app-wide settings. That way, your accesses are strongly typed, have Intellisense, and aren't susceptible to misspelling key strings.
Whether using your own static class or HttpApplicationState, be sure to set a lock before reading a setting when you might also change it. You can use HttpApplicationState.Lock() if you decide to stay with that approach.
You might try running your app under IIS Express locally, or even IIS 7 (Vista) or 7.5 (W7), to help debug your issue. Cassini is deprecated at this stage; I would avoid using it as much as possible.
It is probably that you do not have the correct application pool mode.
IIS 7 application pools have 2 modes, classic and integrated. See. http://weblogs.asp.net/jgaylord/archive/2008/09/04/iis7-integrated-mode-and-global-asax.aspx
Related
We are using IIS7 to host an asp.net web-based application.
In this environment administrators and developers can deploy code to the application on a regular basis.
The new code or app goes as a DLL to the ASP.NET bin folder. Upon deployment of the new DLL, IIS restarts the process, impacting (slowing down) all online users.
Is there a way to configure IIS to run the process in the background and once ready make the switch from old state into new without impacting the users?!
Thanks in advance for your feedback!
IIS already does this, that's what recycling is all about. IT's loading the DLL's while the old version of the application is still running. only after this is completed the recycling is complete.
However loading the DLL's is only part of getting web applications ready, there might also be initial loads like loading/caching the user db etc.
These actions are not part of the recycle process, they happen after all DLL's reloaded and the recycling is already completed.
A while back I ran into this issue with an application that had a huge startup time due to heavy db activity/caching during startup. So I was interested if there is some functionality that allows us to execute code before the recycle is marked as completed, so that the application is first considered recycled when everything is ready to run. Basically what I wanted is some kind of staging functionality.
I was in contact with the IIS team regarding this issue, sadly they told me that no such functionality exists, nor is it planned.
To solve this you could try do the following:
Use alternating deploys:
You setup 2 Websites with separate application pools. One of them is the LIVE website the other one is the STAGED website. If you want to deploy changed you simply deploy to the STAGED website. After everything is loaded/cached etc. you switch the URL settings of the web applications to reroute incoming requests from the LIVE to the STAGED one. So the LIVE one becomes the new STAGED and the other way around. The next deploy would then go to the new STAGED again and so on.
UPDATE
Apparently they have created a IIS Module that provides this functionality by now:
IIS Application Warm-Up Module for IIS 7.5
The IIS team has released the first beta test version of the
Application Warm-Up Module for IIS 7.5. This makes warming up your
applications even easier than previously described. Instead of writing
custom code, you specify the URLs of resources to execute before the
Web application accepts requests from the network. This warm-up occurs
during startup of the IIS service (if you configured the IIS
application pool as AlwaysRunning) and when an IIS worker process
recycles. During recycle, the old IIS worker process continues to
execute requests until the newly spawned worker process is fully
warmed up, so that applications experience no interruptions or other
issues due to unprimed caches. Note that this module works with any
version of ASP.NET, starting with version 2.0.
For more information, see Application Warm-Up on the IIS.net Web site.
For a walkthrough that illustrates how to use the warm-up feature, see
Getting Started with the IIS 7.5 Application Warm-Up Module on the
IIS.net Web site.
See:
http://www.asp.net/whitepapers/aspnet4
If you use ASP.NET 4 Auto Start feature:
You can still choose to auto-recycle the worker processes from time to
time. When you do that, though, the app will immediately restart and
your warm up code will execute (unlike today - where you have to wait
for the next request to-do that).
The main difference between Warm Up and Auto Start feature is that the Warm Up Module is part of the recycling process. Rather than blocking the application for requests, while running the init code.
Only thing you get by using the Auto Start feature is that you don't have to wait for a user to hit the page, which does not help your case.
See the Gu's blog post:
http://weblogs.asp.net/scottgu/archive/2009/09/15/auto-start-asp-net-applications-vs-2010-and-net-4-0-series.aspx
UPDATE 2:
Sadly the Warmup Module has been discontinued for IIS 7/7.5:
http://forums.iis.net/t/1176740.aspx
It will be part of IIS8 though (It's now called Application Initialization Module):
http://weblogs.asp.net/owscott/archive/2012/03/01/what-s-new-in-iis-8.aspx
UPDATE 3:
As pointed out in the comments the Warmup Module resurfaced for IIS 7.5 as Application Initialization Module for IIS 7.5 after IIS 8 was released:
http://www.iis.net/downloads/microsoft/application-initialization
The first part of ntziolis answer is a wee bit inaccurate. The worker process isn't being recycled or restarted, it just keeps running. If this were the case, then in shared pool environments you would have sites knocked out every time a new one was deployed.
When you deploy a new ASP.NET application it's the site's "Application Domain" within the worker process is torn down, not the pool process.
In addition pool recycling is a completely separate concept to deployment
At this point in time in the commercial life of ASP.NET, during a deployment, a site will be in an inconsistent state until all of the site is deployed. There is still no good story about this from Microsoft at this time for single site on a single server deployments.
This is why ASP.NET has the special App_Offline.htm page. It's there so you can enable that page, deploy and then turn it off.
The second part of ntziolis answer is nearly correct but you don't need two sites or two application pools. You just need two file system folders that switch between being the physical folders for the site...if you're on a single server and not behind a load balancer or ARR.
If your sites were on a web server behind a load-balancer or ARR then having two different sites would make sense, you could route requests from one site to the other and round-robin on each deploy.
Obviously if there is a large amount of user generated content (uploaded files and the like) then you'd map a virtual directory in your site to a common location for this data.
In larger scale deployments where your app is running across (for example) a load-balanced environment you can do more sophisticated deployments.
For related questions please see:
How Do I deploy an application to IIS while that web application is running
Publishing/uploading new DLL to IIS: website goes down whilst uploading
Is smooth deployment possible with componentized ASP.NET MVC apps?
We would like to warm up an ASP.NET MVC application hosted on IIS 7.5 server. The warm up module that used to be available at http://forums.iis.net/t/1176740.aspx has been removed since sometime.
The application should be warmed up everytime IIS or ASP.NET worker-process restarts for any reason. During the warm up period, IIS should return some HTTP status code signifying its warm up state or its inability to serve any clients.
Would creating a executable that navigates through necessary pages in the site via HttpRequests be a good idea? The executable can be triggered from IProcessHostPreloadClient implementation. Is it possible to configure IIS so that it would only accept requests from localhost and once the executable is done, it can switch over to all clients - but that switch should not trigger an IIS restart (obviously).
Is it possible to use an Visual Studio 2010 - Web Performance Test to warm-up an application instead of creating an manual executable? Any other alternatives?
PS: The application uses Forms Authentication and uses sessions - so maintaining state cookie and other cookies is important.
UPDATE 1 - We are using .NET Framework 4.0 and Entity Framework (database first) in our application. The first time hits to EF queries are slow. The reason behind the warm up is to get these first time hits out of the way. We are already using compiled queries at most places and we have implemented pre-compiled views for EF. The size of the model and application is very large and complex. Warm up needs to walk through many pages to ensure that compiled and non-compiled EF queries get executed at-least once before any end user gets access to the application.
Microsoft has released a module that does exactly what you ask for. The Application Initialization Module for IIS 7.5 improves the responsiveness of Web sites by loading the Web applications before the first request arrives.
You can specify a series of Urls that IIS will preload before accepting requests from real users. I don't think you can get a true user login expereince, but maybe you can set up simulated pages that does not require login that fulfills the same warmup you ask for?
The feature I think is most compelling is that this module also enables overlapped process recycling. The following tutorial from IIS 8.0 include a step-by-step approach on how to enable overlapped process recycling.
When IIS detects that an active worker process is being recycled, IIS does not switch active traffic over to the new recycled worker process until the new worker process finishes running all application initialization Urls in the new process. This ensures that customers browsing your website don't see application initialization pages once an application is live and running.
This IIS Application Initialization module is built into IIS 8.0, but is available for download for IIS 7.5.
You may take a look at the following post for the Auto-Start feature built into IIS 7.5 and ASP.NET 4.0.
Any application that generates a server request for the hosted resources can be used to warm up an IIS process. Exactly how many requests you need depends on what parts need warming up. Typically, warm-up is used for:
Starting up a worker process. For this, you only need to ask for one resource to warm up a process for the entire application.
Perform any static initialization, database startup, or pre-caching. Anything you do in your Global.asax file will happen when you do your first request, so if you can make all of your initialization happen then, you'll still only need to make one page request.
Force pre-compilation of ASP.NET pages. For this to happen you would need to hit every page. Fortunately, this is typically not much of a time cost, so you likely don't need to worry about it. If you do have individual pages that load slowly, you can warm them up separately.
The "warm-up" process here isn't anything magical. You just need force IIS to serve the URL in question. Everything you mentioned would take care of that: using a stress-test tool to query the URL, writing a custom utility to post HTTP requests, even just scripting out a tool like 'wget' or a PowerShell script to download the URLs would do it.
As far as restricting access to localhost, as far as I know, within IIS, the only way to change that requires you to restart IIS. You could always build a pre-request hook into your application and maintain the state there, and have your warm-up process query some specific URL that toggles that state to "open". But I'm not sure what you would accomplish. If, somehow, a user did try to query your site before your warm-up finished, all that would happen is your site would take a long time to respond, then they would eventually get the page they asked for. If you locked them out of the site during warm-up, they would instead get a browser network error that claimed the site was offline, which (to me) sounds much worse.
Backstory
Last month our development team created a new asp.net 3.5 application to place out on our production website. Once we had the work completed, we requested from the group that manages are server to copy the app out to our production site, and configure the virtual directory as a new application.
On 12/27/2010, two public 'Gineau Pigs' were selected to use the app, and it worked great.
On 12/30/2010, We received notification by internal staff, that when that staff member tried to access the application (this was the Business Process Owner) they recieved the 'Server Application Unavailable' message.
When I called the group that does our server support, I was told that it probably failed, because I didn't close the connections in my code. However, the same group went in and then created a separate app pool for this Extension Request application. It has had no issues since.
I did a little googling, since I do not like being blamed for things. I found that the 'Server Application Unavailable' message will also appear when you have multiple applications using different frameworks and you do not put them in different application pools.
Technical Details - Tree of our website structure
Main Website <-- ASP Classic
+-Virtual Directory(ExtensionRequest) <-- ASP 3.5
From our server support group:
'Reviewed server logs and website setup in IIS. Had to reset the application pool as it was not working properly. This corrected the website and it is now back online. We went ahead and created a application pool for the extension web so it is isolated from the main site pool. In the past we have seen other application do this when there is a connection being left open and the pool fills up. Would recommend reviewing site code to make sure no connections are being left open.'
The Real Question:
What really caused the failure? Isn't the connection being left open issue an ASP Classic issue? Wouldn't the ExtensionRequest application have to be used (more than twice) in the first place to have the connections left open? Is it more likely the failure is caused by them not bothering to setup the new Application in it's own App Pool in the first place?
Sorry for the long windedness
You'd really need to obtain and review the server's Application & System event and HTTPERR logs for the period the server was reporting these errors.
Without these it'd be hard speculate what was the root cause of the problem.
Update:
OP incorrectly tagged his question so this next section no longer applies. However I'll leave in place because I think the information is useful for those encountering these issues and perhaps thinking about migrating to IIS7.x.
You are correct that running two different .NET Framework's in the same application pool can cause these errors but that's something you'd tend to see on Windows 2003/IIS6, not Windows 2008/IIS7.
IIS7 uses a slightly different approach to specifying which .NET Framework version is loaded and it's determined by the Application pool's managedRunTimeVersion property. When requests are processed by IIS/ASP.NET the site's Handler Mapping's use a preCondition attribute to determine when to load the requisite handler (which is kind of like a script mapping in previous versions of IIS).
This mechanism prevents the incorrect runtime version being loaded into the application pool's worker process.
So if an application pool is configured to run .NET Framework version v4.0 only that version will load, even if your application is built against v2.0.
There's a great article on how this works here:
Achtung! IIS7 Preconditions
The section on Handlers about half way through explains why the dangers of accidentally loading the wrong .NET version into a pool are mitigated by the preCondition feature.
A Server Application Unavailable error usually means something catastrophic has happened (like loading the wrong ASP.NET version's ISAPI filter into an already running worker process).
Not closing SQL connections is unlikely to cause this type of serious error. You'd more than likely be seeing a yellow screen of death runtime errors if that were the case. Running out of SQL connections usually doesn't bend ASP.NET so out of shape that the whole service tops itself.
My prime suspect would be a permissions problem where the application pool identity was unable to correctly access the application folders. But it's just a hunch.
Again, what you need to do is get the Application & System event logs and the HTTPERR logs (they reside in %systemroot%\System32\LogFiles\HTTPERR. That will contain clues and facts about what went wrong.
Update 2:
On Windows 2003/IIS6, if you have two applications running different ASP.NET versions that reside in the same pool you will get this error. In my experience (I work for a web hoster) it is the primary cause of this infamous error page:
There's also a tell-tale event logged to the Application Event log:
Event Type: Error
Event Source: ASP.NET 2.0.50727.0
Event Category: None
Event ID: 1062
Date: 12/01/2011
Time: 12:31:43
User: N/A
Computer: KK-DEBUG
Description:
It is not possible to run two different versions of ASP.NET in the same
IIS process. Please use the IIS Administration Tool to reconfigure your
server to run the application in a separate process.
Whilst your root application may not be written in ASP.NET it's likely that something has triggered loading of a different version of the framework into your site's application pool.
there's a rogue web.config in the root...this will trigger ASP.NET to load
there's a wildcard mapping to ASP.NET 1.1 in the site script maps (less likely, but possible)
I'm inclined to think that your new application most certainly ended up in a pool where other sites or applications were running a different framework version. The only way to really find out is to obtain the Application event logs and look for the event shown above.
It's hard to tell; there could be many causes (too many resources used, calling outside of .NET caused something to crash, etc). I would look in the Event log and see if you can find something there.
If you're running different versions of .NET you definitely want separate pools. If you have the option, I would recommend separate pools for each application (even if in the same .NET version).
As far as "closing the connection" (I assume you mean the connection to the database). If you're creating "low level" connections (i.e. SqlConnection, SqlCommand) then make sure you're wrapping them in a "using" statement, otherwise your connection pool can fill up. In my experience though, you should receive regular .NET errors in this case. If you're using an ORM this shouldn't be an issue.
Edit:
If you can't find anything useful in the Event Log, you could try this: http://learn.iis.net/page.aspx/266/troubleshooting-failed-requests-using-tracing-in-iis-7/
how I Can Configure IIS to start a method (I define it) before starting each asp.net's application on it?
i just want to do someting with IIS (not each application) so that any application that starts on Server executes a method that i Defined it. in fact i want to create a threat that do something. for example i can create this threat in a asp.net application but when IIS shuts down this threat too will shut down. now i want sure at any time this threat is running (one or more instances of this threat). and IIS version is 6.
You can use the Global.asax file and put your code in the Application_Start() method of each ASP.Net application, which will run it once when the first request comes in to the application.
I'm not entirely clear if this answers your question. Can you be a bit more specific on what you're trying to do?
Scenario: I've an n-Tier enterprise ASP.NET application deployed using Web Deployment Projects. All tiers produce independent assemblies that is consumed by the ASP.NET application.
Problem: When I run the app. for the first time after deployment it takes lot of time to load dependent assemblies in memory. But once loaded its lighting fast app. In case if there are no users accessing the app, IIS unloads the assemblies from the memory and when a user tried to access the app on a later instance it goes on loading all the assemblies once again taking the same amount of time to load as it takes to do so for the first time.
I'm looking for a solution that enables me to keep my assemblies loaded into memory persistently overriding the volatile nature of assemblies towards memory residency.
Or any other solution that lets my users happily use the app resolving the mentioned problem.
In IIS 6, go to the Application Pools section, and right-click > Properties on the pool which hosts the ASP.NET application in question. Go to the Performance tab and uncheck "Shutdown worker processes after being idle for:"
In IIS 7, go to the Connections pane and find Application Pools, and select Advanced Settings for the pool which hosts your application. Find the "Idle Timeout" property and set it to "0" (this disables it).
The default is 20 minutes of inactivity. By unchecking the box, once your AppDomain is loaded by the worker process, it will never die (unless you kill the process or something of course). By default, IIS will recycle the process when it reaches some limit, such as a memory cap, but it will also start a new one and "phase over" all incoming requests until the old one is unused, so as to minimize disruption.
I've also written a small c# class which will keep your ASP.NET application alive (alternate archived version) under normal circumstances. Since it runs within the application, obviously it can't stop IIS or anything else from explicitly killing the process, but it will keep the application "hot", e.g. the app will never go idle long enough for IIS to decide to shut it off.
If you do not have direct control over your IIS configuration (shared host, for example) your best bet is to have a small application running on a separate system - say, an always-on workstation - which hits your site every x minutes to keep the application pool from timing out. Nothing fancy - a simple WebRequest and a while() loop in a console application will do.
One of the advantages of ASP .net is the posibility to create static (shared) instances of objects.
To avoid the necessity of an external process you can create an static timer in (per example) global.asax which calls for a page on the domain with a simple WebRequest. On this way the site keeps alive himself until a manual reset of the pool is done.
I wrote a little C# console application that keeps my 4 sites alive every 10 mins via windows task scheduler. Life is once again good. We do not run the app from 2-5am just so the serves can do any cleanups of memory, if it even matters. for our sites there is rarely anyone on at those hours anyway.