lunes, 15 de octubre de 2012

Los archivos de configuracion en .Net

A pesar de que usted ha estado usando ASP.NET durante un tiempo, ¿cuánto realmente sabemos acerca de los archivos de configuración de ASP.NET? Mientras que usted probablemente ha tocado el archivo Web.config de vez en cuando, hay algunos matices que intervienen en la configuración de ASP.NET que puede no haber notado. En este articulo voy a discutir la arquitectura detrás de los archivos de configuración de ASP.NET y de mostrar cómo los cambios en la configuración afecta a los programas en ejecución. También voy a cubrir varias formas de agregar sus propios ajustes de configuración personalizados, incluyendo cómo implementar un ensamblado independiente para el manejo de opciones de configuración personalizadas para su aplicación.

Machine.config

Al instalar el Microsoft ®. NET Framework, un archivo XML denominado Machine.config se instala en la carpeta \ Windows \ Microsoft.Net \ Framework \ xxx \ config (donde xxx es la versión del Framework). Machine.config contiene los ajustes por defecto para su instalación y establece los parámetros para saber cómo. NET se ejecutara en toda la máquina.
Al navegar a través Machine.config, usted encontrará los nodos para todo tipo de ajustes de la máquina. Verás <system.net>, <system.diagnostic> y <system.runtime.remoting>, entre otros. Como se puede adivinar, <system.diagnostic> incluye la configuración de la gestión de la conducta de diagnóstico de los mensajes de seguimiento del uso de la instalación y los listeners que se gestionan en su máquina. El grupo de la sección <system.runtime.remoting> incluye la configuración de la gestión de como se comporta de forma remota en su máquina. Estos ajustes incluyen artículos tales como los componentes que se utilizan para gestionar los canales.
El grupo de la sección que queremos ver es <system.web>, que incluye la configuración que le indican al sistema ASP.NET como se debe ejecutar en su máquina. El nodo <system.web> contiene otras secciones y grupos de secciones. Cerca de la parte superior de Web.config se encuentran los grupos dentro de la sección <system.web>. Por ejemplo, la Figura 1 se muestran las secciones que definen las capacidades del navegador, los objetivos del cliente, las opciones de compilación y procesamiento de la página de valores. Tenga en cuenta que estos no son los parámetros de configuración actuales (ya llegaremos a eso más tarde). Estos elementos sólo establecen una sección dentro del archivo de configuración para un ensamblado específico y el tipo que analiza las opciones de configuración y las interpreta en tiempo de ejecución.

Figura 1 system.web
<sectionGroup name="system.web">
  <section name="browserCaps" type=
     "System.Web.Configuration.HttpCapabilitiesSectionHandler,
        System.Web, Version=1.0.5000.0, Culture=neutral,
        PublicKeyToken=b03f5f7f11d50a3a"/>
  <section name="clientTarget" type=
     "System.Web.Configuration.ClientTargetSectionHandler,
        System.Web, Version=1.0.5000.0, Culture=neutral,
        PublicKeyToken=b03f5f7f11d50a3a"/>
  <section name="compilation"
     type="System.Web.UI.CompilationConfigurationHandler,
        System.Web, Version=1.0.5000.0, Culture=neutral,
        PublicKeyToken=b03f5f7f11d50a3a"/>
  <section name="pages"
     type="System.Web.UI.PagesConfigurationHandler,
        System.Web, Version=1.0.5000.0, Culture=neutral,
        PublicKeyToken=b03f5f7f11d50a3a"/>
•••


Los ajustes <system.web> aparecen unas cuantas páginas más bajo en el archivo. Allí encontrará todas las diversas maneras en que puede configurar elementos tales como el estado de sesión, la autenticación, la compilación de la página, y la configuración de depuración. Por ejemplo, el elemento <sessionState> incluye valores para la definición de cómo se gestiona el estado de sesión (deshabilitado, almacenado en la memoria del proceso en curso, almacenados en SQL Server ™, o almacenado en un servidor de estado de ASP.NET en un equipo específico). Aquí están los ajustes por defecto para el estado de sesión que se define en una instalación nueva. NET:

