Taking an ASP.NET Web Application Offline

by Chad Green 4. April 2009 14:40

Simple Answer

There are times you need to take an ASP.NET web application offline.  In general, the way to do so is place an App_Offline.htm file into the root of the web application.  The ASP.NET application looks for that with every request, if it see it then it will display that page vice the requested page.

My Problem

The one problem I have with this is that due to security at work, I need a system administrator to touch the web servers outside of the development network (even as the project lead, I’m not allowed to touch the production server).  Last week we had issues with the system due to some maintenance done on the database.  I wasn’t able to get a hold of the DBA to fix that problem and the on-call web administrator was not acting promptly enough to upload an App_Offline page I provided them.

So, for about five hours people were getting errors as soon as they logged into the system.  And wouldn’t you know this was a weekend that a lot of people decided to try to get things done.  Normally, almost nobody goes into the system during the weekend.

My Solution

With the events of last weekend, I decided that I needed to find a way to take the application offline for such problems without having to get the system administrator involved.  I did a lot of searching around the web and almost everything simply talked about the App_Offline solution.  The idea I came up with was to use a flag in the HTTP Application State to indicate whether the application was offline or not.  Then I would have the Application_BeginRequest event look at that, if the application was offline then direct to a page that told the user that the application was offline.  I describe this solution in detail below.

I would assume that you would add this solution to an existing web application, but for the purpose of this blog entry, I have created a new ASP.NET Web Application that I have called “ApplicationOfflineExample.”

ApplicationStateHelper Class

The first thing you will want to do with your application is add the ApplicationStateHelper class described below.  The purpose of this class is to provide helper methods for accessing the variables stored in the HTTP Application State.  The code for this class is as such:

Public NotInheritable Class ApplicationStateHelper  ''' <summary>  ''' Gets or sets a value indicating whether the application is offline.  ''' </summary>  ''' <value><c>True</c> if the application is offline; otherwise, <c>False</c>.</value>  ''' <revisions>  '''   <revision date="4/4/2009" author="CEG" version="1.00.00.000">Initial Development</revision>  ''' </revisions>  Public Shared Property ApplicationOffline() As Boolean    Get      If IsNothing(HttpContext.Current.Application.Item("ApplicationOffline")) = True _OrElse TypeOf HttpContext.Current.Application.Item("ApplicationOffline") Is Boolean = False Then        HttpContext.Current.Application.Add("ApplicationOffline", False)      End If      Return DirectCast(HttpContext.Current.Application.Item("ApplicationOffline"), Boolean)    End Get    Set(ByVal value As Boolean)      If IsNothing(HttpContext.Current.Application.Item("ApplicationOffline")) Then        HttpContext.Current.Application.Add("ApplicationOffline", value)      Else        HttpContext.Current.Application.Item("ApplicationOffline") = value      End If    End Set  End Property  ''' <summary>  ''' Gets or sets the application offline message.  ''' </summary>  ''' <value>The application offline message.</value>  ''' <revisions>  '''   <revision date="4/4/2009" author="Chad Green" version="1.00.00.000">Initial Development</revision>  ''' </revisions>  Public Shared Property ApplicationOfflineMessage() As String    Get      If IsNothing(HttpContext.Current.Application.Item("ApplicationOfflineMessage")) = True _OrElse TypeOf HttpContext.Current.Application.Item("ApplicationOfflineMessage") Is String = False Then        HttpContext.Current.Application.Add("ApplicationOfflineMessage", _"Application offline.  Try again later.")      End If      Return DirectCast(HttpContext.Current.Application.Item("ApplicationOfflineMessage"), String)    End Get    Set(ByVal value As String)      If IsNothing(HttpContext.Current.Application.Item("ApplicationOfflineMessage")) Then        HttpContext.Current.Application.Add("ApplicationOfflineMessage", value)      Else        HttpContext.Current.Application.Item("ApplicationOfflineMessage") = value      End If    End Set  End PropertyEnd Class

As you can see, we have two shared (static) property values.  The first one, ApplicationOffline, is a flag that indicates whether the application is offline or not.  The second, ApplicationOfflineMessage, stores the message that will be displayed to users when the application is offline.  The properties values are shared in order to provide quicker and easier access to the values throughout the web application.

Site Administration Web Page

