new Blog(".NET Programming", "Photography").ToString();

Whenever you do maintenance work on a website it is advisable to show the visitors a nice message telling them politely to come back later, rather than a nasty error, or even worse: a big Yellow Screen of Death.

Since ASP.NET 2.0 came out of the labs of Microsoft, there is a way to take a web application down using the “app_offline.htm” approach. You simply create a HTM file, which you then upload to the server, and if there is any request to this web application, IIS will automatically show the contents of the app_offline.htm file. Once uploaded, most people only rename the file so that it doesn't catch up with IIS anymore, and the site is already back online.

This approach comes in really handy when you upload new files to the server, and while the upload did not finish, there are already requests coming in. (Ex: somebody accesses your website - ~/default.aspx, and you have some logic in this page that references a class that has not been uploaded yet)

Where this approach simply doesn’t cut the mustard is when you want to restrict the access for visitors, but you still want to be able to access the site as an administrator (testing, problem investigation, general maintenance). The app_offline.htm approach is not good for this because simply everybody will get the content of the app_offline.htm file no matter what the requested page is.

In the quest for a good solution to this problem I had the following facts in mind:

same sort of easy use like uploading the app_offline.htm (maybe a similar file to trigger the action)

access granted based on the ip of the visitor (if AdminIP == RequestIP –> unrestricted surfing)

My current solution looks like this:

The filter is triggered when a file named “offline.html” exists on the server. (This is practically the same idea as the app_offline.htm one)

As you can immediately see, on each Request, I’m performing a check for a file named offline.html with File.Exists(). If it exists I’m checking for the administrator IP in the web.config file to see if the request is coming for somebody that should not be restricted.

Once offline.html uploaded, each “restricted” visitor will only see the content of offline.html.

To disable the whole functionality you only need to rename the offline.html file to anything else (I suggest a difference of a character so that it can be easily renamed back: offlin.html).

In a very small maintenance group this solution works just fine, but for future work I’d definitely create some functionality to define more IP addresses which can access the website while it’s taken “offline”. Defining an IP class would also be another good idea, particularly when the number of “administrators” is very big.

There is little limit in the possibilities to identify who can and cannot access your website if you use this approach, you only need to program your logic into a BeginRequest event, and you are ready to go.

Implementing some CRUD functionality for Admin IP's was not the scope of this work, although if people request a sample for this, I could sit down and come up with a nice little solution.

Anyway, the whole idea is that anyone can implement their own "authentication" on the sample above. If somebody would like to: he/she could create a filtering based on the existance of specific cookies.

Have you considered the performance implication of doing an IO read with every request.

Your idea is a good one, although I would probably come up with a different mechanism (other than the IO read) to send visitors to the offline page.

An admin page that toggles an Application variable could be more performant. The admin page could also set the admin IP based on your current IP while accessing the page or you could modify this functionality to be sessionID based.

As mentioned in the post, this solution works well in a small maintenance group.

The actual IO read overhead is not a problem in an small application used simultaneously by 100~200 users. Of course I have thought about performance, and for bigger number of users I'ld suggest something different than your solution.

Storing an IP address in the Session is not accetable at all due to the fact that this would enable on 1 administrator. (Once the application is down, only one admin can access the website -> and what happens if the session expires?)

I'd rather create an interface in the admin area of the website where you can "enable" multiple IP addresses which are saved to some sort of datastore (file, database, whatever), and of course a big red button with "Take Application Offline" written on it. While these options are saved in the datastore, I'd save these into an Application variable | cache on each Application_Start event.

Then on every request I'd only retrieve the IP addresses from Application["AdminIPAddresses"] (ex).

Anyway, the whole idea of the post remains the same, but performance improvements can always be considered.

Well, if you only need to upload a new version of the website, if you temporarily update your database, or whatsoever, you'll be ok with app_offline.htm but if you need access to the website it won't be good .

I agree, this is a great idea. Using a technique to read the web.config would probably be less resource intensive than I/O, but like you said, it's the idea worth noting.

Expanding on your idea... have an application offline section in the admin area of your site. The administrator sets the reason for taking the application offline and clicks the "take offline" button. The application updates a application offline specific twitter account with the status (they can update as needed) and updates the web.config with the admin's ip address. The offline.htm file displays the twitter feed and any other relevant information to ease the pain for the end user. You can read more about my offline file idea here. blog.ntierdesign.com/.../creating-a-user-friendly-app-offline-system-maintenance-page

Thanks for your comment, your idea is practically similar to mine except the client side enhancements. This video thing well suited on a website "out there", but I guess you wouldn't want to do this when the application in question is an intranet application of the company you work for.

Regarding "the offline state in the web.config file", I do not agree with that. Once the file is saved on the production server, the ASP.NET application is restarted which is again a bit wasteful from performance point of view (because then we have to load up everything again). And there is another interesting fact which is more noticeable if the uploaded application has not been precompiled + you save a new web.config file, there will be a little outage until the system recompiles everything and generates the needed dll, into the ASP.NET Temporary Files directory. Depending the server this can vary between just a few seconds right up to ALLOT (based on how big you solution is ).

True, not for every situation, but the video is just an example. The ping functionality is the idea.

The web.config isn't optimal for my situation either, but you're most likely taking the application offline to push out some updates right? Modifying the web.config AND anything in the bin directory will recycle your app pool regardless. If your concerned about the perf hit, you'll of course want to pre-compile your app prior to publishing.

There's never a one solution that fits all situations, but your post has spun off several ideas for me and for that, I thank you!

You can also simply use the IP lock feature in IIS. Then you set the custom error page for http error 403 (IIS7) 403.6 (IIS6) to your html file and you have this functionality without any performance penalty. You can also now do whatever you want with the site (ie mess up the web.config the message will still be shown) and as a bonus you will be using the IIS gui for the configuration.

This way, even if the administrator logs out, they can still get to the login page to login. A user that logs in can only login and logout - so they are restricted to getting anywhere else other than the login screen.