Displaying a stub page while ASP.NET app starts - c#

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?

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

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.

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.

Related

Slow first request after publishing Azure Web App

I have performance issue with ASP.NET Web API app hosted as Azure Web App. After deploying the first request to web service is really slow (we are talking about seconds here). Subsequent requests work just fine without extra delay.
"Always on" feature works fine keeping the app from unloading but this does not solve my issue. I do not want this first request to warm up the service (BTW - should it be warmed up?).
I've used diagnostic and profiling tools in Azure without finding the root cause of this thing. I've used Application Insights as well. It seems like one function of mine needs much more time to execute during this first request - debugging the app locally I did not notice any performance issue with mentioned function.
How can I fix this?
Thanks!
This bit me as well. "Always On" will only make automated calls to your service root - think about slapping the process every time so it won't fall sleep.. We don't use this in our PROD services, we rather have an Azure Availability Test invoking a Ping() endpoint every 5 mins - two birdies, one stone. Besides, AlwaysOn will generate 404 errors in App Insights if you don't have anything in the root..
A totally different thing is warming up each one of the endpoints so they could get JIT-ed and ready, and I have not found anything better than a warm-up script with the whole list of endpoints to call, it is not perfect but it works. So every time you do a deployment o do a restart this will automatically run and your first calls won't be hurt.
Have a look at this article.
I hope this helps

Cannot keep alive Web Application on IIS after Recycling or Restarting

I have an MVC application that send an e-mail periodically using Quartz.NET. Although the published application works properly on IIS, it cannot works after recycling application pool or restarting the application on IIS. Searching on the web I found several post suggesting to make some changes on config files or IIS, but none of them working properly. So, is there any method to solve the problem? I need a solution that can be applied on application side (or on IIS side if it is simple just making a config changes, etc.). I think this is a common problem when keeping an application on IIS, isn't it?
Note: I use Windows Server 2008 and IIS 7.5.
You do not mention in your question where your application is going to run so I guess it's going to be hosted in-house.
Following your comment I gather you do not have any problems installing and running a Windows Service on your server.
My suggestion - and something I've implemented in the past - is to use the ASP.NET MVC application only as a UI where you create, delete or suspend your jobs/triggers which will be persisted in a database so, whatever happens to your application, you won't lose your jobs/triggers and they will be executed as soon as the application goes back on-line.
The database will be shared with the other layer, the Windows Service, which will be responsible for running your scheduled jobs.
First step is to setup and use AdoJobStore to store Quartz.Net data. As you can see in the post there are a few providers you can use.
Second step is to create and configure your Windows Service. I would use TopShelf to host it. The implementation is very simple and straightforward; plus you can use the Quartz.Net integration provided here.
If you go through the documentation you won't find any problem integrating the solution.
Quartz.Net depends on some configuration you have to add in your app.config/web.config. In this answer there's a detail explanation about the configuration and AdoJobStore.
There are a few things to remember implementing this type of solution.
Your Web Application is going to set the property threadPool to ZeroSizeThreadPool in your config:
<add key="quartz.threadPool.type" value="Quartz.Simpl.ZeroSizeThreadPool, Quartz" />
or in your code:
properties["quartz.threadPool.type"] = "Quartz.Simpl.ZeroSizeThreadPool, Quartz";
and it's never going to start the Scheduler (your windows service is going to use that).

Share data between Windows Service and Cassini-dev running in the same process

I have a Windows Service written in C#. I have recently added CassiniDev to it to allow remote web administration and monitoring of the service. The integration went really well except for my inability to interact with data layer of my Windows Service from hosted ASP.NET pages.
I have tried putting everything of interest into a common assembly but the debugger shows there are two loaded assemblies with the same name but from different paths. Cassini runs ASP.NET off some temp folder so the assembly I am using is really "a different instance" in the address space of the same process.
I am not sure what is going on here. Probably some "application domain" separation stuff that I do not understand at this time.
So with Windows Service and the web server running in the same process, how can I make them interact? Say I have some status in the Service part that I want to report in the ASP.NET part. Any ideas how I could make this happen? Shared memory or TCP comes to mind but it sounds like an overkill for purely intra-process communication.
If security isn't an immediate concern, i.e. the data isn't highly sensitive and in a controlled environment, then you could have success using Named Pipes. A managed API for processing piping has been implemented as part of the framework, so you don't need to think in native calls.

Is there a way to have code run on a time schedule in an ASP.NET web app?