<sessionState mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="10" sqlConnectionString=
"data source=127.0.0.1;Integrated Security=SSPI"
cookieless="false" timeout="20"/>



Regrese a la parte superior del Machine.config y verá lo siguiente en el grupo de la sección <system.web>:

<section name="sessionState"
 type=
 "System.Web.SessionState.SessionStateSectionHandler,
 System.Web, Version=1.0.5000.0, Culture=neutral,
 PublicKeyToken=b03f5f7f11d50a3a"
 allowDefinition="MachineToApplication" />



Esta línea en Machine.config le dice a ASP.NET que utilize una clase llamada SessionStateSectionHandler en el ensamblado System.Web.dll para administrar el estado. Cuando se carga ASP.NET, una clase necesita para interpretar el elemento de estado de sesión, y SessionStateSectionHandler es la clase que va a hacer eso.

Como se puede ver en el código, Machine.config se especifica que el estado de sesión deben ser manejado  in-process. Para la mayoría, un solo servidor de aplicaciones o para granjas de servidores web que mantienen la afinidad de la máquina cuando se utiliza el equilibrio de carga, "InProc" estado de sesión funciona muy bien. Sin embargo, para una granja de servidores Web es probable que desee almacenar el estado de sesión en otro lugar (por ejemplo, en un equipo que ejecuta SQL Server). Si cambia la configuración del estado de sesión para utilizar SQL Server en el archivo Machine.config, a continuación, todas las aplicaciones de la máquina utilizaran SQL Server. Por supuesto, usted probablemente querrá controlar el estado de sesión en cada aplicación. Es por eso que las aplicaciones ASP.NET individuales incluyen un archivo Web.config.

Web.config

Los archivos Web.config modifican la configuración predeterminada estipulada en Machine.config. Si usted hace una búsqueda de Web.config, usted encontrará un buen número en su máquina. Puede haber un archivo Web.config en la carpeta \ inetpub \ wwwroot que controla la configuración de <system.web> para todo el sitio. Luego hay un archivo Web.config en el directorio virtual de la aplicación. Además, cada subdirectorio bajo el directorio virtual de una aplicación puede tener un archivo Web.config.
Machine.config define la configuración predeterminada de la máquina. Después de eso, ASP.NET busca el archivo Web.config en el directorio \ inetpub \ wwwroot para los ajustes. Por último, ASP.NET busca de los archivos Web.config en el directorio de la aplicación virtual y sus subdirectorios de cambiar la configuración. En el momento en ASP.NET llega a los valores establecidos por una hoja de subdirectorio de su aplicación, es concebible (aunque poco probable) que el archivo Web.config pueda haber cambiado por completo la configuración predeterminada.

A continuación se muestra cómo la configuración dentro de los archivos Web.config se aplican a una aplicación. ASP.NET, lee los archivos de configuración y realiza los cambios en este orden:

Machine.config (establece los valores por defecto de la máquina)
\ Inetpub \ wwwroot \ web.config (modifica la configuración para el sitio principal)
appvirtualdir \ Web.config (modifica la configuración de esta aplicación)
appvirtualdir \ subdir \ Web.config (modifica la configuración de este subdirectorio)
Los valores se modifican de una manera jerárquica, donde cada subdirectorio tiene la oportunidad de modificar los ajustes previamente estipulados que se encuentran en cada archivo Web.config.

Si usted no tiene ganas de llenar los subdirectorios de la aplicación con los archivos Web.config, el elemento <location> le permite especificar determinados parámetros de configuración de ruta en el archivo Web.config principal. Para utilizar el elemento <location>, coloca el elemento en el archivo Web.config y especificar la ruta a la que los valores se aplican. A continuación se muestra un ejemplo:
<?xml version="1.0" ?>
<configuration>
 <location path="SubDir">
   <system.web>
       <!-- settings for "SubDir" go here... -->
   </system.web>
 </location>
