15

In quite some scenario's, placing app_offline.htm in the root is just right: you do some updates, the message appears while updating, and that's that. The idea is, as Microsoft puts it, that before anything is called, IIS first checks if app_offline.htm is there and if so, it cancels everything and displays it.

So for so good, but in many situations it doesn't work:

  • When you have a compile error in an ASPX page and a user links directly to it
  • When you have conflicting assemblies
  • When you have a parsing error in your web.config
  • In the midst of removing / uploading the entire site.
  • A direct link to a static HTML page is still displayed as such
  • File-not-founds, access-denieds are thrown before the message is shown

Possibly more scenario's exist that fail. My point is: for any serious updating work, app_offline.htm is not suitable. I sometimes create a redirect in IIS, to another site, but another site may not always be available and it can confuse users.

Ideally, I'd want to keep the current location in the url location bar of the end-user, show the message, and have the page auto-refresh each minute to see whether the site is back, so that the user continues where he left of when the site comes back. While technically easy enough with a static page, it will fail for the above mentioned reasons the minute an error is thrown.

Abel
  • 56,041
  • 24
  • 146
  • 247

6 Answers6

10

No one else mentioned web.config and recompilation, so here it is. I've encountered this issue. I disagree with the person who said it's "not intended for prod use": VS 2010 uses app_offline when deploying so it's baked into the code.

The workaround (credit goes to Kurt Schindler, blog post here).

  1. copy up app_offline.htm to your site
  2. make a web.config that looks like this (see below numbered block)
  3. copy that web.config up to your remote directory
  4. copy all of the site files except your true web.config up to the remote dir
  5. copy the real web.config up to the remote dir (which should kick off a recompile)

web.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
  <system.web>
    <httpRuntime waitChangeNotification="300"
       maxWaitChangeNotification="300"/>
  </system.web>
  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"  />
  </system.webServer> 
</configuration>

The consequence of this is that you can't use the VS 2010 app deployment directly if you care about end users not seeing YSOD during a deploy. So you'll need to use Nant or some other deploy tool to do this.

Neal
  • 4,278
  • 2
  • 19
  • 25
jcollum
  • 43,623
  • 55
  • 191
  • 321
6

One way I've seen this handled on a number of very highly traffic'ed sites is to have multiple folders in the inetpub directory. Something like:

inetpub
     \ site2011-02-03 
     \ site2011-03-14

Where the "site2011-02-03" is the existing site and "site2011-03-14" is the one pushed today. Once the push to the new folder is complete you change the IIS site to point to the new directory. In case of failure, you change IIS to the older version.

Quite frankly, I've never encountered the errors you speak of when using app_offline.htm. It has always properly functioned to take the site down; even for direct links to pages. I'd guess that you might have something else going on here. and I've used IIS 7 and 7.5 (2008 R2) with it.

update
Just looked in our config. We have app_offline.htm mapped as the top default document on our servers. That might be a mitigating factor.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • +1 I like the idea of the fallback scenario and just pointing the website to a new location. Thanks for the tip about the default doc: I see now that I used that somewhere else and indeed it helps with some of the errors. However, assembly errors and faults in web.config still fail, as well as an existing link to a physical aspx file. – Abel Mar 14 '11 at 23:44
  • @Abel: Interesting. We'll have to do some internal testing on that. – NotMe Mar 15 '11 at 14:17
3

I like the idea of using an "offline" web app while your actual web app is offline. You would set up a symlink on your web directory to point to the appropriate application.

Your setup might look like the following:

Web_Dir (this is the directory that IIS serves www.yourdomain.com from)
WebApps

  • ActualWebApp
  • OfflineWebApp

Scenario: Your app is online
Web_Dir -> ActualWebApp (Web_Dir is linked to ActualWebApp)

Scenario: Your app is offline
Web_Dir -> OfflineWebApp (Web_Dir is linked to OfflineWebApp)


Essentially, you end up with two different web applications: an actual web app and an "offline" web app. This gives you the flexibility of redirecting users to another site but maintains the appearance of being your domain--because it is!

The actual web app is the real web application. This is the one you're making changes to and the one that has your actual content.

The "offline" web app has very little content. Maybe it only contains the static page you mentioned in your question. Maybe it has some routing to handle any page request, display an offline message, and reload every minute.

Your IIS web directory is actually a link to one of these two web apps. Normally, it will be linked to your actual web app. When you are ready to begin (re)deploying your web app, you change your web directory to point instead to the "offline" app. After the deploy is complete, you change the link back so that it points to the real web app once again.