I have an ASP.NET web app providing access to a database on the server. What I need is a way to run code in the background on a given schedule that auto-updates the server database from another source.
I know how to do this in a windows app by adding a timer, linking up a function to the timer tick event and starting the timer. I do not know how to do this in a web app.
Is there a start-up event for a web app or somewhere where I can start this background process regardless of whatever any users are doing on the site?
You should not do this in an ASP.NET website - this is a major no-no. You are correct in thinking to use a timer on a background .exe. You should look into creating either a Windows Task (a console .exe executed by the server task timer), or a Windows Service. I would suggest the Windows Service as that is standard practice.
If you have access to the computer hosting your site I would write a little app that was run from the Task Scheduler.
The web server is not meant to handle long-running background tasks. It's the wrong tool.
If you dont have access to the hosting computer then I would suggest building some kind of interface whereby another computer rebuilt the database and uploaded it. I'm using the terms "interface" and "upload" in the loosest, broadest sense - apply your own definition.
I was searching for a solution myself couple of months ago, and even though I haven't found enough time to try it so far, I guess I can share the link with you. Maybe you'll find it helpful.
If yes, please, let me know here.
http://quartznet.sourceforge.net/
How to use Quartz.net with ASP.NET
you can use Windows Service or use Timer Control (In the Ajax Category)
Or
As other answers have stated, doing this full function - updating a database and scheduling it as an ASP.NET app is using the wrong tool for the job.
ASP.NET can be used to update a database - that's perfectly valid. Where it breaks down is in the timer. ASP.NET apps aren't meant to be long-running, which is necessary for the timer to work.
If you can do it, I'd strongly suggest using the approach others have suggested - a Windows Service or a Scheduled Task.
However, if you have no access to the actual server, other than to post ASP.NET code - you can't install a service and you can't set up a Windows app to run on a scheduled basis, here's an out-of-the box idea.
Set up a web service or ASPX page that does the update, and then call that page from a scheduled task on a machine you DO control.
So if this was at http://www.someserver.net/updatedb.aspx, there's no reason you can't set a scheduled task on your own PC to call that URL.
I'd consider this a last-ditch solution to be used only if you can't do one of the other options.
The global.asax.cs file has a method that is fired when your application starts: Application_Start. You can hook up your timer method in that event. Just beware, depending on how IIS configured, your app pool may shutdown. For example, if no one hits the site in 20 minutes for example. Just make sure if you HAVE to have this run every X minutes that you have IIS configured to ALWAYS be running and start your app. This is harder than it sounds. In the end, you may want to go with a regular windows scheduled task.

Which technology to use for running crawler and updating database in asp.net website?

I am developing a project for college and i need some suggestions over the development. Its a website which shows information from other websites like Links, Images etc.
I have prepared below given model for the website.
A Home.aspx page which shows data from tables (sql server).
I have coded a crawler (in c#) which can crawl (fetch data) required website data.
I want some way through which i can run the crawler at back end for some time interval and it can insert updates in the tables. I want that i can get updated information in my database so that Home.aspx shows updated info. (Its like smaller version of Google News website)
I want to host the wesbite in Shared Hosted Environment (i.e a 3rd party hosting provider company and that may use IIS platform)
I posted simliar situation to different .NET forums and communities and they suggested lot of different things such as
Create a web service (is it really necessary ?)
Use WCF
Create a Console application and run windows task sheduler (is it okay with asp.net (win forms website) and in shared hosted)
Run crawler on local machine and update database accordingly. (No i want everything online) etc etc
Please suggest me a clear way out so that i complete the task. Please suggest elobrated technology and methods which suits my project.
Waiting...
Thanks...
Your shared host constraint really impacts on technologies restrictions.
In theory, the best way to host your crawler would have been a Windows service, since you can take advantage of windows services configuration. A service is always up, can be automatically started at startup, writes errors in event log, can be automatically restarted after failure...
Then, you Home.aspx would have been a regular website in IIS.
If you really stay on a shared host (where you cannot setup a service), I would have make the crawler as a module which is run on your application startup.
Problem is, IIS application pool doesnt live forever if your web site is not in use, and it may stop the crawler. It is configurable, but I dont know how much in a shared host.
In IIS 7.5, think about starting your module at application warm up
Finally if you need to run the crawler at interval times (like every day at midnight), if your shared host does not let you set task scheduling, think about Quartz Framework, which allow you perform task scheduling inside your application (without the intervention of the OS)
Integrate your crawler code into a aspx page
Setup a task scheduler on your host to call that page every X minutes
When the page is called check that localhost has called the page
If localhost called it run the crawl routine and
If localhost hasn't called it throw a 404 eror

Categories