Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
de Saad Ladki
Resumen
En este artículo se muestra cómo se puede acceder a las secciones de configuración de los archivos de configuración de IIS (applicationHost.config y web.config) mediante programación mediante las API de Microsoft.Web.Administration. Se ocupa de secciones más complejas que contienen elementos y colecciones anidados. Hay ejemplos que usan las secciones de configuración de IIS reales definidas en el archivo IIS_schema.xml. En este artículo se muestra cómo se puede acceder a estas secciones y manipularlas de forma genérica mediante las clases base proporcionadas por Microsoft.Web.Administration y también mediante clases fuertemente tipadas para representar estas secciones.
Introducción
En este artículo se proporcionan ejemplos de acceso mediante programación a las secciones de configuración de IIS mediante las API Microsoft.Web.Administration. Esto se refiere a secciones que contienen elementos anidados (system.webServer/asp) y colecciones (system.webServer/security/isapiCgiRestriction). En la primera sección se muestra cómo se pueden manipular estas secciones mediante las clases base genéricas proporcionadas por Microsoft.Web.Administration y la segunda sección se proporcionan ejemplos de cómo se usan las clases contenedoras fuertemente tipadas que representan estas secciones.
Esquema para secciones con elementos y colecciones anidados
Secciones con elementos anidados
Un ejemplo de una sección que tiene elementos anidados es la sección system.webServer/asp. El elemento "session" se define dentro de la sección "asp". El esquema de esta sección es como se muestra a continuación. Hay otras propiedades en el esquema y otros elementos anidados que no se muestran en el ejemplo.
<sectionSchema name="system.webServer/asp">
<attribute name="appAllowClientDebug" type="bool" defaultValue="false" />
<attribute name="appAllowDebugging" type="bool" defaultValue="false" />
<!-- Omitted to simplify -->
<element name="session">
<attribute name="allowSessionState" type="bool" defaultValue="true" />
<attribute name="keepSessionIdSecure" type="bool" defaultValue="true" />
</element>
</sectionSchema>
Secciones con una colección
Una sección que tiene una colección de elementos indexados por una clave es la sección system.webServer/security/isapiCgiRestriction. El esquema de la sección es como se muestra.
<sectionSchema name="system.webServer/security/isapiCgiRestriction">
<collection addElement="add" clearElement="clear" removeElement="remove">
<attribute name="path" type="string" expanded="true" required="true" isUniqueKey="true" validationType="nonEmptyString" />
<attribute name="allowed" type="bool" required="true" defaultValue="false" />
<attribute name="groupId" type="string" required="false" />
<attribute name="description" type="string" />
</collection>
<attribute name="notListedIsapisAllowed" type="bool" defaultValue="false" />
<attribute name="notListedCgisAllowed" type="bool" defaultValue="false" />
</sectionSchema>
Acceso genérico a las secciones
Microsoft.Web.Administration proporciona varias clases base genéricas que representan distintos componentes del sistema de configuración.
- Configuración: representa un único archivo de configuración (applicationHost.config o los archivos web.config para sitios y aplicaciones)
- ConfigurationElement: una entidad genérica que se usa para representar un elemento en un archivo de configuración. Esta es la clase base para secciones de configuración, entradas de colección, elementos anidados en una sección, etc.
- ConfigurationAttribute: representa una propiedad dentro de configurationElement
- ConfigurationSection: se deriva de ConfigurationElement y representa una sección definida en los archivos de esquema de IIS. Se usa para acceder a las distintas propiedades de una sección.
- ConfigurationElementCollection: Una clase de colección que consta de ConfigurationElements. También deriva de ConfigurationElement.
En el ejemplo siguiente se muestra cómo se puede acceder a los elementos anidados en la sección system.webServer/asp.
static void Main(string[] args) {
ServerManager serverManager = new ServerManager();
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection section = config.GetSection("system.webServer/asp");
ConfigurationElement element = section.GetChildElement("session");
Console.Write("allowSessionState attribute value: ");
Console.WriteLine(element.GetAttributeValue("allowSessionState"));
Console.WriteLine("Set allowSessionState value to false");
element.SetAttributeValue("allowSessionState", false);
Console.Write("allowSessionState attribute value: ");
Console.WriteLine(element.GetAttributeValue("allowSessionState"));
serverManager.CommitChanges();
}
La clase ServerManager es el punto de entrada para acceder a la configuración de varios servidores. Establecemos las propiedades en los archivos applicationHost.config, pero también se puede acceder a estas propiedades y cambiarlas en los archivos web.config de sitios y aplicaciones individuales. La llamada CommitChanges guarda la configuración modificada.
En el ejemplo siguiente se muestra cómo recorrer en iteración los elementos de una colección y agregarle elementos.
static void Main(string[] args) {
ServerManager serverManager = new ServerManager();
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection section =
config.GetSection("system.webServer/security/isapiCgiRestriction");
ConfigurationElementCollection collection = section.GetCollection();
// Iterating through the elements in the collection foreach (ConfigurationElement element in collection)
{
Console.Write("Path: " + element.GetAttributeValue("path"));
Console.WriteLine(" Allowed: " + element.GetAttributeValue("allowed"));
}
// Adding a new element to the collection ConfigurationElement newElement = collection.CreateElement();
newElement.SetAttributeValue("path", @"%SystemDir%\someDll.dll");
newElement.SetAttributeValue("allowed", false);
collection.Add(newElement);
serverManager.CommitChanges();
}
Clases estrictamente tipadas para acceder a las secciones
Las clases fuertemente tipadas que se derivan de las clases base genéricas pueden escribirse para que el acceso a las propiedades sea más fácil e intuitivo. Esto resulta especialmente útil cuando es posible que tenga que acceder a la misma sección muchas veces para distintas operaciones. Estas clases también garantizan que disponga de verificación en tiempo de compilación de los tipos de propiedades. Evitan las llamadas tediosas a métodos como GetChildElement y GetAttributeValue.
En el ejemplo siguiente se muestra el contenedor de la sección system.webServer/asp y el elemento "session" de esa sección. Todas las propiedades de esa sección no se incluyen en este fragmento de código.
public sealed class AspSection : ConfigurationSection {
private AspSession _session;
public AspSection()
{
}
public AspSession Session
{
get
{
if (_session == null)
{
_session = (AspSession)GetChildElement("session",
typeof(AspSession));
}
return _session;
}
}
}
public sealed class AspSession : ConfigurationElement {
public AspSession()
{
}
public bool AllowSessionState
{
get {
return (bool)base["allowSessionState"];
}
set
{
base["allowSessionState"] = value;
}
}
}
La llamada a GetChildElement del ejemplo anterior se usa para tener acceso a un elemento anidado en un elemento de configuración (una sección, un elemento de colección, etc.). Al llamar a base [...] se encapsulan las clases GetAttributeValue y SetAttributeValue, que recuperan y establecen los valores de esos atributos.
En el ejemplo siguiente se muestra cómo se puede acceder a las propiedades de un elemento anidado de forma fuertemente tipada.
static void Main(string[] args) {
ServerManager serverManager = new ServerManager();
Configuration config = serverManager.GetApplicationHostConfiguration();
AspSection section = (AspSection)config.GetSection("system.webServer/asp",
typeof(AspSection));
Console.WriteLine(section.Session.AllowSessionState);
section.Session.AllowSessionState = false;
serverManager.CommitChanges();
}
Observe la llamada a config.GetSection, que recibe una ruta de acceso de sección y también el tipo de sección que desea crear. De forma predeterminada, las llamadas a config.GetSection crean un ConfigurationSection y para obtener una instancia de un recubrimiento fuertemente tipado, debe pasar un tipo.
Este es un ejemplo de cómo crear clases fuertemente tipadas para una sección que tiene una colección. En este ejemplo se usa la sección system.webServer/security/isapiCgiRestriction. Este fragmento de código no incluye todas las propiedades presentes en esta sección.
public sealed class IsapiCgiRestrictionSection : ConfigurationSection {
private IsapiCgiRestrictionCollection _collection;
public IsapiCgiRestrictionSection() {
}
public IsapiCgiRestrictionCollection IsapiCgiRestrictions {
get {
if (_collection == null) {
_collection =
(IsapiCgiRestrictionCollection)GetCollection(typeof(IsapiCgiRestrictionCollection));
}
return _collection;
}
}
}
El método GetCollection de la clase base (ConfigurationElement) se usa para tener acceso a la colección predeterminada de ese elemento.
En el siguiente ejemplo, se muestran las clases con fuerte tipado tanto para la colección en sí como para los elementos de la colección.
public sealed class IsapiCgiRestrictionCollection : ConfigurationElementCollectionBase<IsapiCgiRestrictionElement> {
public IsapiCgiRestrictionCollection() {
}
public new IsapiCgiRestrictionElement this[string path] {
get {
for (int i = 0; i< Count; i++) {
IsapiCgiRestrictionElement restriction = base[i];
if (String.Equals=(Environment.ExpandEnvironmentVariables(restriction.Path),
Environment.ExpandEnvironmentVariables(path), StringComparison.OrdinalIgnoreCase)) {
return restriction;
}
}
return null;
}
}
public IsapiCgiRestrictionElement Add(string path, bool allowed) {
IsapiCgiRestrictionElement element = CreateElement();
element.Path = path;
element.Allowed = allowed;
return Add(element);
}
protected override IsapiCgiRestrictionElement CreateNewElement(string elementTagName) {
return new IsapiCgiRestrictionElement();
}
}
public sealed class IsapiCgiRestrictionElement : ConfigurationElement {
public IsapiCgiRestrictionElement() {
}
public bool Allowed {
get {
return (bool)base["allowed"];
}
set {
base["allowed"] = value;
}
}
public string Path {
get {
return (string)base["path"];
}
set {
base["path"] = value;
}
}
}
Para la clase de colección con tipado fuerte, resulta muy útil poder usar un índice para acceder a la colección mediante la clave de colección, que en este caso es el atributo "path". El parámetro del método Add toma las propiedades necesarias para ese elemento. En este caso, el atributo Add podría haber tomado solo el atributo "path" y, a continuación, el atributo "permitido" tendría su valor predeterminado.
Este es un ejemplo que usa estas clases fuertemente tipadas para recorrer en iteración las entradas de una colección y agregarle un elemento.
static void Main(string[] args) {
ServerManager serverManager = new ServerManager();
Configuration config = serverManager.GetApplicationHostConfiguration();
IsapiCgiRestrictionSection section =
(IsapiCgiRestrictionSection)config.GetSection("system.webServer/security/isapiCgiRestriction", typeof(IsapiCgiRestrictionSection));
// Iterating through the elements in the collection
foreach (IsapiCgiRestrictionElement element in section.IsapiCgiRestrictions) {
Console.Write("Path: " + element.Path);
Console.WriteLine(" Allowed: " + element.Allowed);
}
// Adding a new element to the collection
section.IsapiCgiRestrictions.Add(@"%SystemDir%\someDll.dll", false);
serverManager.CommitChanges();
}