Eric
  • 18,512
  • 4
  • 29
  • 34
  • This is essentially what we use the app_offline.htm trick for, which takes any ASP.NET site down (default IIS behavior). The htm file redirects to another location where we have our offline web app. But it fails for the mentioned cases. – Abel Mar 14 '11 at 23:46
  • Sure. You can overcome those problems by using a symlink instead of the app_offline.htm trick. You won't be redirecting the user and since its an app that you deploy separately from your actual app, you won't suffer from the cases you mentioned in your question. – Eric Mar 15 '11 at 14:08
  • With symlink I assume you mean junction point? Or are you suggesting to deploy on *nix environments (which, for most of my customers, is not an option)? – Abel Mar 15 '11 at 17:40
  • Suggesting that you deploy an ASP.NET web app on a *nix environment is a little crazier than I'd care to get. NTFS symlinks work much like *nix symlinks. More about them on Wikipedia: http://en.wikipedia.org/wiki/NTFS_symbolic_link – Eric Mar 15 '11 at 19:37
  • Ah, that's indeed like an NTFS junction point. Didn't know there was a difference. Tx. – Abel Mar 16 '11 at 00:21
  • Hi, I like this idea as app_offline doesn't work for me and the accepted answer seems too complex. Has anyone tried this in practice? I would worry about any implications of suddenly hard-switching a symbolic link while the web app is running. – cbp Apr 14 '14 at 09:34
0

In our case app_offline.htm was not working until we commented out the section of our web.config page. With it uncommented it would redirect to the error page we had defined instead of the app_offline.htm as expected.

Off The Gold
  • 1,228
  • 15
  • 28
0

old post, I know, but I didn't see this one yet:

  1. Create a new site with app_offline.htm.
  2. Add app_offline.html to site that is being updated.
  3. Remove binding from site that is being updated.
  4. Add binding to the appOffline site.
  5. Add special binding to target site (using port # or some other vanity url, do ip filtering or whatever else you need.)
  6. Do validation on target site.
  7. Restore binding from appOffline to target site.
philn5d
  • 636
  • 7
  • 12
  • This sounds interesting, but can you explain in your post what you mean by (special) binding? The word has too many meanings... – Abel Nov 30 '15 at 15:55
  • The (special) bindings is for a backdoor or perhaps something like "test.example.com". Perhaps for a specific use case, you only want certain ip addresses to access it, so ip filtering. Or add a binding on a specific port of the server. It's basically for validation of the target site. – philn5d Feb 07 '17 at 19:37
  • I see. Note that iis does not allow multiple bindings on same port and address and that you would also have to move the certificates and relevant 443 bindings. When automated, this is a possible workaround, though the same issues with app_offline.htm remain. The advantage would be that you could fix them on a specific fallback site and use the swap trick you explain here. – Abel Feb 07 '17 at 19:57
  • Really depends if this works for the specific scenario, consider - if iis binding is for specific ip address or if specific url, is the cert a wildcard cert or bound specifically, are the sites on the same server or multiple, is there a load balancer, is there a proxy. Automating would be quicker...appcmd is good for that or powershell. – philn5d Feb 07 '17 at 20:07
  • That's indeed precisely my point. And any reasonably involved website configuration may have all of the above (including the site this question was originally asked for, which runs in a double ARR load balanced configuration with EV certificates which cannot use wild cards). All in all you're effectively rewriting what app_offline.htm was for in the first place, and I understand that :). – Abel Feb 07 '17 at 20:13
0

I don't think app_offline.htm was intended for production use.

My solution would be to create a separate web application with a module that catches all requests and redirects them to a static .htm page with a query string of the requested site and some javascript to retry the original request.

When you're ready to do maintenance, setup the dummy application to handle all requests to your domain. Use a different port to or temporary domain while you're doing your maintenance so that you can test. Once you're done, switch them back and users who decided to wait around should be redirected to their originally requested page.

I've only done half of this before (switching application ports to turn on the updated site) so there may be other steps involved to get the desired user experience.

Hope this helps.

agradl
  • 3,536
  • 2
  • 18
  • 16
  • 7
    I think whoever at MS responded on that connect question didn't quite know what they were talking about. MSBuild and Publish and Deploy both use app_offline.htm when publishing a web app to a server. This thing is pretty well ingrained in MS's production publishing model – NotMe Mar 14 '11 at 20:36
  • Your solution is indeed one that could work, it's been in my mind for a while. Not sure what you mean about "not intended for production use". Microsoft [announced it in 2005 as a feature](http://msdn.microsoft.com/en-us/library/baf8bxh4%28v=vs.80%29.aspx) for publishing websites. Sounds to me it was intended for just that: publishing websites, including, or esp. production. – Abel Mar 14 '11 at 23:56
  • I thought it wasn't intended for production use. The only instances I've seen it was during local development. I wasn't aware it was used for publishing as Chris pointed out. At this point its safe to disregard that part of my post – agradl Mar 15 '11 at 13:09
  • Well, actually, in any situation that's _not_ production, I don't really care that testers temporarily see an error. The advantage of still using app_offline.htm is to bring the site down and releasing all references (otherwise you cannot update). Without app_offline.htm it is hard to bring the site down without showing your end-users an error (which happens when you stop the website in IIS). – Abel Mar 15 '11 at 17:44