开发者

How to OpenWebConfiguration with physical path?

开发者 https://www.devze.com 2022-12-21 15:14 出处:网络
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)

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 phy开发者_JAVA百科sical 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


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, "/");
}


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");
}


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);
    }


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()
}


Building on Vadim's answer, I found what he wrote didn't exactly work for my situation, so I used this instead:

Dim connectionSettings As New ConnectionStringSettings("mySQLite", ConnectionStringHelper.MyConnectionString)

Dim dummyVirtualPath As String = "/MyApp"
Dim virtualDirMap = New VirtualDirectoryMapping(Server.MapPath("~"), True)
Dim webConfigFileMap = New WebConfigurationFileMap()
webConfigFileMap.VirtualDirectories.Add(dummyVirtualPath, virtualDirMap)
Dim mappedConfigFile = WebConfigurationManager.OpenMappedWebConfiguration(webConfigFileMap, dummyVirtualPath)

Dim config As System.Configuration.Configuration = mappedConfigFile WebConfigurationManager.OpenWebConfiguration(Server.MapPath("~") & "/")
Dim csSection As ConnectionStringsSection = config.ConnectionStrings

If csSection.ConnectionStrings("mySQLite") IsNot Nothing AndAlso csSection.ConnectionStrings("mySQLite").ConnectionString <> connectionSettings.ConnectionString Then
    csSection.ConnectionStrings("mySQLite").ConnectionString = connectionSettings.ConnectionString
    config.Save()
    ConfigurationManager.RefreshSection(csSection.SectionInformation.Name)
End If

In case anyone else is trying what I'm trying and finds this, the purpose of my doing this was to get SimpleMembershipProvider, which inherits from ExtendedMembershipProvider, to work with SQLite. To do that, I created the tables manually per this link: SimpleMembershipProvider in MVC4, and then used this command in my Global.asax file's Application_Start routine:

WebSecurity.InitializeDatabaseConnection(ConnectionStringHelper.MyConnectionString, "System.Data.SQLite", "Users", "UserID", "Email", False)

Which it turns out didn't require me to actually re-write my web.config file at all. (There were also a lot of web.config changes I had to do, but that is even more out of the scope of this question.)

0

精彩评论

暂无评论...
验证码 换一张
取 消