How to read web.config section as XML in C#? - c#

This is copied example from:
How to read custom config section in app.config in c#
I want to read following custom section from app.config:
<StartupFolders>
<Folders name="a">
<add folderType="Inst" path="c:\foo" />
<add folderType="Prof" path="C:\foo1" />
</Folders>
<Folders name="b">
<add folderType="Inst" path="c:\foo" />
<add folderType="Prof" path="C:\foo1" />
</Folders>
</StartupFolders>
And this is my case too. However, I don't want to create custom class for handling values, defining this class in web.config, and then finally using it. It is heavy-weight for my needs.
Instead I would like to do something very simple -- retrieve a section as XML. Then I could use regular Linq.Xml to parse it. This way, I don't need to create new classes per each section, I don't need to declare them. For my purpose it is sufficient on one hand, and minimal at the other (I do it once, key-value mapper for nested sections). I.e. perfect.
The only missing piece is (my question) -- how to get a web.config section as XML?
Note about the section:
it cannot be encoded, because it has to be edited by hand
it cannot be serialized for the same reason
So I am not looking for a workaround how to squeeze entire section as value in appSettings, but I am really looking for a method to get proper section as XML.
I would like to get it from ConfigManager (!), because this way I don't have to deal with resolving which web.config should I read, etc. I.e. less chance to make mistake than mimicing web.config precedence manually.
Forgive me for reminding this, but please avoid "answers", you shouldn't do this, use custom class per each section, etc. I already considered this, and opted against it.

I think you either have to do it manually and load the Web config into memory:
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("~/Web.config"));
Or you will need to create the custom configuration sections you want to avoid.

