Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying a stub page while ASP.NET app starts

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?

like image 394
Impworks Avatar asked Jan 24 '14 15:01

Impworks


3 Answers

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

like image 182
TGlatzer Avatar answered Sep 28 '22 03:09

TGlatzer


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.

like image 26
Mark Redman Avatar answered Sep 28 '22 04:09

Mark Redman


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.

like image 30
fejesjoco Avatar answered Sep 28 '22 03:09

fejesjoco