</configuration>



Por supuesto, puede haber algunos ajustes que le gustaría mantener sin ser reemplazado. El elemento incluye un atributo <location> allowOverride que impide el override cuando se establece en false.

Cambio de ajustes
ASP.NET lee estos archivos de configuración cuando se inicia la aplicación. Los ajustes se guardan en la memoria, lo que garantiza un alto rendimiento. ASP.NET también vigila los archivos de configuración. Al cambiar la configuración y guardar un archivo de configuración, ASP.NET reinicia automáticamente la aplicación y vuelve a cargar la configuración actualizada en la memoria. Eso significa que el dominio de la aplicación que aloja la aplicación dentro de aspnet_wp.exe será borrado y reconstruido. Se pierde el proceso de estado cuando se guarda el archivo de configuración (como el estado de sesión que no haya sido descargado para un servidor de estado).
Si bien hay un buen número de ajustes por defecto en ASP.NET, a menudo es útil crear su propia configuración. Por ejemplo, es una mala práctica para codificar los datos sensibles y maleables, tales como cadenas de conexión de base de datos, directamente en su aplicación. ¿Qué sucede cuando un administrador de base de datos cambia la cadena de conexión (por ejemplo, la contraseña de acceso)? Usted recibirá una llamada de teléfono, porque la aplicación no funciona, por lo general estando en su casa, en medio de la noche o en fin de semana! Y entonces usted necesita cambiar su código fuente, recompilar y volver a implementar la aplicación.
Así, en lugar de codificar, tiene sentido utilizar un archivo de configuración. De esta forma, los administradores de sistemas se les llama en el medio de la noche para cambiar la configuración (y te puedes quedar en la cama). Echemos un vistazo a algunas de las formas de almacenar y recuperar la configuración utilizando el archivo Web.config.

Uso de la Sección <appSettings>
Si sólo tiene un valor simple que desea almacenar en el archivo Web.config, el lugar más conveniente de hacerlo es en el nodo <appSettings>. El nodo <appSettings> cae dentro del elemento <configuration>, pero fuera del elemento <system.web>, como se muestra en la Figura 2. Tenga en cuenta que la sintaxis <appSettings> incluye el verbo "add" que instruye el componente NameValueFileSectionHandler para añadir pares clave / valor a una colección. La figura 2 también muestra cómo recuperar las llaves durante el evento Page_Load, así como la forma de recuperar los valores reales en respuesta a un clic de botón.
  
Figura 2 Recuperación de la configuración de la aplicación
Web.config
<configuration>
 <appSettings>
   <add key="ConnectionString" value="Value for ConnectionString"/>
   <add key="Other appSetting" value="Value for Other appSetting"/>
 </appSettings>

<!-- other settings-->
<system.web>
  <!--system Web settings go here... -->
</system.web>
</configuration>

Form1.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
 if(!this.IsPostBack)
 {
   DropDownListappSettingsKeys.DataSource =
       ConfigurationSettings.AppSettings.Keys;
   DropDownListappSettingsKeys.DataBind();
 }
}

private void ButtonGetValueOfAppSettingKey_Click(
 object sender, System.EventArgs e)
{
 string strKey = DropDownListappSettingsKeys.SelectedItem.Text;
 string strValueOfKey = ConfigurationSettings.AppSettings[strKey];
 LabelValueOfappSettingsKey.Text = strValueOfKey;
}



