我有一个在 IIS7 中创建站点的 win 表单。一项功能需要打开 web.config 文件并进行一些更新。(连接字符串、smtp、模拟)
但是我没有虚拟路径,只有物理路径。
有什么办法我仍然可以使用 WebConfigurationManager?
我需要使用它查找部分和读/写的能力。
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration
我有一个在 IIS7 中创建站点的 win 表单。一项功能需要打开 web.config 文件并进行一些更新。(连接字符串、smtp、模拟)
但是我没有虚拟路径,只有物理路径。
有什么办法我仍然可以使用 WebConfigurationManager?
我需要使用它查找部分和读/写的能力。
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration
您必须将物理路径映射到虚拟路径。这是您将如何做到的。
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 的回答在我们的开发服务器上效果很好,但在我们的实时服务器上被轰炸并显示以下消息:
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");
}
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);
}
我最终使用了 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()
}
基于 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 更改,但这超出了这个问题的范围。)