How can I modify / manipulate the web.config programmatically with C# ? Can I use a configuration object, and, if yes, how can I load the web.config into a configuration object ? I would like to have a full example changing the connection string. After the modification the web.config should be written back to the harddisk.
Here it is some code:
var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = (ConnectionStringsSection)configuration.GetSection("connectionStrings");
section.ConnectionStrings["MyConnectionString"].ConnectionString = "Data Source=...";
configuration.Save();
See more examples in this article, you may need to take a look to impersonation.
Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as ConnectionStringsSection;
//section.SectionInformation.UnprotectSection();
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();
Since web.config file is xml file you can open web.config using xmldocument class. Get the node from that xml file that you want to update and then save xml file.
here is URL that explains in more detail how you can update web.config file programmatically.
http://patelshailesh.com/index.php/update-web-config-programmatically
Note: if you make any changes to web.config, ASP.NET detects that changes and it will reload your application(recycle application pool) and effect of that is data kept in Session, Application, and Cache will be lost (assuming session state is InProc and not using a state server or database).
This is a method that I use to update AppSettings, works for both web and desktop applications. If you need to edit connectionStrings you can get that value from System.Configuration.ConnectionStringSettings config = configFile.ConnectionStrings.ConnectionStrings["YourConnectionStringName"]; and then set a new value with config.ConnectionString = "your connection string";. Note that if you have any comments in the connectionStrings section in Web.Config these will be removed.
private void UpdateAppSettings(string key, string value)
{
System.Configuration.Configuration configFile = null;
if (System.Web.HttpContext.Current != null)
{
configFile =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
}
else
{
configFile =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
}
var settings = configFile.AppSettings.Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
Related
I am modifying my MyApp.vhost.exe, and the App.vhost.exe is modified as I can see in the text editor, but when I stop the debug application, the App.config values revert back to what they were before the change. What am I doing wrong or what am I missing?
Configuration exeConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var section = exeConfiguration.GetSection(monitorSectionElementName);
if (section != null)
{
var monitorPathElements = (section as MonitorSection).MonitorPaths;
monitorPathElements[monitorPath].CheckSum = checkSum;
}
exeConfiguration.Save(ConfigurationSaveMode.Full, true);
ConfigurationManager.RefreshSection(monitorSectionElementName);
I have created mvc application.. In that i have write code for update web.config.i.e
try
{
//// Helps to open the Root level web.config file.
Configuration webConfigApp = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
AppSettingsSection objAppsettings = (AppSettingsSection)webConfigApp.GetSection("appSettings");
//Edit
if (objAppsettings != null)
{
////Modifying the AppKey from AppValue to AppValue1
objAppsettings.Settings["DaysToKeepJob"].Value = model.Keepjobsfolders.ToString();
objAppsettings.Settings["DeleteLocalStoreStudies"].Value = model.DeleteLocalStoreStudies.ToString();
objAppsettings.Settings["ManualBurnerNoOfCopies"].Value = model.ManualNumberofCopies.ToString();
objAppsettings.Settings["DefaultBurner"].Value = model.DefaultBurner.ToString();
objAppsettings.Settings["AutoBurnerNoOfCopies"].Value = model.AutoNumberofCopies.ToString();
objAppsettings.Settings["SmartDisk"].Value = model.chkSMARTDisk.ToString();
objAppsettings.Settings["ForcetodefaultTransfer"].Value = model.chkKeepjobsfolders.ToString();
////Save the Modified settings of AppSettings.
webConfigApp.Save();
}
if (diskType.Title != null)
{
var res = DiskTypeSave(diskType);
}
return Json(new { Status = "Success", Msg = "Rules Saved Successfully." }, JsonRequestBehavior.AllowGet);
}
but after this line webConfigApp.Save(); my session i.e Session["UserAccessRights"] get null . i know because of updating web.config it get null.
Please suggest to maintain session even web.config updates
Every time you change the web.config the application is restarted in IIS.
You can do one of the things below :
Use another settings file, a xml, json, etc. to store those values
Use the database to store those settings per user
Use SQL server for saving sessions or a state server, not in-memory (default)
For this you first have to keep Sessions copy into local variable and then assign again. But for this you have to keep Session.SessionId copy also, because on new session it sets again.
With Advanced Installer, I'm trying to make a Custom Action, that at installationtime, encrypt the Connection String.
I seems like I can't use "~" here. (I moved my working code from the MVC project, to here).
Is there a simple alternative to that line or am I forced to make a complete rewrite and use e.g. a solution that uses somekind of Stream (like this Modifying Web.Config During Installation
Exception thrown by custom action:
System.Reflection.TargetInvocationException: Exception has been thrown by the
target of an invocation. ---> System.ArgumentException:
The application relative virtual path '~' is not allowed here.
Custom Action:
[CustomAction]
public static ActionResult EncryptConnStr(Session session)
{
try
{
var config = WebConfigurationManager.OpenWebConfiguration("~");
var section = (ConnectionStringsSection)config.GetSection("connectionStrings");
var cms = section.ConnectionStrings[GetConnectionStringName()];
var connStr = BuildConnStr(session["CONN_STR_SERVER"], session["CONN_STR_DATABASE"], session["CONN_STR_USERNAME"], session["CONN_STR_PASSWORD"]);
if (cms == null)
{
// Add new Connection String
section.ConnectionStrings.Add(new ConnectionStringSettings(GetConnectionStringName(), connStr));
}
else
{
// Update existing Connection String
cms.ConnectionString = connStr;
}
// Encrypt
section.SectionInformation.ProtectSection(ConnStrEncryptionKey);
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
return ActionResult.Success;
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace, ex.Message);
throw;
}
}
The solution to the path issue, is to use ConfigurationManager a long with some mapping, like this, instead of the web version WebConfigurationManager.
var map = new ExeConfigurationFileMap { ExeConfigFilename = path };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
The encryption works fine as the code is, but the issue with save is still not solved because the execution time is to early. The installation isn't finished and the web.config isn't yet copyed to the APPDIR.
I'm giving .config file path and i want to retrieve appSetting value for key=MYDATA from that given .config file.
I tried following code but not getting expected.
//System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//var classLibrary1AppSettings = (System.Collections.Specialized.NameValueCollection)System.Configuration.ConfigurationManager.GetSection("appSettings");
//config.AppSettings.File = "C:\\mydemo\\web.config";
want to get value for key=MYDATA
Finally I able to manage it , posting will help others
System.Configuration.ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = "C:\\mydemo\\web.config";
System.Configuration.Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
AppSettingsSection section = (AppSettingsSection)configuration.GetSection("appSettings");
if (section.Settings.AllKeys.Any(key => key == "MYDATA"))
{
section.Settings["MYDATA"].Value = updateConfigId;
configuration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
Here is the structure of my application. I have an asp.net web application running at the root of a website. In a child directory I have WebServices\MyWCFService\. Outlined here:
\parentapp\
\parentapp\App_Data\
\parentapp\Web.config
\parentapp\other_parent_stuff
\parentapp\WebServices\
\parentapp\WebServices\MyWCFService\
\parentapp\WebServices\MyWCFService\bin\
\parentapp\WebServices\MyWCFService\bin\MyWCFService.dll
\parentapp\WebServices\MyWCFService\Web.config (WCF's .config)
\parentapp\WebServices\MyWCFService\other_wcf_stuff
Ultimately what I need to do is open the root application's web.config to get its connection strings so the WCF service can connect to the database info provided there. From the WCF, I can get its own web.config, but I need to go up to the website's root to get that web.config. I get the root directory by doing this:
string svcDir = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
DirectoryInfo rootDir = Directory.GetParent(svcDir).Parent.Parent;
string root = rootDir.FullName;
Now apperently to open the config file, you need to use the virtual path (instead of local file system path) like so:
VirtualDirectoryMapping vdm = new VirtualDirectoryMapping(root, true);
WebConfigurationFileMap wcfm = new WebConfigurationFileMap();
wcfm.VirtualDirectories.Add("/", vdm);
Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");
And from there, I should be able to access the connection string by calling config.ConnectionStrings.ConnectionStrings["db_name"].
The problem is I can never get past the config declaration where I am getting an ArgumentOfOfRangeException. This was expected during testing since the root points to my VS Projects folder at C:\\Users\\me\\Documents\\Visual Studio 2012\\Projects. So I dropped a test web.config file in there, but I still get the exception. On the production servers, the path would point to the parent application's root folder, which contains the config file.
Also, keep in mind that within the WCF Service, HttpContext.Current is always null so I can't use its Request method to get the virtual path that way. Same goes for Server.MapPath. Any ideas? I am not opposed to going about this a different way, so long as ultimately, I can open the parent app's web.config.
I finally found the right ConfigurationManger method to use in this case, where a virtual path is not needed. Here is the code:
//web config subfolder and filename
const string WEB_CONFIG = "\\Web.config";
//open parent application's web.config file to get connection string to specific database
string svcDir = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
DirectoryInfo rootDir = Directory.GetParent(svcDir).Parent.Parent;
string root = rootDir.FullName;
string webconfigPath = root + WEB_CONFIG;
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = webconfigPath;
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
string connectionString = "";
if (configuration.ConnectionStrings.ConnectionStrings["db_name"].ConnectionString.Length > 0)
{
connectionString = configuration.ConnectionStrings.ConnectionStrings["db_name"].ConnectionString;
}
Works like a charm.
Here is how i ended up doing this:
public string GetConnectionStringValueFromParent(string key)
{
string value = string.Empty;
try
{
const string WEB_CONFIG = "\\Web.config";
string svcDir = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
DirectoryInfo rootDir = Directory.GetParent(svcDir).Parent;
string root = rootDir.FullName;
string webconfigPath = root + WEB_CONFIG;
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = webconfigPath;
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
if (configuration.ConnectionStrings.ConnectionStrings[key].ConnectionString.Length > 0)
{
value = configuration.ConnectionStrings.ConnectionStrings[key].ConnectionString;
}
}
catch (Exception ex)
{
throw ex;
}
return value;
}