Как открыть конфигурацию с физическим путем?
У меня есть выигрышная форма, которая создает сайт в IIS7. Одна функция должна открыть файл web.config и сделать несколько обновлений. (строка подключения, smtp, олицетворение)
Однако у меня нет виртуального пути, только физический путь.
Есть ли способ, которым я все еще могу использовать WebConfigurationManager?
Мне нужно использовать его способность находить раздел и читать / писать.
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration
4 ответа
Вам придется сопоставить физический путь с виртуальным путем. Вот как бы вы это сделали.
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, "/");
}
Ответ Вадима отлично сработал на нашем сервере разработки, но сработал на нашем живом сервере со следующим сообщением:
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");
}
В итоге я использовал 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()
}
Ответ Вадима был именно то, что мне было нужно, но я столкнулся с той же проблемой, что и Киет, и его решение помогло!
Я подумал, что добавлю, что имя веб-сайта IIS можно получить, позвонив:
System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName();
Кроме того, код cjbarth включал в себя удобное решение для тестирования в средах, где расположение wwwroot и Web.config может различаться:
System.Web.HttpContext.Current.Server.MapPath("~");
Таким образом, с учетом этого еще одно небольшое улучшение функции Вадима будет гласить:
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);
}
Основываясь на ответе Вадима, я обнаружил, что написанное им не совсем подходит для моей ситуации, поэтому я использовал его вместо этого:
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. Чтобы сделать это, я создал таблицы вручную по этой ссылке: SimpleMembershipProvider в MVC4, а затем использовал эту команду в моем Global.asax
файла Application_Start
Режим дня:
WebSecurity.InitializeDatabaseConnection(ConnectionStringHelper.MyConnectionString, "System.Data.SQLite", "Users", "UserID", "Email", False)
Что, оказывается, вовсе не требовало от меня переписывания файла web.config. (Было также много изменений в web.config, которые мне пришлось сделать, но это еще больше выходит за рамки этого вопроса.)