I'd like to get a value from this config file from within an MVC view. How is this achieved?
Thanks
UnsupportedBrowsers.config (projectRoot/config/..)
<UnsupportedBrowsers>
<Browser alias="Internet Explorer">
<Version>
<add key="ie6" value="IE6"/>
<add key="ie7" value="IE7"/>
<add key="ie8" value="IE8"/>
</Version>
</Browser>
</UnsupportedBrowsers>
First, it would be better to do it in the Controller rather than in the View.
Second, reading an XML file is an easy task, use XDocument class for example:
var xDoc = XDocument.Load("projectRoot\config\UnsupportedBrowsers.config");
var versionKeys = xDoc.Descendants("Version").First().Descendants();
foreach(var key in versionKeys)
{
//Do something with the retrived keys..
}
Side note:
In any case, you're better cache this object in order to avoid of I/O blockings if each new incoming request need to use it.
Related
I want ta change another Webconfig but I'm getting erors
What I tried is
string path = "E:\\username\\myprojects\\myproject\\Web.config";
Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(path);
webConfig.AppSettings.Settings.Add("DBNAME", "DEV_TEMP");
webConfig.Save();
This said " Web.config denied relative virtual paths"
and another I tried on webconfig
<configuration>
<appSettings>
<add key="DBNAME" value="DEV_DEVELOPMENT"/>
</appSettings>
DBNAME value change to "DEV_TEMP"
XDocument doc=XDocument.Load("E:\\username\\myprojects\\myproject\\Web.config");
doc.Element("appSettings").Element("DBNAME").Value = "DEV_TEMP";
doc.Save("Web.config");
and it says Null reference
Assuming you have a good reason to do this, you could use something like:
var addElement = doc.Element("configuration").Element("appSettings").Elements().First(x => x.Attribute("key").Value == "DBNAME");
var valueAttribute = addElement.Attribute("value");
valueAttribute.Value = "DEV_TEMP";
Note that you also need to get the configuration element, and you can get the add element by selecting the element where the key attribute matches DBNAME as there could be multiple add elements. Also value is the attribute of add, not an element itself. See the XML Document Object Model (DOM)
for further information.
I'm trying to get the values from the oracle.manageddataaccess.client section in my App.config file. This section looks like this:
<oracle.manageddataaccess.client>
<version number="*">
<dataSources>
<dataSource alias="alias1" descriptor="connection string 1" />
<dataSource alias="alias2" descriptor="connection string 2" />
</dataSources>
</version>
</oracle.manageddataaccess.client>
I've tried using the ConfigurationManager API to read the values, but I haven't had any luck.
With:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["oracle.manageddataaccess.client"]
just returns an empty string.
config.Sections seems to only work for tags that are explicitly a section tag.
I just need to be able to read the dataSource values in this section.
Update:
config.Sections["oracle.manageddataaccess.client"].SectionInformation returns information about the section, and the GetRawXml() is getting closer to what I want, but I'm trying to get a specific subset of this.
I didn't find exactly what I was looking for, but I found a way around it.
If anyone else has the same issue, you can use XDocument and Linq to filter for what you need. You need to include your using statements: System.Linq and System.Xml.Linq
XDocument doc = XDocument.Parse(config.Sections["oracle.manageddataaccess.client"].SectionInformation.GetRawXml());
var value = from node in doc.Descendants("dataSource")
where node.Attribute("alias").Value == whatever
select node.Attribute("descriptor").Value;
I'm trying to pull data from the web config file as outlined by this msdn resource.
Here is my code:
System.Configuration.Configuration activeCampaignApiSetting1 =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(null);
if (activeCampaignApiSetting1.AppSettings.Settings.Count > 0) {
System.Configuration.KeyValueConfigurationElement activeCampaignApiKeySetting =
activeCampaignApiSetting1.AppSettings.Settings["ActiveCampaignApiKey"];
if (activeCampaignApiKeySetting != null) {
activeCampaignApiKey = activeCampaignApiKeySetting.Value;
}
System.Configuration.KeyValueConfigurationElement activeCamapignApiUrlSetting =
activeCampaignApiSetting1.AppSettings.Settings["ActiveCampaignApiUrl"];
if (activeCamapignApiUrlSetting != null) {
activeCampaignApiUrl = activeCamapignApiUrlSetting.Value;
}
}
When I try to instantiate this class:
var acs = new Acs(activeCampaignApiKey, activeCampaignApiUrl);
it throws an exception telling me that the values are blank.
The values in the web config file are there:
<add key="ActiveCampaignApiKey" value="apikey_removed" />
<add key="ActiveCampaignApiUrl" value="apiurl_removed" />
Anyone know where I may be going wrong?
Cheers
If they are appSetting inside web.config, you can access them via ConfigurationManager.AppSettings.
<?xml version="1.0"?>
<configuration>
<configSections>
<appSettings>
<add key="ActiveCampaignApiKey" value="apikey_removed" />
<add key="ActiveCampaignApiUrl" value="apiurl_removed" />
</appSettings>
</configSections>
</configuration>
string activeCampaignApiKeySetting
= ConfigurationManager.AppSettings["ActiveCampaignApiKey"];
string activeCamapignApiUrlSetting
= ConfigurationManager.AppSettings["ActiveCampaignApiUrl"];
Please make sure you reference System.Configuration, and include using System.Configuration; directive.
FYI: They return string value (not key value pair).
Ok so I have a better solution,
As I'm working with nopCommerce I need to use:
private readonly ISettingService _settingService = EngineContext.Current.Resolve<ISettingService>();
string apikey = _settingService.GetSettingByKey<string>("apikey_removed");
string apiurl = _settingService.GetSettingByKey<string>("apiurl_removed");
As outlined in this forum thread
Then in the administration backend under configuration > settings > all settings I add the key there.
This is a much better solution because if the api key or url ever need to be changed it can be done through the nopcommerce administration panel. rather than rebuilding/publishing the solution to a web server.
Hope this helps someone :)
I'm trying to read some configuration in my global.aspx Application_Start method. When I read ConfigurationManager.GetSection("system.web/httpHandlers") everything is fine:
ConfigurationManager.GetSection("system.web/httpHandlers")
{System.Web.Configuration.HttpHandlersSection}
base {System.Configuration.ConfigurationSection}: {System.Web.Configuration.HttpHandlersSection}
Handlers: Count = 48
But when I read ConfigurationManager.GetSection("system.webServer/handlers") (which contains my custom handlers, it returns null. What am I doing wrong?
The section looks like this:
<system.webServer>
<handlers>
<add verb="*" path="*.loc" name="LocalizedResourceStreamer"
type="CFW.WebUI.HttpHandlers.LocalizedResourceStreamer,WebUI" />
</handlers>
</system.webServer>
Notes:
Web.configs are nested, ConfigurationManager.GetSection takes nesting into account by default.
The overall problem is trying to see if *.loc files are being served.
So far:
Looks like the system.webServer is ignored.
Depending on your OS/setup, the system.webServer element may be configured to be ignored - and so the config system will not be constructing any inner configuration items from it. E.g. on my machine (WinXP, IIS 5.1), it's set to ignored by default.
Check the machine.config on the machine where this code is running, and see how the system.webServer element is configured. I don't have machines available with suitable later OSes at the moment, but it may be that this element is always set to be ignored - after all, that part of the config is for IIS' use, rather than our own.
try :
**p.s. my web.config contains : <httpHandlers> and not handlers as yours. change as necessarily :) - also the webserver vs system.web **
Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection webConfigSections = webConfig.GetSection("system.web/httpHandlers");
if (webConfigSections != null)
{
// PropertyInformationCollection t = webConfigSections.ElementInformation.Properties;
XDocument xmlFile = XDocument.Load(new StringReader(webConfigSections.SectionInformation.GetRawXml()));
IEnumerable<XElement> query = from c in xmlFile.Descendants("add") select c;
foreach (XElement band in query)
{
}
}
p.s. thats the problem with this section - he doesnt have a uniquee element name that can be taken. thats why you take it whole("add" element) and parse it.
I want to change the location where my application looks for the app.config file.
I know that I can use ConfigurationManager.OpenExeConfiguration() to access an arbitrary config file - however, when the .Net Framework reads the config file (for ConnectionStrings or EventSources, for instance), it will look at the default location. I want to actually change the location, globally for the entire .Net Framework (for my application, of course).
I also know that I can use AppDomainSetup to change the location of the app.config for a new AppDomain. However, that doesn't apply to the primary AppDomain of the application.
I also know that I can override function Main() and create a new AppDomain as above and run my application in that new AppDomain. However, that has other side-effects - for instance, Assembly.GetEntryAssembly() will return a null reference.
Given how everything else works in .Net, I would expect there to be some way to configure the startup environment of my application - via a Application Manifest, or some such - but I have been unable to find even a glimmer of hope in that direction.
Any pointer would be helpful.
David Mullin
I used the approach with starting another AppDomain from Main(), specifying the "new" location of the configuration file.
No issues with GetEntryAssembly(); it only returns null, when being called from unmanaged code - or at least it doesn't for me, as I use ExecuteAssembly() to create/run the second AppDomain, much like this:
int Main(string[] args)
{
string currentExecutable = Assembly.GetExecutingAssembly().Location;
bool inChild = false;
List<string> xargs = new List<string>();
foreach (string arg in xargs)
{
if (arg.Equals("-child"))
{
inChild = true;
}
/* Parse other command line arguments */
else
{
xargs.Add(arg);
}
}
if (!inChild)
{
AppDomainSetup info = new AppDomainSetup();
info.ConfigurationFile = /* Path to desired App.Config File */;
Evidence evidence = AppDomain.CurrentDomain.Evidence;
AppDomain domain = AppDomain.CreateDomain(friendlyName, evidence, info);
xargs.Add("-child"); // Prevent recursion
return domain.ExecuteAssembly(currentExecutable, evidence, xargs.ToArray());
}
// Execute actual Main-Code, we are in the child domain with the custom app.config
return 0;
}
Note that we are effectively rerunning the EXE, just as a AppDomain and with a different config. Also note that you need to have some "magic" option that prevents this from going on endlessly.
I crafted this out from a bigger (real) chunk of code, so it might not work as is, but should illustrate the concept.
I am not sure why you want to change the location of your config file - perhaps there can be different approach for solving your actual problem. I had a requirement where I wanted to share configuration file across related applications - I had chosen to use own xml file as it had given me extra benefit of having complete control over the schema.
In your case, it's possible to externalize sections of your config file to a separate file using configSource property. See here under "Using External Configuration Files" to check how it has been done for connection strings section. Perhaps, this may help you.
var configPath = YOUR_PATH;
if (!Directory.Exists(ProductFolder))
{
Directory.CreateDirectory(ProductFolder);
}
if (!File.Exists(configPath))
{
File.WriteAllText(configPath, Resources.App);
}
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = configPath,
LocalUserConfigFilename = configPath,
RoamingUserConfigFilename = configPath
};
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
Then use config member as you want.
Another approach is to leave the config file with the executable file and move the relevant changeable sections to external xml files which can be in whatever location you choose.
If you are using your config file in a readonly capacity, then you can add the relevant chunks to an XML file in a different location using XML Inlcude. This won't work if you are trying to write values back directly to app.config using the Configuration.Save method.
app.config:
<?xml version="1.0"?>
<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
<appSettings>
<xi:include href="AppSettings.xml"/>
</appSettings>
<connectionStrings>
<xi:include href="ConnectionStrings.xml"/>
</connectionStrings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/></startup>
</configuration>
ConnectionStrings.xml:
<?xml version="1.0"?>
<add name="Example1ConnectionString"
connectionString="Data Source=(local)\SQLExpress;Initial Catalog=Example1DB;Persist Security Info=True;User ID=sa;Password=password"
providerName="System.Data.SqlClient" />
<add name="Example2ConnectionString"
connectionString="Data Source=(local)\SQLExpress;Initial Catalog=Example2DB;Persist Security Info=True;User ID=sa;Password=password"
providerName="System.Data.SqlClient" />
AppSettings.xml:
<?xml version="1.0"?>
<add key="Setting1" value="Value1"/>
<add key="Setting2" value="Value2"/>
A file URI looks like this:
file:///C:/whatever.txt
You can even define failover files in case the one you are trying to reference is missing. This pattern is from https://www.xml.com/pub/a/2002/07/31/xinclude.html:
<xi:include href="http://www.whitehouse.gov/malapropisms.xml">
<xi:fallback>
<para>
This administration is doing everything we can to end the stalemate in
an efficient way. We're making the right decisions to bring the solution
to an end.
</para>
</xi:fallback>