A section having a collection of elements indexed by a key is the system.webServer/security/isapiCgiRestriction section. The schema for the section is as shown.
Microsoft.Web.Administration provides several generic base classes which represents different components in the configuration system.
The example below shows how the nested elements can be accessed in the system.webServer/asp section.
The ServerManager class is the entry point to access the various server settings. We set the properties in the applicationHost.config files, but these properties can also be accessed and changed in the web.config files of individual sites and applications. The CommitChanges call saves the changed settings.
The next example shows how to iterate through elements in a collection and add elements to it.
Strongly Typed Classes to Access the Sections
Strongly typed classes derived from the generic base classes can be written in order to make accessing properties easier and more intuitive. This is especially useful when you might have to access the same section many times for different operations. These classes also ensure that you have compile time checking for property types. They avoid the tedious calls to methods like GetChildElement and GetAttributeValue.
The example below shows the wrapper for the system.webServer/asp section and the "session" element for that section. All the properties in that section are not included in this snippet.
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;
}
}
}
The GetChildElement call in the above example is used to access a nested element in a configuration element (a section, collection element etc.). Calling base[...] wraps the GetAttributeValue and SetAttributeValue classes which retrieves and sets the values for those attributes.
The next example shows how the properties in a nested element can be accessed in a strongly typed manner.
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 the call to config.GetSection which takes a section path and also the type of section you want to create. By default calls to config.GetSection create a ConfigurationSection and in order to get an instance of a strongly typed wrapper you need to pass in a type.
Here is an example of how to create strongly typed classes for a section which has a collection. This example uses the system.webServer/security/isapiCgiRestriction section. This snippet does not include all the properties that are present on this section.
public sealed class IsapiCgiRestrictionSection : ConfigurationSection {
private IsapiCgiRestrictionCollection _collection;
public IsapiCgiRestrictionSection() {
}
public IsapiCgiRestrictionCollection IsapiCgiRestrictions {
get {
if (_collection == null) {
_collection =
(IsapiCgiRestrictionCollection)GetCollection(typeof(IsapiCgiRestrictionCollection));
}
return _collection;
}
}
}
The GetCollection method of the base class (ConfigurationElement) is used to access the default collection for that element.
The next example shows the strongly typed classes for the collection itself and the elements in the collection.
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;
}
}
}
For the strongly typed collection class it is very useful to be able to index into the collection using the collection key, which in this case is the "path" attribute. The parameter to the Add method takes the required properties for that element. In this case the Add could have only taken the "path" attribute and then the "allowed" attribute would then have its default value.
Here is an example using these strongly typed classes to iterate through the entries in a collection and to add an element to it.
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();
}