The Configuration API enables you to retrieve and modify configuration settings. You can use the Configuration API to modify web configuration files on the local machine or a remote machine. If you are responsible for maintaining a large number of websites, the Configuration API can make your life much easier. You can build administrative tools that enable you to make configuration changes quickly to multiple applications. You can use the Configuration API in an ASP.NET page, or you can build command-line tools or Windows Forms applications that use the Configuration API. The Configuration API is exposed by the WebConfigurationManager class (located in the System.Web.Configuration namespace). This class supports the following properties: The WebConfigurationManager also supports the following methods: GetSection Retrieves a configuration section relative to the current page or a supplied virtual path. GetWebApplicationSection Retrieves a configuration section from the current web application root web configuration file. OpenMachineConfiguration Retrieves a Machine.config file on either the local machine or a remote server. OpenMappedMachineConfiguration Retrieves a Machine.config file by using a particular file mapping. OpenMappedWebConfiguration Retrieves a web configuration file by using a particular file mapping. OpenWebConfiguration Retrieves a Web.config file on either the local machine or a remote server. Almost every configuration section in the web configuration file has a corresponding class in the .NET Framework that represents the configuration section. These classes provide you with a strongly typed representation of each configuration section. For example, corresponding to the <authentication> section in the web configuration file, there is a System.Web.Configuration.AuthenticationSection class. Corresponding to the <pages> section in the web configuration file, there is a System.Web.Configuration.PagesSection class. Each of these classes expose properties that correspond to all the attributes you can set in the web configuration file. Reading Configuration Sections from the Current Application When an ASP.NET application starts, the application merges all the configuration settings in the configuration hierarchy to create one representation of the configuration settings. A particular configuration setting might have different values at different levels in the hierarchy. You can use the methods of the WebConfigurationManager class to get the value of a configuration setting at any level in the hierarchy. The WebConfigurationManager.GetWebApplicationSection() method always retrieves a configuration setting from the application root Web.config file. For example, the page in Listing 26.8 displays whether debugging is enabled. Listing 26.8. ShowConfigApp.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load() Dim section As CompilationSection = CType( WebConfigurationManager .GetWebApplicationSection("system.web/compilation"), CompilationSection) lblDebug.Text = section.Debug.ToString() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config App</title> </head> <body> <form runat="server"> <div> Debug Mode: <asp:Label Runat="server" /> </div> </form> </body> </html> | The GetWebApplication() method returns an object. You must cast the value returned by this method to a particular configuration section type. In Listing 26.8, the value returned by this method is cast to an instance of the CompilationSection type. Realize that you will get the same result when the page in Listing 26.8 is located in different subfolders. For example, debugging might not be enabled in a root configuration file, but it might be enabled in a configuration file in a particular subfolder. However, if you call the GetWebApplicationSection() method, the method always returns the configuration setting for the application root Web.config file. If you want to get the value of a configuration setting relative to the folder in which the page executes, then you can use the GetSection() method instead of the GetWebApplicationSection() method. The page in Listing 26.9 is located in a subfolder. The page displays the value of the debug setting retrieved from both the GetWebApplicationSection() method and the GetSection() method (see Figure 26.5). Figure 26.5. Retrieving a configuration setting with the GetSection() and GetWebApplicationSection() methods. Listing 26.9. SubFolder\ShowConfigRelative.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load() Dim section As CompilationSection = CType( WebConfigurationManager.GetSection ("system.web/compilation"), CompilationSection) lblDebug1.Text = section.Debug.ToString() section = CType(WebConfigurationManager.GetWebApplicationSection("system.web /compilation"), CompilationSection) lblDebug2.Text = section.Debug.ToString() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Relative</title> </head> <body> <form runat="server"> <div> GetSection Debug: <asp:Label Runat="server" /> <br /><br /> GetWebApplicationSection Debug: <asp:Label Runat="server" /> </div> </form> </body> </html> | When you request the page in Listing 26.9, different values are displayed by the GetSection() method and GetWebApplicationSection() method. The method displays the configuration setting relative to the current directory. The second method displays the configuration setting from the application root Web.config file. If you want to retrieve the value of a configuration setting for a particular path, then you can use the overload of the GetSection() method that accepts a path parameter. The page in Listing 26.10 iterates through all the immediate subfolders contained in the current application and displays whether debugging is enabled (see Figure 26.6). Figure 26.6. Displaying configuration settings for each subfolder in an application. Listing 26.10. ShowConfigPath.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Web.Configuration" %> <%@ Import Namespace="System.Collections.Generic" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load() Dim results As New Dictionary(Of String, Boolean)() Dim rootDir As New DirectoryInfo(Request.PhysicalApplicationPath) Dim dirs As DirectoryInfo() = rootDir.GetDirectories() For Each dir As DirectoryInfo In dirs Dim path As String = "~/" & dir.Name Dim section As CompilationSection = CType(WebConfigurationManager.GetSection ("system.web/compilation", path), CompilationSection) results.Add(path, section.Debug) Next grdResults.DataSource = results grdResults.DataBind() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Path</title> </head> <body> <form runat="server"> <div> <asp:GridView AutoGenerateColumns="false" Runat="server"> <Columns> <asp:BoundField DataField="Key" HeaderText="Path" /> <asp:BoundField DataField="Value" HeaderText="Debug Mode" /> </Columns> </asp:GridView> </div> </form> </body> </html> | Opening a Configuration File If you want to open a particular configuration file, then you can use one of the Open methods exposed by the WebConfigurationManager class. For example, the page in Listing 26.11 uses the OpenMachineConfiguration() method to open the Machine.config file and display the default value for the authentication mode setting. Listing 26.11. ShowConfigMachine.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load() Dim config As Configuration = WebConfigurationManager.OpenMachineConfiguration() Dim section As AuthenticationSection = CType(config.GetSection("system.web /authentication"), AuthenticationSection) lblMode.Text = section.Mode.ToString() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Machine</title> </head> <body> <form runat="server"> <div> Authentication Mode Default Value: <asp:Label Runat="server" /> </div> </form> </body> </html> | You can use the WebConfigurationManager class to display configuration information for other websites located on the same server. For example, the page in Listing 26.12 displays a list of all the virtual directories contained in the default website. You can select a virtual directory and view the authentication mode associated with the virtual directory (see Figure 26.7). Figure 26.7. Displaying configuration information for any application hosted on a server. Listing 26.12. ShowConfigSites.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <%@ Import Namespace="System.DirectoryServices" %> <%@ Import Namespace="System.Collections.Generic" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Const sitePath As String = "IIS://localhost/W3SVC/1/ROOT" Sub Page_Load() If Not Page.IsPostBack Then dropVDirs.DataSource = GetVirtualDirectories() dropVDirs.DataBind() End If End Sub Private Function GetVirtualDirectories() As List(Of String) Dim dirs As New List(Of String)() Dim site As New DirectoryEntry(sitePath) Dim vdirs As DirectoryEntries = site.Children For Each vdir As DirectoryEntry In vdirs If vdir.SchemaClassName = "IIsWebVirtualDir" Then Dim vPath As String = vdir.Path.Remove(0, sitePath.Length) dirs.Add(vPath) End If Next Return dirs End Function Protected Sub btnSelect_Click(ByVal sender As Object, ByVal e As EventArgs) Dim config As Configuration = WebConfigurationManager.OpenWebConfiguration (dropVDirs.SelectedValue) Dim section As AuthenticationSection = CType( config.GetSection("system.web /authentication"), AuthenticationSection) lblAuthenticationMode.Text = section.Mode.ToString() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Sites</title> </head> <body> <form runat="server"> <div> <asp:Label Text="Virtual Directory:" AssociatedControl Runat="server" /> <asp:DropDownList Runat="server" /> <asp:Button Text="Select" OnClick="btnSelect_Click" Runat="server" /> <hr /> Authentication Mode: <asp:Label Runat="server" /> </div> </form> </body> </html>ShowConfigSites | The list of virtual directories is retrieved with the classes from the System.DirectoryServices namespace. When you select a virtual directory, the OpenWebConfiguration() method is called with the path to the virtual directory to get the configuration information. Warning Before you can use the classes from the System.DirectoryServices namespace, you must add a reference to the System.DirectoryServices.dll assembly. In Visual Web Developer, select the menu option Website, Add Reference. Opening a Configuration File on a Remote Server You can use the WebConfigurationManager class to open Machine.config or Web.config files located on remote web servers. However, before you can do this, you must perform one configuration step. You must enable the remote server to accept remote configuration connections by executing the following command from a command prompt: aspnet_regiis -config+ To disable remove configuration connections, execute the following command: aspnet_regiis -config- The aspnet_regiis tool is located in the following path: \WINDOWS\Microsoft.NET\Framework\[version]\aspnet_regiis.exe Note If you open the SDK Command Prompt, then you don't need to navigate to the Microsoft.NET folder to execute the aspnet_regiis tool. After you make this modification to a remote server, you can retrieve (and modify) configuration settings on the remote server by using one of the Open methods exposed by the WebConfigurationManager class. For example, the page in Listing 26.13 contains a form that enables you to enter a server, username, and password. When you submit the form, the page connects to the remote server and retrieves its Machine.config file. The page displays the current value of the remote server's authentication mode (see Figure 26.8). Figure 26.8. Changing configuration settings for a remote server. Listing 26.13. ShowConfigRemote.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) Try Dim config As Configuration = WebConfigurationManager.OpenMachineConfiguration (Nothing, txtServer.Text,txtUserName.Text, txtPassword.Text) Dim section As AuthenticationSection = CType(config.GetSection("system.web /authentication"), AuthenticationSection) lblAuthenticationMode.Text = section.Mode.ToString() Catch ex As Exception lblAuthenticationMode.Text = ex.Message End Try End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Remote</title> </head> <body> <form runat="server"> <div> <asp:Label Text="Server:" AssociatedControl Runat="server" /> <br /> <asp:TextBox Runat="server" /> <br /><br /> <asp:Label Text="User Name:" AssociatedControl Runat="server" /> <br /> <asp:TextBox Runat="server" /> <br /><br /> <asp:Label Text="Password:" AssociatedControl Runat="server" /> <br /> <asp:TextBox TextMode="Password" Runat="server" /> <br /><br /> <asp:Button Text="Submit" OnClick="btnSubmit_Click" Runat="server" /> <hr /> Authentication Mode: <asp:Label Runat="server" /> </div> </form> </body> </html> | You can use the page in Listing 26.13 even when the web server is located in some distant part of the Internet. You can enter a domain name or IP address in the server field. Using the Configuration Class When you use one of the WebConfigurationManager Open methodssuch as the OpenMachineConfiguration() or OpenWebConfiguration() methodsthe method returns an instance of the Configuration class. This class supports the following properties: AppSettings Returns the appSettings configuration section. ConnectionStrings Returns the connectionStrings configuration section. EvaluationContext Returns an instance of the ContextInformation class that enables you to determine the context of the configuration information. FilePath Returns the physical file path to the configuration file. HasFile Returns true when there is a file that corresponds to the configuration information. Locations Returns a list of locations defined by the configuration. NamespaceDeclared Returns true when the configuration file includes a namespace declaration. RootSectionGroup Returns the root section group. SectionGroups Returns the child section groups contained by this configuration. Sections Returns the child sections contained by this configuration. The Configuration class also supports the following methods: GetSection Enables you to return the specified configuration section. GetSectionGroup Enables you to return the specified configuration section group. Save Enables you to save any configuration changes. SaveAs Enables you to save the configuration as a new file. A configuration file contains two basic types of entities: section groups and sections. For example, the <system.web> element in a configuration file represents a section group. The <system.web> section group contains child sections such as the <authentication> and <httpRuntime> sections. You can use the Configuration.RootSectionGroup property to get the primary section group in a configuration file. You can use the SectionGroups property to return all of a section group's child section groups and the Sections property to return all of a section group's child sections. For example, the page in Listing 26.14 recursively displays the contents of the Machine.config file in a treeView control (see Figure 26.9). Figure 26.9. Displaying all configuration sections from the system.web configuration section group. Listing 26.14. ShowConfigContents.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> sub Page_Load() ' Add first node Dim parentNode As New TreeNode("configuration") TreeView1.Nodes.Add(parentNode) ' Start from the root section group Dim config As Configuration = WebConfigurationManager.OpenMachineConfiguration() ' Show child section groups AddChildSectionGroups(parentNode, config.RootSectionGroup) ' Show child sections AddChildSections(parentNode, config.RootSectionGroup) end sub Private Sub AddChildSectionGroups(ByVal parentNode As TreeNode, ByVal parentConfigSectionGroup As ConfigurationSectionGroup) For Each configSectionGroup As ConfigurationSectionGroup In parentConfigSectionGroup.SectionGroups Dim childNode As New TreeNode(configSectionGroup.SectionGroupName) parentNode.ChildNodes.Add(childNode) AddChildSectionGroups(childNode, configSectionGroup) AddChildSections(childNode, configSectionGroup) Next End Sub Private Sub AddChildSections(ByVal parentNode As TreeNode, ByVal parentConfigSectionGroup As ConfigurationSectionGroup) For Each configSection As ConfigurationSection In parentConfigSectionGroup.Sections Dim childNode As New TreeNode(configSection.SectionInformation.Name) parentNode.ChildNodes.Add(childNode) Next End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Contents</title> </head> <body> <form runat="server"> <div> <asp:TreeView Runat="server" /> </div> </form> </body> </html> | Modifying Configuration Sections You can use the WebConfigurationManager class not only when opening a configuration file to read the values of various configuration settings. You also can use the WebConfigurationManager class to modify existing configuration settings or add new ones. The Configuration class supports two methods for saving configuration information: the Save() and SaveAs() methods. For example, the page in Listing 26.15 enables you to turn on and off debugging for an application (see Figure 26.10). Figure 26.10. Modifying the value of the Debug configuration setting. Listing 26.15. ShowConfigModify.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> sub Page_Load() if Not Page.IsPostBack Then Dim config As Configuration = WebConfigurationManager.OpenWebConfiguration (Request.ApplicationPath) Dim section As CompilationSection = CType(config.GetSection("system.web /compilation"), CompilationSection) chkDebug.Checked = section.Debug end if end sub Protected Sub btnUpdate_Click(ByVal sender As Object, ByVal e As EventArgs) Dim config As Configuration = WebConfigurationManager.OpenWebConfiguration(Request .ApplicationPath) Dim section As CompilationSection = CType(config.GetSection("system.web /compilation"), CompilationSection) section.Debug = chkDebug.Checked config.Save(ConfigurationSaveMode.Modified) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Show Config Modify</title> </head> <body> <form runat="server"> <div> <asp:CheckBox Text="Enable Debugging?" Runat="server" /> <br /><br /> <asp:Button Text="Update" OnClick="btnUpdate_Click" Runat="server" /> </div> </form> </body> </html> | The page in Listing 26.15 loads the application root Web.config file with the help of the OpenWebConfiguration() method (the Nothing parameter causes the root Web.config file to be loaded). Next, the value of the Compilation.Debug property is modified. Finally, the Save() method is called to save this change. When you call the Save() method, you can pass a ConfigurationSaveMode parameter to the method. This parameter can have the following values: Full Saves all configuration settings, regardless of whether they have been modified. Minimal Saves only those configuration settings that are different from their inherited value. Modified Saves only those configuration settings that have been modified. To use the Save() or SaveAs() methods, the account associated with the page must have Write permissions for the folder where the configuration file is saved. By default, when pages are served from Internet Information Server, ASP.NET pages execute in the security context of the NETWORK SERVICE account (in the case of Windows Server 2003) or the ASPNET account (in the case of other operating systems). By default, neither of these accounts have permissions to save configuration changes. Note To make things more confusing, when pages are served from the web server included with Visual Web Developer, the pages are always served in the security context of the current user. There are multiple ways that you can get around this permission problem. First, remember that you can use many of the methods of the WebConfigurationManager class from a console application or a Windows Forms application. If you build this type of application, then you can sidestep these security issues. Another option is to enable per-request impersonation for your ASP.NET application. When impersonation is enabled, an ASP.NET page executes within the security context of the user making the page request. If the user account has permissions to write to the file system, then the page has permissions to write to the file system. The web configuration file in Listing 26.16 enables impersonation. Listing 26.16. Web.config <?xml version="1.0"?> <configuration> <system.web> <identity impersonate="true" /> </system.web> </configuration> | If you add the configuration file in Listing 26.16 to the same folder that contains the file in Listing 26.15, then you will be able to make modifications to configuration files. Warning Most changes to a configuration file result in an application restart. When an ASP.NET application restarts, all data stored in memory is blown away. For example, all data cached in the Cache object or Session state is lost. Provisioning a New Website When you are provisioning new websites, you often need to create a new virtual directory. The Configuration API doesn't provide you with any help here. However, you can create new virtual directories (and applications) by taking advantage of the classes in the System.DirectoryServices namespace. These classes enable you to use Active Directory Services Interface (ADSI) to modify properties of Internet Information Server. Note You also can manipulate Internet Information Server properties by using Windows Management Instrumentation (WMI). For more information, see the topic "Using WMI to Configure IIS" at the Microsoft MSDN website (msdn.microsoft.com). Before you can use the classes from the System.DirectoryServices namespace, you need to add a reference to the System.DirectoryServices.dll assembly. In Visual Web Developer, select the menu option Website, Add Reference, and select System.DirectoryServices.dll. For example, the page in Listing 26.17 enables you to provision a new ASP.NET application (see Figure 26.11). The page creates a new virtual directory and a new application. The page also creates a new web configuration file in the virtual directory that contains the default language and debug settings you specify. Figure 26.11. Creating a new ASP.NET application. Listing 26.17. ProvisionSite.aspx [View full width] <%@ Page Language="VB" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.DirectoryServices" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Const wwwroot As String = "c:\Inetpub" Const sitePath As String = "IIS://localhost/W3SVC/1/ROOT" Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) Dim NewFolder As String = Path.Combine(wwwroot, txtVirtualDir.Text) CreateVirtualDirectory(NewFolder, txtVirtualDir.Text, txtVirtualDir.Text) CreateConfiguration(txtVirtualDir.Text) ' Show link to new site lnkNewSite.NavigateUrl = "http://localhost/" & txtVirtualDir.Text lnkNewSite.Target = "_top" lnkNewSite.Visible = True End Sub Private Sub CreateVirtualDirectory(ByVal folderPath As String, ByVal virtualDirectoryName As String, ByVal appFriendlyName As String) ' Create new Folder Directory.CreateDirectory(folderPath) ' Create Virtual Directory Dim vRoot As New DirectoryEntry(sitePath) Dim vDir As DirectoryEnTry = vRoot.Children.Add(virtualDirectoryName, "IIsWebVirtualDir") vDir.CommitChanges() vDir.Properties("Path").Value = folderPath vDir.Properties("DefaultDoc").Value = "Default.aspx" vDir.Properties("DirBrowseFlags").Value = 2147483648 vDir.CommitChanges() vRoot.CommitChanges() ' Create Application (Isolated) vDir.Invoke("AppCreate2", 1) vDir.Properties("AppFriendlyName").Value = appFriendlyName vDir.CommitChanges() End Sub Private Sub CreateConfiguration(ByVal virtualPath As String) ' Open configuration Dim config As Configuration = WebConfigurationManager.OpenWebConfiguration("/" & virtualPath) ' Set language and debug setting Dim section As CompilationSection = CType(config.GetSection("system.web /compilation"), CompilationSection) section.DefaultLanguage = rdlLanguage.SelectedItem.Text section.Debug = chkDebug.Checked ' Save configuration config.Save(ConfigurationSaveMode.Modified) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Provision Site</title> </head> <body> <form runat="server"> <div> <asp:Label Text="Virtual Directory:" AssociatedControl Runat="server" /> <br /> <asp:TextBox Runat="server" /> <br /><br /> <asp:Label Text="Default Language:" AssociatedControl Runat="server" /> <asp:RadioButtonList Runat="server"> <asp:ListItem Text="VB" Selected="True" /> <asp:ListItem Text="C#" /> </asp:RadioButtonList> <br /> <asp:CheckBox Text="Enable Debugging" Runat="server" /> <br /><br /> <asp:Button Text="Submit" OnClick="btnSubmit_Click" Runat="server" /> <hr /> <asp:HyperLink Visible="false" Text="Go to New Site" Runat="server" /> </div> </form> </body> </html> | To use the page in Listing 26.17, you'll need adequate permissions. You can enable per-request impersonation by adding the file in Listing 26.16 to the same folder as the page in Listing 26.17. Note Internet Information Server includes several sample ADSI scripts. Look in your Inetpub\AdminScripts folder. |