Una de las opciones que todo aplicación debería tener es el poder ponerse en modo OFFLINE para evitar el acceso de usuarios. Esto es completamente necesario cuando queremos realizar cambios a nuestra aplicación (cambiar algo, poner una actualización, etc) o a nuestra base de datos y evitarnos problemas con los usuarios que se encuentren logueados dentro de la aplicación en ese momento.

Muchos ejemplos a través de la Web exponen la forma de realizar esta tarea utilizando dos técnicas:

1. La primera de ellas es utilizar el archivo App_Offline.htm sin embargo, esta técnica tiene un inconveniente. Y es que, una vez que hemos subido el archivo a nuestra aplicación esta se bloquea completamente y no tenemos forma de volver a ponerla ONLINE a menos que eliminemos el archivo. Es decir no podemos controlarla.

2. La segunda de ellas es el utilizar la etiqueta httpRuntime, pero nuevamente tenemos el mismo problema. Al habilitar el modo OFFLINE mediante esta etiqueta, tampoco podremos acceder a un modo de administración para cambiarla.

Un ejemplo de la etiqueta httpRuntime

<configuration>
   <system.web>    
<httpRuntime enable="false" />
   </system.web>
</configuration> 

 

Tomando en cuenta lo anterior, lo mas optimo seria que podamos por medio de alguna pagina de administración colocar nuestro sitio en modo OFFLINE, pero manteniendo el acceso a la pagina de administración para poder volver a cambiar el valor que pondrá nuestra aplicación nuevamente en modo ONLINE.

Para ello, utilizaremos el web.config de nuestra aplicación y una pequeña clase que se encargara de Leer y escribir los valores.

Lo primero será, abrir nuestro web.config y definir dentro del appSettings dos nuevas KEY que contendrán los valores para el modo OFFLINE de nuestra aplicación:

<appSettings>
    <add key="IsOffline" value="false" />
    <add key="IsOfflineMessage" value="Sistema temporalmente no disponible por tareas de mantenimiento." />
  </appSettings>

 

En las KEY anteriores tenemos el IsOffLine con value de false, esto es para indicarle a nuestra aplicación que actualmente su modo de funcionamiento es ONLINE, este valor será el que posteriormente cambiemos a TRUE para volver al modo OFFLINE.

Nuestra segunda KEY (IsOfflineMessage) posee el value (Sistema temporalmente….) que será mostrado al usuario como un mensaje cuando el sitio este en modo OFFLINE.

Una vez definidas nuestras dos KEY en el web.config, escribiremos una clase personalizada para leer y escribir los valores. Así que, agregamos un nuevo elemento de tipo clase al proyecto llamado SettingsRules y la definimos como Public.

Está clase contendrá dos métodos, el primero será para leer los valores:

public string readIsOnlineSettings(string sectionToRead)
   {
       Configuration cfg = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
       KeyValueConfigurationElement isOnlineSettings = (KeyValueConfigurationElement)cfg.AppSettings.Settings[sectionToRead];
       return isOnlineSettings.Value;
   }

 

El segundo método, será el encargado de escribir los nuevos valores al web.config

public bool saveIsOnlineSettings(string sectionToWrite, string value)
   {
       bool succesFullySaved;
 
       try
       {
           Configuration cfg = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
           KeyValueConfigurationElement repositorySettings = (KeyValueConfigurationElement)cfg.AppSettings.Settings[sectionToWrite];
 
           if (repositorySettings != null)
           {
               repositorySettings.Value = value;
               cfg.Save(ConfigurationSaveMode.Modified);
           }
           succesFullySaved = true;
       }
       catch (Exception)
       {
           succesFullySaved = false;
       }
       return succesFullySaved;
   }

 

Por último, definiremos en nuestra clase una región llamada instance, que contendrá un método encargado de devolver una instancia de la clase (esto para no tener que hacerlo luego)

#region instance
 
   private static SettingsRules m_instance;
 
   // Properties
   public static SettingsRules Instance
   {
       get
       {
           if (m_instance == null)
           {
               m_instance = new SettingsRules();
           }
           return m_instance;
       }
   }
 
   #endregion instance
 
Con esto, nuestra clase principal esta completa. Así que pasaremos a la implementación de las páginas y el resto de código que completará la funcionalidad.
 
Para complementar la tarea del web.config utilizaremos el fabuloso GLOBAL.ASAX, este contendrá el código encargado de detectar si nuestra aplicación tiene el valor de ONLINE o OFFLINE y además de bloquear todas las paginas y directorios excepto el que le hayamos definido como administrador, esto para luego poder volver a configurar el sitio.
 
El evento del Global.Asax que utilizaremos será el Application_BeginRequest
 
protected void Application_BeginRequest(Object sender, EventArgs e)
    {
 
        if (Convert.ToBoolean(SettingsRules.Instance.readIsOnlineSettings("IsOffline")))
        {
 
            string Virtual = Request.Path.Substring(0, Request.Path.LastIndexOf("/") + 1);
            
 
            if (Virtual.ToLower().IndexOf("/admin/") == -1)
            {
                //We don't makes action, is admin section
                Server.Transfer("~/TemporarilyOfflineMessage.aspx");
            }
 
        }
    }

La primer Línea del IF, verifica si el atributo del web.config es True o False, si es true toma la dirección WEB que se ha solicitado y la incluimos en un IF para verificar si corresponde a la Sección admin (está sección no es mas que un folder en nuestra aplicación llamado admin y puede ser cambiado a cualquier otro).

Si el resultado de ese if es –1 quiere decir que no coincide, entonces, esa será la bandera que nos permitirá bloquear inmediatamente la pagina actual, transfiriendo al usuario a una pagina de mantenimiento.

Ahora, en nuestra carpeta Admin crearemos una nueva pagina asp.net llamada OnlineSettings.aspx para actualizar y leer los datos del web.config y una pagina Default.aspx para pruebas.

Nuestra página OnlineSettings tendrá dos pasos importantes:

1. Leer los datos actuales de configuración

protected void Page_Load(object sender, EventArgs e)
   {
       if (!IsPostBack)
       {
           IsOffline.Checked = Convert.ToBoolean(mySettings.readIsOnlineSettings("IsOffline"));
           OfflineMessage.Text = mySettings.readIsOnlineSettings("IsOfflineMessage");
       }
   }

 

2. Actualizar los datos con los nuevos valores.

protected void UpdateButton_Click(object sender, EventArgs e)
    {
        string htmlMessage = OfflineMessage.Text.Replace(Environment.NewLine, "<br />");
 
        // Update the Application variables
        Application.Lock();
        if (IsOffline.Checked)
        {
            mySettings.saveIsOnlineSettings("IsOffline", "True");
            mySettings.saveIsOnlineSettings("IsOfflineMessage", htmlMessage);
        }
        else
        {
            mySettings.saveIsOnlineSettings("IsOffline", "false");
            mySettings.saveIsOnlineSettings("IsOfflineMessage", htmlMessage);
        }
 
        Application.UnLock();
    }

 

Por último en la raíz de la aplicación, crearemos una nueva página aspx llamada TemporarilyOfflineMessage.aspx que será la que se muestre cuando se bloquee la aplicación.

Al final nuestra aplicación se vería algo así

Página bloqueada

Configuración del Bloqueo

Y para terminar la aplicación de ejemplo