Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to OpenWebConfiguration with physical path?

I have a win form that creates a site in IIS7. One function needs to open the web.config file and make a few updates. (connection string, smtp, impersonation)

However I do not have the virtual path, just the physical path.

Is there any way I can still use WebConfigurationManager?

I need to use it's ability to find section and read/write.

System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration
like image 230
aron Avatar asked Mar 03 '10 04:03

aron


4 Answers

You will have to map the physicalPath to a virtualPath. Here is how you would do that.

using System.Web.Configuration;  //Reference the System.Web DLL (project needs to be using .Net 4.0 full, not client framework)

public static Configuration OpenConfigFile(string configPath)
{
    var configFile = new FileInfo(configPath);
    var vdm = new VirtualDirectoryMapping(configFile.DirectoryName, true, configFile.Name);
    var wcfm = new WebConfigurationFileMap();
    wcfm.VirtualDirectories.Add("/", vdm);
    return WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");
}
like image 171
Vadim Rybak Avatar answered Oct 01 '22 11:10

Vadim Rybak


Vadim's answer worked great on our dev server, but bombed out on our live server with the following message:

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: site 

To correct this, I found another overload for WebConfigurationManager.OpenMappedWebConfiguration that takes the IIS website name as the third parameter. The result is as follows:

public static Configuration OpenConfigFile(string configPath)
{
    var configFile = new FileInfo(configPath);
    var vdm = new VirtualDirectoryMapping(configFile.DirectoryName, true, configFile.Name);
    var wcfm = new WebConfigurationFileMap();
    wcfm.VirtualDirectories.Add("/", vdm);
    return WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/", "iis_website_name");
}
like image 31
Keith Avatar answered Oct 01 '22 12:10

Keith


Vadim's answer was exactly what I needed, but I came across the same issue as Kieth, and his solution did the trick!

I thought I'd add though, that the IIS Website name can be retrieved by calling:

System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName();

Also, cjbarth's code included a tidy solution for those testing in environments where the location of wwwroot and Web.config can vary:

System.Web.HttpContext.Current.Server.MapPath("~");

So with these in mind another slight improvement on Vadim's function would read:

    public static Configuration GetWebConfig() {
        var webConfigFile = new FileInfo("Web.config");
        var wwwRootPath = HttpContext.Current.Server.MapPath("~");
        var vdm = new VirtualDirectoryMapping(wwwRootPath, true, webConfigFile.Name);
        var wcfm = new WebConfigurationFileMap();
        wcfm.VirtualDirectories.Add("/", vdm);
        var siteName = HostingEnvironment.ApplicationHost.GetSiteName();
        return WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/", siteName);
    }
like image 24
Fehr Avatar answered Oct 01 '22 11:10

Fehr


I ended up using Powershell.

$file = "D:\Applications\XXX\Private\XXX\XXXX\web.config"

 

$configurationAssembly = "System.Configuration, Version=4.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a"
[Void] [Reflection.Assembly]::Load($configurationAssembly)

 
$filepath = New-Object System.Configuration.ExeConfigurationFileMap
$filepath.ExeConfigFileName = $file
$configuration = [System.Configuration.ConfigurationManager]::OpenMappedExeConfiguration($filepath,0)
$section = $configuration.GetSection("appSettings")



Write-Host "Set the Protection Provider"

 

if (-not $section.SectionInformation.IsProtected)
{
    $section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider")
    $configuration.Save()
}
like image 25
Joe Avatar answered Oct 01 '22 11:10

Joe