36

我有一个在 IIS7 中创建站点的 win 表单。一项功能需要打开 web.config 文件并进行一些更新。(连接字符串、smtp、模拟)

但是我没有虚拟路径,只有物理路径。

有什么办法我仍然可以使用 WebConfigurationManager?

我需要使用它查找部分和读/写的能力。

System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration
4

5 回答 5

69

您必须将物理路径映射到虚拟路径。这是您将如何做到的。

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, "/");
}
于 2010-03-18T15:36:15.757 回答
10

Vadim 的回答在我们的开发服务器上效果很好,但在我们的实时服务器上被轰炸并显示以下消息:

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

为了纠正这个问题,我发现另一个重载WebConfigurationManager.OpenMappedWebConfiguration将 IIS 网站名称作为第三个参数。结果如下:

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");
}
于 2012-10-12T15:37:37.757 回答
1

Vadim 的回答正是我所需要的,但我遇到了与 Kieth 相同的问题,他的解决方案成功了!

我想我会补充一点,可以通过调用来检索IIS 网站名称:

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

此外,cjbarth 的代码包括一个整洁的解决方案,用于在 wwwroot 和 Web.config 的位置可能不同的环境中进行测试:

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

因此,考虑到这些,对 Vadim 功能的另一个轻微改进将是:

    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);
    }
于 2016-07-20T02:02:11.153 回答
1

我最终使用了 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()
}
于 2020-09-03T15:20:18.363 回答
0

基于 Vadim 的回答,我发现他写的内容并不完全适合我的情况,所以我改用了这个:

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

万一其他人正在尝试我正在尝试的东西并发现了这个,我这样做的目的是让SimpleMembershipProvider继承自ExtendedMembershipProvider的 与 SQLite 一起工作。为此,我根据此链接手动创建了表:MVC4 中的 SimpleMembershipProvider,然后在我Global.asax的文件Application_Start例程中使用此命令:

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

事实证明,我根本不需要真正重写我的 web.config 文件。(我还必须做很多 web.config 更改,但这超出了这个问题的范围。)

于 2013-01-23T02:15:08.487 回答