You can define a re-usable custom config section that exposes the section XML as you desire. The key is, that you don't have to define a different class for each custom config section.
For clarity, my project namespace is "ConsoleApp1" as is the assembly name (this appears in type definitions).
First, create a custom config section that exposes the XML reader:
public class XmlConfigSection : ConfigurationSection
{
public XmlReader Xml { get; private set; }
override protected void DeserializeSection(XmlReader reader)
{
Xml = reader;
}
}
You can then define any of your custom sections to use this class in the app.config:
<configSections>
<section name="StartupFolders" type="ConsoleApp1.XmlConfigSection, ConsoleApp1" />
<section name="AnotherCustomSection" type="ConsoleApp1.XmlConfigSection, ConsoleApp1" />
</configSections>
Then in your code, you can access raw XmlReader of the config section like this:
var xmlReader = (ConfigurationManager.GetSection("StartupFolders") as XmlConfigSection).Xml;
If you then want an XML string instead of the reader you can do something like this (though I'd suggest sticking with the XmlReader):
StringBuilder sb = new StringBuilder();
while (xmlReader.Read())
sb.AppendLine(xmlReader.ReadOuterXml());
var xmlStr = sb.ToString();

Totally untested but could you use something like this? :
ConfigurationSection exampleSection =
(ConfigurationSection)ConfigurationManager
.GetSection("system.web/exampleSection");
Then possibly use exampleSection.ElementInformation to get more info?

Related

How to load Configuration from a string [duplicate]

I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks

How make stringConnection throw a txt file MVC Entity Framework

Is there a way to acomplish that? I know how to do it with the web.config file but I was told that cannot be in web.config cuz it must be in a text file where the connection string must be.
Here is what i have tried:
<configuration>
<connectionStrings configSource="ConexionBaseDeDatos.txt"></connectionStrings>
</configuration>
Similar like if i'd it use the a .config file like this
<configuration>
<connectionStrings configSource="ConexionBaseDeDatos.config"></connectionStrings>
</configuration>
And the base name
using System.Data.Entity;
namespace appSwicth.Models {
public class ConexionBaseDeDatos:DbContext {
DbContext db;
public ConexionBaseDeDatos() :base()
{
}
}
}
But I got an error:
"Root Element is missing"
And then the url of the file and nothing more.(the url is totally correct). In the txt file i have nothing now. Could that be the reason of why? I added a connectiong string to it but still not worked, maybe im doing something wrong.
Any way to solve this? If you need more, let me know.
Following is the Standard Format to mention the External Configuration file only.
<?xml version='1.0' encoding='utf-8'?>
<configuration>
<connectionStrings configSource="Your_File_Name.config"/>
</configuration>
It's self explanatory from it's name Config Source
The Source belongs to Configuration files only.
From MSDN - Storing and Retrieving Connection Strings
Alternative - From the above comments
Fetch the information from App Settings like below.
<add key="ConexionBaseDeDatos" value="ConexionBaseDeDatos.txt"/>

How to open a config file app settings using ConfigurationManager?

My config file is located here:
"~/Admin/Web.config"
I tried opening it via the below code but it didn't work:
var physicalFilePath = HttpContext.Current.Server.MapPath("~/Admin/Web.config");
var configMap = new ConfigurationFileMap(physicalFilePath);
var configuration = ConfigurationManager.OpenMappedMachineConfiguration(configMap);
var appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");
when appsettings line runs, it throws the below error message:
Unable to cast object of type 'System.Configuration.DefaultSection' to type 'System.Configuration.AppSettingsSection'.
My Web.Config looks like below:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="AdminUsername" value="Test1"/>
<add key="AdminPassword" value="Test2"/>
</appSettings>
<connectionStrings></connectionStrings>
</configuration>
How could I get the appsettings?
For web-app, you need to use System.Web.Configuration.WebConfigurationManager class and no need to set absolute path.
var web=System.Web.Configuration.WebConfigurationManager
.OpenWebConfiguration("~/admin/web.config");
String appValue=web.AppSettings.Settings["key"].Value;
If you are looking for adding some stuff to the Web.config, and then reading it from the code.
What you need is Custom Configuration Sections in Web.config
Look here:
How do I define custom web.config sections with potential child elements and attributes for the properties?
and here:
Creating Custom Configuration Sections in Web.config - 4GuysFromRolla.com

synchronizing XML nodes between class and file using C#

I'm trying to write an IXmlSerializable class that stays synced with an XML file. The XML file has the following format:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<logging>
<logLevel>Error</logLevel>
</logging>
...potentially other sections...
</configuration>
I have a DllConfig class for the whole XML file and a LoggingSection class for representing <logging> and its contents, i.e., <logLevel>. DllConfig has this property:
[XmlElement(ElementName = LOGGING_TAG_NAME,
DataType = "LoggingSection")]
public LoggingSection Logging { get; protected set; }
What I want is for the backing XML file to be updated (i.e., rewritten) when a property is set. I already have DllConfig do this when Logging is set. However, how should I go about doing this when Logging.LogLevel is set? Here's an example of what I mean:
var config = new DllConfig("path_to_backing_file.xml");
config.Logging.LogLevel = LogLevel.Information; // not using Logging setter, but a
// setter on LoggingSection, so how
// does path_to_backing_file.xml
// have its contents updated?
My current solution is to have a SyncedLoggingSection class that inherits from LoggingSection and also takes a DllConfig instance in the constructor. It declares a new LogLevel that, when set, updates the LogLevel in the base class and also uses the given DllConfig to write the entire DllConfig out to the backing XML file. Is this a good technique?
I don't think I can just serialize SyncedLoggingSection by itself to the backing XML file, because not all of the contents will be written, just the <logging> node. Then I'd end up with an XML file containing only the <logging> section with its updated <logLevel>, instead of the entire config file with <logLevel> updated. Hence, I need to pass an instance of DllConfig to SyncedLoggingSection.
It seems almost like I want an event handler, one in DllConfig that would notice when particular properties (i.e., LogLevel) in its properties (i.e., Logging) were set. Is such a thing possible?
Since you are implementing IXmlSerializable yourself, you can make DllConfig.Logging private. Then add a public method on DllConfig to set LogLevel instead of setting Logging.LogLevel directly. That will be the only way you can change the LogLevel. In the implementation of that public method, you can serialize the whole DllConfig to overwrite the xml.

Is there a way to get a System.Configuration.Configuration instance based on arbitrary xml?

I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks

Categories

Resources