So, I'm doing a website that does a lot of things and one of them is, doing a dynamic connection string... I already did it, but because I took the code from the internet, I'm kinda lost, so I was hoping that somebody could help and explain how it works and what each thing does...
Here's the code:
protected void Page_Load(object sender, EventArgs e)
{
AddUpdateConnectionString("ConString");
}
void AddUpdateConnectionString(string name)
{
bool isNew = false;
string path = Server.MapPath("~/Web.Config");
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNodeList list = doc.DocumentElement.SelectNodes(string.Format("connectionStrings/add[#name='{0}']", name));
XmlNode node;
isNew = list.Count == 0;
if (isNew)
{
node = doc.CreateNode(XmlNodeType.Element, "add", null);
XmlAttribute attribute = doc.CreateAttribute("name");
attribute.Value = name;
node.Attributes.Append(attribute);
attribute = doc.CreateAttribute("connectionString");
attribute.Value = "";
node.Attributes.Append(attribute);
attribute = doc.CreateAttribute("providerName");
attribute.Value = "System.Data.SqlClient";
node.Attributes.Append(attribute);
}
else
{
node = list[0];
}
string conString = node.Attributes["connectionString"].Value;
SqlConnectionStringBuilder conStringBuilder = new SqlConnectionStringBuilder(conString);
conStringBuilder.InitialCatalog = TxtBaseDeDados.Text;
conStringBuilder.DataSource = TxtHost.Text;
conStringBuilder.IntegratedSecurity = false;
conStringBuilder.UserID = TxtUtilizador.Text;
conStringBuilder.Password = TxtPalavraPasse.Text;
node.Attributes["connectionString"].Value = conStringBuilder.ConnectionString;
if (isNew)
{
doc.DocumentElement.SelectNodes("connectionStrings")[0].AppendChild(node);
}
doc.Save(path);
}
protected void Button1_Click(object sender, EventArgs e)
{
AddUpdateConnectionString("ConString");
}
If you are wanting to load a connection string from the web.config file I would encourange you to use the ConfigurationManager class like this:
ConfigurationManager.ConnectionStrings["WingtipToys"].ConnectionString
WingtipToys would be stored like this in web.config
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="WingtipToys" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=WingtipToys;Integrated Security=True;Pooling=False" />
</connectionStrings>
Here is more info: https://learn.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager?view=netframework-4.8
It creates or updates the setting in your web.config file used to store the details of how to connect to your back-end database. Config files are XML documents (which are laid out in hierarchical format), so the code finds the config, finds the right section inside of the config (creating it if it's not there), constructs a new connection string, stores it in the XML and saves the changes.
Related
I'm trying to write a routine that updates values in an XML file and believe I'm close. Here's an example of the XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is generated by the GPS_Client program. -->
<Sites>
<Site>
<Id>A</Id>
<add key="landingName" value="Somewhere" />
<add key="landingLat" value="47.423719" />
<add key="landingLon" value="-123.011364" />
<add key="landingAlt" value="36" />
</Site>
<Site>
<Id>B</Id>
<add key="landingName" value="Somewhere Else" />
<add key="landingLat" value="45.629160" />
<add key="landingLon" value="-128.882934" />
<add key="landingAlt" value="327" />
</Site>
</Sites>
The key is that I need to update a specific key without updating the rest of the keys with the same name. Here's the current code:
private void UpdateOrCreateAppSetting(string filename, string site, string key, string value)
{
string path = "\"#" + filename + "\"";
XDocument doc = XDocument.Load(path);
var list = from appNode in doc.Descendants("appSettings").Elements()
where appNode.Attribute("key").Value == key
select appNode;
var e = list.FirstOrDefault();
// If the element doesn't exist, create it
if (e == null) {
new XElement(site,
new XAttribute(key, value));
// If the element exists, just change its value
} else {
e.Element(key).Value = value;
e.Attribute("value").SetValue(value);
}
}
I assume I need to concatenate site, Id and key in some way, but don't see how it's done.
Using this XmlLib, you can have it create the node if it doesn't exist automatically.
private void UpdateOrCreateAppSetting(string filename, string site,
string key, string value)
{
string path = "\"#" + filename + "\"";
XDocument doc = XDocument.Load(path);
XPathString xpath = new XPathString("//Site[Id={0}]/add[#key={1}]", site, key);
XElement node = doc.Root.XPathElement(xpath, true); // true = create if not found
node.Set("value", value, true); // set as attribute, creates attribute if not found
doc.Save(filename);
}
I'm trying to read the text in between <keyMaterial></keyMaterial>
I tried using //WLANProfile/MSM/security/sharedKey as the element route, seen in the code below. It refuses to return a value. I have run through the debugger and after the breakpoint at the line: XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//WLANProfile/MSM/security/sharedKey");
the SharedKeyNodes object doesn't return a count for. I know it's just a matter of figuring out the element route so I'm not coming here completely hopeless...
System.Xml.XPathNodeList
My XML looks like this:
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>nosignal</name>
<SSIDConfig>
<SSID>
<hex>6E6F7369676E616C</hex>
<name>nosignal</name>
</SSID>
<nonBroadcast>true</nonBroadcast>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>auto</connectionMode>
<autoSwitch>false</autoSwitch>
<MSM>
<security>
<authEncryption>
<authentication>WPA2PSK</authentication>
<encryption>AES</encryption>
<useOneX>false</useOneX>
<FIPSMode xmlns="http://www.microsoft.com/networking/WLAN/profile/v2">false</FIPSMode>
</authEncryption>
<sharedKey>
<keyType>passPhrase</keyType>
<protected>true</protected>
<keyMaterial>01000000D</keyMaterial>
</sharedKey>
</security>
</MSM>
</WLANProfile>
[ EDIT with the help of LB the new code looks like this and it WORKS! ]
[ For anyone that is struggling with a similar problem. ]
My Class is:
class ProfileManager
{
public static string readProfile() {
XmlDocument wifiProfile = new XmlDocument();
string path = #"C:\temp\nosignal.xml";
string password = "";
wifiProfile.Load(path);
XmlNamespaceManager mgr = new XmlNamespaceManager(wifiProfile.NameTable);
mgr.AddNamespace("ns", "http://www.microsoft.com/networking/WLAN/profile/v1");
XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//ns:WLANProfile/ns:MSM/ns:security/ns:sharedKey", mgr);
foreach (XmlNode itemNode in sharedKeyNodes)
{
XmlNode keyMaterialNode = itemNode.SelectSingleNode("ns:keyMaterial", mgr);
if (keyMaterialNode != null)
{
password = keyMaterialNode.InnerText;
}
}
return password;
}
}
I'm close, but still just a bit stuck. Any help would be appreciated!!! Thank you!
You don't use the default XmlNamespace "http://www.microsoft.com/networking/WLAN/profile/v1"
wifiProfile.Load(path);
XmlNamespaceManager mgr = new XmlNamespaceManager(wifiProfile.NameTable);
mgr.AddNamespace("ns", "http://www.microsoft.com/networking/WLAN/profile/v1");
XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//ns:WLANProfile/ns:MSM/ns:security/ns:sharedKey",mgr);
I have the following but its not working for me:
static void SaveVersion(string configFile, string Version)
{
XmlDocument config = new XmlDocument();
config.Load(configFile);
XmlNode appSettings = config.SelectSingleNode("configuration/appSettings");
XmlNodeList appKids = appSettings.ChildNodes;
foreach (XmlNode setting in appKids)
{
if (setting.Attributes["key"].Value == "AgentVersion")
setting.Attributes["value"].Value = Version;
}
config.Save(configFile);
}
The config file i'm loading up on config.Load(configFile) is the following:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v2.0.50727" />
</startup>
<appSettings>
<add key="AgentVersion" value="2.0.5" />
<add key="ServerHostName" value="" />
<add key="ServerIpAddress" value="127.0.0.1" />
<add key="ServerPort" value="9001" />
</appSettings>
</configuration>
Am I missing something? I figured it would edit just that particular attribute AgentVersion but its not really doing anything.
Are you aware of the ConfigurationManager class? You can use it to manipulate your app.config file without doing anything manually. I don't think you should reinvent the wheel unless you have a good reason to:
static void SaveVersion(string configFile, string version)
{
var myConfig = ConfigurationManager.OpenExeConfiguration(configFile);
myConfig.AppSettings.Settings["AgentVersion"].Value = version;
myConfig.Save();
}
Try this:
static void SaveVersion(string configFile, string Version)
{
var config = new XmlDocument();
config.Load(configFile);
var agentVersionElement = config.DocumentElement.SelectSingleNode("configuration/appSettings/add[#key = 'AgentVersion']") as XmlElement;
if (agentVersionElement != null)
agentVersionElement.SetAttribute("value", version);
config.Save(configFile);
}
Note that I'm doing the SelectSingleNode from the DocumentElement, not from the XmlDocument itself.
I have a XML file(web.config) and I need to edit the value attribute of each tag, depend of the key name...
this is an example of the XML file:
<appSettings>
<add key="A1" value="Hi" />
<add key="B1" value="Hello" />
</appSettings>
I mean, How can I change the value "hi" & "hello" using the key attribute(A1 & B1) ??
Thanks alot
try this code, it works fine:
XmlDocument doc = new XmlDocument();
doc.Load("Your.xml");
XmlNodeList elementList = doc.GetElementsByTagName("add");
for (int i = 0; i < elementList.Count; i++)
{
if(elementList[i].Attributes["key"].Value == "A1")
elementList[i].Attributes["value"].Value = "NewValue";
}
if you just want to edit application configuration file
this function can help you
private static void SaveConfig(string KeyName, string value)
{
System.Configuration.ConfigurationManager.AppSettings[KeyName] = value;
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Windows.Forms.Application.ExecutablePath);
System.Configuration.AppSettingsSection ass = config.AppSettings;
if (ass.Settings[KeyName] != null)
ass.Settings[KeyName].Value = value;
else
ass.Settings.Add(KeyName, value);
config.Save();
}
by calling SaveConfig("key","newvalue") you can chage the configvalue
I'm working with C#, Framework 3.5 (VS 2008).
I'm using the ConfigurationManager to load a config (not the default app.config file) into a Configuration object.
Using the Configuration class, I was able to get a ConfigurationSection, but I could not find a way to get the values of that section.
In the config, the ConfigurationSection is of type System.Configuration.NameValueSectionHandler.
For what it worth, when I used the method GetSection of the ConfigurationManager (works only when it was on my default app.config file), I received an object type, that I could cast into collection of pairs of key-value, and I just received the value like a Dictionary. I could not do such cast when I received ConfigurationSection class from the Configuration class however.
EDIT:
Example of the config file:
<configuration>
<configSections>
<section name="MyParams"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<MyParams>
<add key="FirstParam" value="One"/>
<add key="SecondParam" value="Two"/>
</MyParams>
</configuration>
Example of the way i was able to use it when it was on app.config (the "GetSection" method is for the default app.config only):
NameValueCollection myParamsCollection =
(NameValueCollection)ConfigurationManager.GetSection("MyParams");
Console.WriteLine(myParamsCollection["FirstParam"]);
Console.WriteLine(myParamsCollection["SecondParam"]);
Suffered from exact issue. Problem was because of NameValueSectionHandler in .config file. You should use AppSettingsSection instead:
<configuration>
<configSections>
<section name="DEV" type="System.Configuration.AppSettingsSection" />
<section name="TEST" type="System.Configuration.AppSettingsSection" />
</configSections>
<TEST>
<add key="key" value="value1" />
</TEST>
<DEV>
<add key="key" value="value2" />
</DEV>
</configuration>
then in C# code:
AppSettingsSection section = (AppSettingsSection)ConfigurationManager.GetSection("TEST");
btw NameValueSectionHandler is not supported any more in 2.0.
Here's a good post that shows how to do it.
If you want to read the values from a file other than the app.config, you need to load it into the ConfigurationManager.
Try this method: ConfigurationManager.OpenMappedExeConfiguration()
There's an example of how to use it in the MSDN article.
Try using an AppSettingsSection instead of a NameValueCollection. Something like this:
var section = (AppSettingsSection)config.GetSection(sectionName);
string results = section.Settings[key].Value;
Source:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d5079420-40cb-4255-9b3b-f9a41a1f7ad2/
The only way I can get this to work is to manually instantiate the section handler type, pass the raw XML to it, and cast the resulting object.
Seems pretty inefficient, but there you go.
I wrote an extension method to encapsulate this:
public static class ConfigurationSectionExtensions
{
public static T GetAs<T>(this ConfigurationSection section)
{
var sectionInformation = section.SectionInformation;
var sectionHandlerType = Type.GetType(sectionInformation.Type);
if (sectionHandlerType == null)
{
throw new InvalidOperationException(string.Format("Unable to find section handler type '{0}'.", sectionInformation.Type));
}
IConfigurationSectionHandler sectionHandler;
try
{
sectionHandler = (IConfigurationSectionHandler)Activator.CreateInstance(sectionHandlerType);
}
catch (InvalidCastException ex)
{
throw new InvalidOperationException(string.Format("Section handler type '{0}' does not implement IConfigurationSectionHandler.", sectionInformation.Type), ex);
}
var rawXml = sectionInformation.GetRawXml();
if (rawXml == null)
{
return default(T);
}
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(rawXml);
return (T)sectionHandler.Create(null, null, xmlDocument.DocumentElement);
}
}
The way you would call it in your example is:
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = #"c:\\foo.config"
};
var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var myParamsSection = configuration.GetSection("MyParams");
var myParamsCollection = myParamsSection.GetAs<NameValueCollection>();
This is an old question, but I use the following class to do the job. It's based on Scott Dorman's blog:
public class NameValueCollectionConfigurationSection : ConfigurationSection
{
private const string COLLECTION_PROP_NAME = "";
public IEnumerable<KeyValuePair<string, string>> GetNameValueItems()
{
foreach ( string key in this.ConfigurationCollection.AllKeys )
{
NameValueConfigurationElement confElement = this.ConfigurationCollection[key];
yield return new KeyValuePair<string, string>
(confElement.Name, confElement.Value);
}
}
[ConfigurationProperty(COLLECTION_PROP_NAME, IsDefaultCollection = true)]
protected NameValueConfigurationCollection ConfCollection
{
get
{
return (NameValueConfigurationCollection) base[COLLECTION_PROP_NAME];
}
}
The usage is straightforward:
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
NameValueCollectionConfigurationSection config =
(NameValueCollectionConfigurationSection) configuration.GetSection("MyParams");
NameValueCollection myParamsCollection = new NameValueCollection();
config.GetNameValueItems().ToList().ForEach(kvp => myParamsCollection.Add(kvp));
Here are some examples from this blog mentioned earlier:
<configuration>
<Database>
<add key="ConnectionString" value="data source=.;initial catalog=NorthWind;integrated security=SSPI"/>
</Database>
</configuration>
get values:
NameValueCollection db = (NameValueCollection)ConfigurationSettings.GetConfig("Database");
labelConnection2.Text = db["ConnectionString"];
-
Another example:
<Locations
ImportDirectory="C:\Import\Inbox"
ProcessedDirectory ="C:\Import\Processed"
RejectedDirectory ="C:\Import\Rejected"
/>
get value:
Hashtable loc = (Hashtable)ConfigurationSettings.GetConfig("Locations");
labelImport2.Text = loc["ImportDirectory"].ToString();
labelProcessed2.Text = loc["ProcessedDirectory"].ToString();
Try this;
Credit: https://www.limilabs.com/blog/read-system-net-mailsettings-smtp-settings-web-config
SmtpSection section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
string from = section.From;
string host = section.Network.Host;
int port = section.Network.Port;
bool enableSsl = section.Network.EnableSsl;
string user = section.Network.UserName;
string password = section.Network.Password;
This works like a charm
dynamic configSection = ConfigurationManager.GetSection("MyParams");
var theValue = configSection["FirstParam"];