9

Can I display a specific page while ASP.NET application is still in the process of initialization?

We've got a huge ASP.NET application that takes about 30 seconds to complete its Application_Start() handler after each redeploy or AppDomain restart. Showing a nice self-reloading "temporarily unavailable" page during that time will greatly improve the experience for first users.

I tried to extract the initializer code into a different thread, but it has a lot of dependencies: the HttpContext, Server and several other classes are unavailable from derived threads. The code becomes intervowen and incomprehendable, so I'm looking for a better solution. Maybe some IIS configuration or extension?

Impworks
  • 2,647
  • 3
  • 25
  • 53

3 Answers3

8

Well, since IIS 7.5 you can use Application Initialization for that (http://www.iis.net/downloads/microsoft/application-initialization) that will make it possible to either show a "splash-Screen" or to just pre-start Application-Pools.

Here is the explanation for IIS8: http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-application-initialization It will work similar with IIS7.5, but there you have to install the module beforehand.

And here a link taken from the comments: http://blogs.msdn.com/b/abhisk/archive/2013/08/16/configuring-application-initialization.aspx

TGlatzer
  • 5,815
  • 2
  • 25
  • 46
  • Can you provide an example of how this would work? The page you linked to is a little light on actual usage. – Tommy Jan 28 '14 at 12:38
  • I added a link to the IIS.net page for ApplicationInitialization – TGlatzer Jan 28 '14 at 13:08
  • I managed to make it work using the following tutorial: http://blogs.msdn.com/b/abhisk/archive/2013/08/16/configuring-application-initialization.aspx. It's exactly what I needed. – Impworks Jan 28 '14 at 13:08
  • @Impworks - yeah, this one caught my eye as an awesome way to handle those pesky 30s - 1m start ups. Don't forget to award the bounty, I think Grumbler earned it on this one :) – Tommy Jan 28 '14 at 13:15
  • @Tommy, definitely, just can't do that before until 24h after bounty announcement though. – Impworks Jan 28 '14 at 15:27
  • @Impworks - gotcha! didn't know about that limitation – Tommy Jan 28 '14 at 15:59
2

You could load a static html page or page that is not effected by the system startup, then via ajax poll/check something (value, etc) that will only be available once the application starts, this way you could have an animation or some loading information on the page.

Mark Redman
  • 24,079
  • 20
  • 92
  • 147
  • How do I make sure the static HTML page is only displayed when the application is not fully started? It must replace any page on the website, not just the start page. – Impworks Jan 24 '14 at 20:14
  • Good question: Its looks like you cannot run code before the application starts for example, even using an HttpModule to check the application start: http://stackoverflow.com/questions/2779137/hook-into-application-start-in-a-httpmodule – Mark Redman Jan 24 '14 at 21:45
  • Use normal JavaScript http request. If you need code example let me know and I will post my stub page and js – Exzile Mar 23 '23 at 03:47
1

I think you're looking for something that is impossible. So you want to create an Application_Start that takes a long time to finish, and you want your application to be responsive during that time. Application_Start is a synchronous event, meaning that not a single request will begin processing before it completes. It is its job after all.

You have to loosen up your requirements somehow. Here are some ideas.

A new HTTP layer

As I said, you cannot run .NET code in your application before Application_Start finishes. But you can run another, different application.

So let's create another application that faces the clients. A reverse proxy or similar. I'm sure there are reverse proxy implementations out there which allow you to do some scripting and solve the issue. On the other hand, I have myself written a simple reverse proxy in C#. When it received an HTTP request, it created an HttpWebRequest and relayed it to another URL. It supported GET and POST, it is working in production for years now. If you are interested, I may be able to share some details about it.

The only thing you have to solve is how your backend application communicates with the frontend. That's easy, you can use WCF, IPC, create a simple 0-byte marker file somewhere, anything at all. When your Application_Start starts, you can create that 0-byte file, and when it completes, you delete it.

Note that many things happen after you shut down your application, restart it, and before the Application_Start runs. IIS initialization can take a few seconds. So instead of the 0-byte marker file, which only has 2 states (exists/not exists), you can expose a simple WCF service, with named pipes for example. It can have 3 states: doesn't respond at all (the application is stopped), it responds that the application is starting up, or it responds that the application is running. This WCF service has to be self-hosted and run in the background, because IIS won't respond obviously.

HTML/JS magic

It is basically the same idea as above. It is easier because you don't have to set up another application, but less flexible. You have to create an HTML landing page for your application and you have to make sure that users don't bookmark any other page. If you can do that, you are in luck. You can use the ideas from the above solution about how your application can communicate with the outside world while it's starting up. You can not use simple web services hosted in IIS, but you can host your own WCF services without any problems (create your own ServiceHost, etc.). Of course, this self-hosted WCF service won't run at the same host:port as your application. But it's pretty easy to expose a JSON service in WCF.

So, in your HTML landing page, you write some JS AJAX code that queries your self-hosted JSON service. If there is no response, you can tell the user that the application is not running at all. If the service says that it is starting up, you can tell that to the user. If the service says that the application is running, then you redirect your user.

This will not work if your users are browsing your site already when you shut it down. See, that's why you need an entirely new layer.

IIS magic

This is a somewhat uncharted territory for me. In integrated mode, .NET is an integral part of IIS, so I think it's hard to work around it. In classic mode, however, .NET is run as an ISAPI extension. So you can, in theory, write a new ISAPI extension that runs before .NET. The bad news is that it has to be written in C/C++. But it is obvious, because like I said, you cannot run .NET code before Application_Start finishes. But IIS is not dead during that time, so solve it at the IIS level. This can get ugly and I'm only 99% sure that it is actually possible.

Refactoring

The above are all workarounds. You really should refactor your code so that Application_Start finishes quickly. It is not meant to be a heavyweight function. There is already a framework for preloading ASP.NET apps. If you tell us why you need HttpContext and Server in your initialization code, we are here to help you with those problems.

fejesjoco
  • 11,763
  • 3
  • 35
  • 65
  • Thank you for such a detailed answer. It may be useful for people who work with older versions of IIS, since ApplicationInitialization module suggested by @Grumbler85 requires IIS 7.5 and newer. – Impworks Jan 28 '14 at 15:34
  • Oh yes, I felt kind of bad after writing so much and finding out about that feature :). Anyway, it's good that I learned something new. And it does match the IIS magic part of my answer, makes sense that it comes built in now. – fejesjoco Jan 28 '14 at 15:40