Usando NameValueFileSectionHandler
La mayoría de los ajustes de configuración tienden a ser pares nombre / valor (como en el ejemplo anterior). La sección <appSettings> está built in, y se puede fácilmente acceder a los parámetros de configuración en tiempo de ejecución. Sin embargo, hay casos en los que es posible que desee aislar un conjunto de opciones de configuración o de otra manera definirlo por separado. Por ejemplo, las aplicaciones de su dominio pueden tener alguna información de configuración especial que desea incluir en un grupo separado con nombre (que no es, en appSettings).
La forma más sencilla de hacer esto es configurar su propia sección con nombre, puede utilizar el componente NameValueSectionHandler existente para analizar y construir una colección de clave / valor que se puede acceder en tiempo de ejecución. La Figura 3 muestra cómo definir un grupo de configuración independiente para ser analizado por ASP.NET. Observe cómo el Web.config de la aplicación añade una <sectionGroup> y un <section> designado hasta el elemento <configSections> y le dice a ASP.NET para que utilice el componente NameValueSectionHandler para parcearlo. System.dll, el cual contiene el tipo de NameValueSectionHandler, es un assamblie del sistema, por lo que necesita usar el nombre completo del asamblie con el fin de especificar el handle.

   Figura 3 Definición de un grupo de configuración independiente

Web.config
<configuration>
<configSections>
 <sectionGroup name="system.web">
  <section name="customSection"
   type="System.Configuration.NameValueSectionHandler,
   System, Version=1.0.5000.0, Culture=neutral,
   PublicKeyToken=b77a5c561934e089"/>
</configSections>

<customSection>
 <add key="customSection Setting 1"
  value="Value for customSection Setting 1"/>
 <add key=" customSection Setting 2"
  value="Value for customSection Setting 2"/>
</customSection>

</configuration>

Form1.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
 if(!this.IsPostBack)
 {
   NameValueCollection nvccustomSection;
   nvccustomSection = (NameValueCollection)
     ConfigurationSettings.GetConfig("customSection");
   DropDownListcustomSectionKeys.DataSource = nvccustomSection.Keys;
   DropDownListcustomSectionKeys.DataBind();
 }
}

private void ButtonGetValueOfcustomSectionKey_Click(
 object sender, System.EventArgs e)
{
 string strKey = DropDownListcustomSectionKeys.SelectedItem.Text;

 NameValueCollection nvccustomSection;
 nvccustomSection = (NameValueCollection)
   ConfigurationSettings.GetConfig("customSection");

 string strValueOfKey = nvccustomSection[strKey];
 LabelValueOfcustomSectionKey.Text = strValueOfKey;        
}



Secciones de configuración personalizadas
Si usted decide que simples pares nombre / valor no son lo suficientemente bueno para los ajustes de configuración de la aplicación, usted puede escribir su propia sección de configuración de los componentes del controlador. Por ejemplo, si usted desea utilizar sus propios esquemas XML en una sección del archivo de configuración, tendrá acceso a los datos XML directamente desde el archivo de configuración. Interpretar el código XML directamente a usted le da medio para comprobar la sintaxis de configuración y tal vez una excepción si hay un problema.
Escribir un componente para leer las secciones del archivo de configuración es bastante sencilla. Sólo tiene que escribir una clase que deriva de IConfigurationSectionHandler y luego hacer referencia a ella en el archivo Web.config propia. La interfaz IConfigurationSectionHandler se muestra en las siguientes líneas de código:


public interface IConfigurationSectionHandler
{
 object Create(object parent, object input, XmlNode node);
}


IConfigurationSectionHandler contiene un solo método: Crear. El único propósito de crear es analizar la sección de configuración. Crear toma tres parámetros: dos objetos (los padres y de entrada) y XMLNode. El primer parámetro, el padre, representa los valores de configuración en una configuración de matriz correspondiente sección, es decir, la información de configuración que se ha leído en ya. El segundo objeto, de entrada, representa un HttpConfigurationContext. No hay mucho que HttpConfigurationContext, sólo la ruta de acceso virtual al archivo de configuración Web.config. Posiblemente, se podría utilizar la ruta para abrir el archivo Web.config directamente. Sin embargo, el tercer parámetro, llamado nodo, representa el XmlNode que contiene la información de configuración del archivo de configuración. Así es como se puede tener acceso directo al contenido XML de la sección de configuración.
La figura 4 muestra una aplicación de IConfigurationSectionHandler utilizado en la muestra de este mes. El controlador de configuración personalizada se configura un componente de registro de las solicitudes de registro de la solicitud. La clase CustomConfigSettings contiene las variables (una cadena para almacenar un nombre de archivo de registro y un valor booleano para almacenar o el registro no se debe hacer). La clase CustomConfigHandler se utiliza la infraestructura de ASP.NET para analizar la sección de configuración personalizada y el escenario con el resto de la aplicación.


   Figura 4 Analizador de configuración personalizada