In order to be able to set the offline status of the web application, I have added a web page, SiteAdministration.aspx, that provides the necessary capability.  The page contains several elements, including an indication as to the application’s offline status, a text box to specify the message displayed when the application is offline, and a button to switch the application offline status.  I have also added a Return Home link to make using this demo easier.

<html xmlns="http://www.w3.org/1999/xhtml" >  <head id="Head1" runat="server">    <title>Site Administration</title>  </head>  <body>    <form id="frmSiteAdministration" runat="server">      <p>The purpose of this page is to provide administration of the site.</p>      <hr />      <h1>Site Status</h1>      <p>The site is currently <asp:Label ID="lblSiteStatus"runat="server"Text="Online"Font-Bold="true"ForeColor="Black" />.</p>            <p>Offline Message: <asp:TextBox ID="txtOfflineMessage"runat="server"TextMode="MultiLine"Rows="5"Width="300" /></p>      <p><asp:Button ID="btnChangeSiteStatus" runat="server" Text="Take Site Offline" /></p>      <hr />      <p><a href="Default.aspx">Return Home</a></p>    </form>  </body></html>

In the code behind we have the following procedures.

Private Sub PrepareSiteStatusSection()    If ApplicationStateHelper.ApplicationOffline Then        lblSiteStatus.Text = "Offline"        lblSiteStatus.ForeColor = Drawing.Color.Red        btnChangeSiteStatus.Text = "Bring Site Back Online"    Else        lblSiteStatus.Text = "Online"        lblSiteStatus.ForeColor = Drawing.Color.Black        btnChangeSiteStatus.Text = "Take Site Offline"    End If    txtOfflineMessage.Text = ApplicationStateHelper.ApplicationOfflineMessageEnd Sub

The PrepareSiteStatusSection takes the application offline status information and populates the appropriate details on the page.  This method is used later when updating the page.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load    If Not Page.IsPostBack Then        PrepareSiteStatusSection()    End IfEnd Sub

Then we have the Page_Load method.  The only thing we are doing here is calling the PrepareSiteStatusSection method to populate Site Status section of the page.

Private Sub btnChangeSiteStatus_Click(ByVal sender As Object, _ByVal e As System.EventArgs) Handles btnChangeSiteStatus.Click  ApplicationStateHelper.ApplicationOffline = Not ApplicationStateHelper.ApplicationOffline  ApplicationStateHelper.ApplicationOfflineMessage = txtOfflineMessage.Text  PrepareSiteStatusSection()End Sub

Finally we have the button click event handler code that will either take the application offline or back online.

Application Offline Web Page

Next, we add a web page that will be used to inform users that the application is offline.

<html xmlns="http://www.w3.org/1999/xhtml" >  <head id="Head1" runat="server">    <title>Application Offline</title>  </head>  <body>    <form id="frmApplicationOffline" runat="server">      <asp:Label ID="lblOfflineMessage" runat="server" />    </form>  </body></html>

As you can see, this page is very simple and just includes a label that we’ll populate in the page’s load event seen below.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load  If Not Page.IsPostBack Then    lblOfflineMessage.Text = ApplicationStateHelper.ApplicationOfflineMessage  End IfEnd Sub

Global Application Class

Finally, we need to modify the Application_BeginRequest method in the Global Application Class (Global.asax).  If your application does not have such, make sure to add it now.  Then you want to add the If clause shown below to the Application_BeginRequest method.

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)  If Request.Path <> "/SiteAdministration.aspx" AndAlso _Request.Path <> "/ApplicationOffline.aspx" Then    If ApplicationStateHelper.ApplicationOffline Then      Response.Redirect("ApplicationOffline.aspx")    End If  End IfEnd Sub

First thing we do is ensure that the application is not serving up the SiteAdminsitration or ApplicationOffline pages.  Obviously we want those to continue to work.  Next we are looking at the ApplicationOffline variable from the ApplicationStateHelper.  If it is set to the True, then we redirect to the ApplicationOffline page.

Results

Now, if you run the application everything will work.  Once you go to the Site Administration page and click the Take Site Offline button, users will no longer be able to access the application web pages other than the Site Administration page (which you would use some type of authorization method to only allow authorized users to the page).

The only caveat I have found so far is that if your application gets restarted for any reason, the offline flag will return to false allowing users to access the whole application.

Download Example Solution Here

 

kick it on DotNetKicks.com

Tags:

Comments

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

TextBox

Tag cloud