public class CustomConfigSettings
{
 private string _strlogfilename;
 private bool _bLogRequests;
       
 public CustomConfigSettings(string strlogfilename, bool bLogRequests)
 {
   _strlogfilename = strlogfilename;
   _bLogRequests = bLogRequests;
 }

 public string LogFileName
 {
   get { return _strlogfilename; }
 }

 public bool LogRequests
 {
   get { return _bLogRequests; }
 }
}

public class CustomConfigHandler : IConfigurationSectionHandler
{
 public virtual object Create(object parent, object input, XmlNode node)
 {
   XmlNode n = node.Attributes.RemoveNamedItem("LogRequests");
   if(n == null)
   {
     throw new ConfigurationException("Attribute expected: LogRequests");
   }

   bool bLogRequests;
   if(string.Compare(n.Value, "TRUE", true) == 0)
   {
     bLogRequests = true;
     // Set up the request logger here...
   }
   else bLogRequests = false;

   n = node.Attributes.RemoveNamedItem("LogFileName");
   if(n == null)
   {
     throw new ConfigurationException("Attribute expected: LogFileName");
   }

   return new CustomConfigSettings(n.Value, bLogRequests);
 }
}



Al analizar el fichero de configuración, la clase CustomConfigurationHandler espera ver un elemento que contiene dos atributos: LogFileName y LogRequests, en representación de si debe o no hacer el registro. La figura 5 muestra cómo el controlador de la sección de configuración hace referencia en Web.config. Tenga en cuenta que Web.config define una nueva sección, llamada <customConfigHandling>, y especifica el CustomConfigHandler como la clase para analizar la información de configuración de esa sección. A continuación, el nodo <system.web> incluye un elemento para el registro de configuración.
   
Figura 5 controlador de configuración personalizada
<configuration>
<configSections>
 <sectionGroup name="system.web">
  <section name="customConfigHandling"
        type="CustomConfigHandling.CustomConfigHandler,
        CustomConfigHandlerLib"/>
  </sectionGroup>
</configSections>

<system.web>
 <customConfigHandling LogRequests="true"
   LogFileName="c:\requestlog.txt"/>
</system.web>



CustomConfigHandler.Create es llamado por el sistema para analizar la información de configuración. ASP.NET entrega la información de configuración que ya se ha reunido (el primer parámetro) y un XmlNode que representa el elemento que va a ser analizada con el método Create.
Como con todos los otros datos de configuración, usted puede recoger los valores de configuración personalizados en tiempo de ejecución. El siguiente código muestra cómo obtener acceso a la información de configuración personalizada durante un evento Page_Load.

private void Page_Load(object sender, System.EventArgs e)
{
 CustomConfigSettings customConfigSettings;
 customConfigSettings = (CustomConfigSettings)
   ConfigurationSettings.GetConfig("system.web/customConfigHandling");
 if(customConfigSettings != null)
 {
   LabelLogFileName.Text = customConfigSettings.LogFileName;
   LabelLogRequests.Text = customConfigSettings.LogRequests.ToString();
 }
}



Tenga en cuenta que el objeto devuelto por GetConfig es una instancia de CustomConfigSettings.

Conclusión
ASP.NET ofrece varias formas de agregar su propia configuración, e incluso le permite escribir su propio controlador de sección de configuración. Aunque sólo he arañado la superficie, ya verás cuando te sumerjas más profundo que el sistema de configuración es extensible y suficientemente flexible como para hacer casi cualquier cosa que te gustaría que hiciera.