I'm working on a C# class library that needs to be able to read settings from the web.config or app.config file (depending on whether the DLL is referenced from an ASP.NET web application or a Windows Forms application).
I've found that
ConfigurationSettings.AppSettings.Get("MySetting")
works, but that code has been marked as deprecated by Microsoft.
I've read that I should be using:
ConfigurationManager.AppSettings["MySetting"]
However, the System.Configuration.ConfigurationManager class doesn't seem to be available from a C# Class Library project.
What is the best way to do this?
For a sample app.config file like below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="countoffiles" value="7" />
<add key="logfilelocation" value="abc.txt" />
</appSettings>
</configuration>
You read the above application settings using the code shown below:
using System.Configuration;
You may also need to also add a reference to System.Configuration in your project if there isn't one already. You can then access the values like so:
string configvalue1 = ConfigurationManager.AppSettings["countoffiles"];
string configvalue2 = ConfigurationManager.AppSettings["logfilelocation"];
You'll need to add a reference to System.Configuration in your project's references folder.
You should definitely be using the ConfigurationManager over the obsolete ConfigurationSettings.
Update for .NET Framework 4.5 and 4.6; the following will no longer work:
string keyvalue = System.Configuration.ConfigurationManager.AppSettings["keyname"];
Now access the Setting class via Properties:
string keyvalue = Properties.Settings.Default.keyname;
See Managing Application Settings for more information.
Right click on your class library, and choose the "Add References" option from the Menu.
And from the .NET tab, select System.Configuration. This would include the System.Configuration DLL file into your project.
I'm using this, and it works well for me:
textBox1.Text = ConfigurationManager.AppSettings["Name"];
Read From Config:
You'll need to add a reference to the configuration:
Open "Properties" on your project
Go to "Settings" Tab
Add "Name" and "Value"
Get Value with using following code:
string value = Properties.Settings.Default.keyname;
Save to the configuration:
Properties.Settings.Default.keyName = value;
Properties.Settings.Default.Save();
You must add a reference to the System.Configuration assembly to the project.
You might be adding the App.config file to a DLL file. App.Config works only for executable projects, since all the DLL files take the configuration from the configuration file for the EXE file being executed.
Let's say you have two projects in your solution:
SomeDll
SomeExe
Your problem might be related to the fact that you're including the app.config file to SomeDLL and not SomeExe. SomeDll is able to read the configuration from the SomeExe project.
Try this:
string keyvalue = System.Configuration.ConfigurationManager.AppSettings["keyname"];
In the web.config file this should be the next structure:
<configuration>
<appSettings>
<add key="keyname" value="keyvalue" />
</appSettings>
</configuration>
Step 1: Right-click on references tab to add reference.
Step 2: Click on Assemblies tab
Step 3: Search for 'System.Configuration'
Step 4: Click OK.
Then it will work.
string value = System.Configuration.ConfigurationManager.AppSettings["keyname"];
I had the same problem. Just read them this way:
System.Configuration.ConfigurationSettings.AppSettings["MySetting"]
web.config is used with web applications. web.config by default has several configurations required for the web application. You can have a web.config for each folder under your web application.
app.config is used for Windows applications. When you build the application in Visual Studio, it will be automatically renamed to <appname>.exe.config and this file has to be delivered along with your application.
You can use the same method to call the app settings values from both configuration files:
System.Configuration.ConfigurationSettings.AppSettings["Key"]
As I found the best approach to access application settings variables in a systematic way by making a wrapper class over System.Configuration as below
public class BaseConfiguration
{
protected static object GetAppSetting(Type expectedType, string key)
{
string value = ConfigurationManager.AppSettings.Get(key);
try
{
if (expectedType == typeof(int))
return int.Parse(value);
if (expectedType == typeof(string))
return value;
throw new Exception("Type not supported.");
}
catch (Exception ex)
{
throw new Exception(string.Format("Config key:{0} was expected to be of type {1} but was not.",
key, expectedType), ex);
}
}
}
Now we can access needed settings variables by hard coded names using another class as below:
public class ConfigurationSettings:BaseConfiguration
{
#region App setting
public static string ApplicationName
{
get { return (string)GetAppSetting(typeof(string), "ApplicationName"); }
}
public static string MailBccAddress
{
get { return (string)GetAppSetting(typeof(string), "MailBccAddress"); }
}
public static string DefaultConnection
{
get { return (string)GetAppSetting(typeof(string), "DefaultConnection"); }
}
#endregion App setting
#region global setting
#endregion global setting
}
Also, you can use Formo:
Configuration:
<appSettings>
<add key="RetryAttempts" value="5" />
<add key="ApplicationBuildDate" value="11/4/1999 6:23 AM" />
</appSettings>
Code:
dynamic config = new Configuration();
var retryAttempts1 = config.RetryAttempts; // Returns 5 as a string
var retryAttempts2 = config.RetryAttempts(10); // Returns 5 if found in config, else 10
var retryAttempts3 = config.RetryAttempts(userInput, 10); // Returns 5 if it exists in config, else userInput if not null, else 10
var appBuildDate = config.ApplicationBuildDate<DateTime>();
If your needing/wanting to use the ConfigurationManager class...
You may need to load System.Configuration.ConfigurationManager by Microsoft via NuGet Package Manager
Tools->NuGet Package Manager->Manage NuGet Packages for Solution...
Microsoft Docs
One thing worth noting from the docs...
If your application needs read-only access to its own configuration,
we recommend that you use the GetSection(String) method. This method
provides access to the cached configuration values for the current
application, which has better performance than the Configuration
class.
I strongly recommend you to create a wrapper for this call. Something like a ConfigurationReaderService and use dependency injection to get this class. This way you will be able to isolate this configuration files for test purposes.
So use the ConfigurationManager.AppSettings["something"]; suggested and return this value. With this method you can create some kind of default return if there isn't any key available in the .config file.
Just for completeness, there's another option available for web projects only:
System.Web.Configuration.WebConfigurationManager.AppSettings["MySetting"]
The benefit of this is that it doesn't require an extra reference to be added, so it may be preferable for some people.
I always create an IConfig interface with typesafe properties declared for all configuration values. A Config implementation class then wraps the calls to System.Configuration. All your System.Configuration calls are now in one place, and it is so much easier and cleaner to maintain and track which fields are being used and declare their default values. I write a set of private helper methods to read and parse common data types.
Using an IoC framework you can access the IConfig fields anywhere your in application by simply passing the interface to a class constructor. You're also then able to create mock implementations of the IConfig interface in your unit tests so you can now test various configuration values and value combinations without needing to touch your App.config or Web.config file.
Please check the .NET version you are working on. It should be higher than 4. And you have to add the System.Configuration system library to your application.
You can use the below line. In my case it was working:
System.Configuration.ConfigurationSettings.AppSettings["yourKeyName"]
You must take care that the above line of code is also the old version and it's deprecated in new libraries.
The ConfigurationManager is not what you need to access your own settings.
To do this you should use
{YourAppName}.Properties.Settings.{settingName}
I was able to get the below approach working for .NET Core projects:
Steps:
Create an appsettings.json (format given below) in your project.
Next create a configuration class. The format is provided below.
I have created a Login() method to show the usage of the Configuration Class.
Create appsettings.json in your project with content:
{
"Environments": {
"QA": {
"Url": "somevalue",
"Username": "someuser",
"Password": "somepwd"
},
"BrowserConfig": {
"Browser": "Chrome",
"Headless": "true"
},
"EnvironmentSelected": {
"Environment": "QA"
}
}
public static class Configuration
{
private static IConfiguration _configuration;
static Configuration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json");
_configuration = builder.Build();
}
public static Browser GetBrowser()
{
if (_configuration.GetSection("BrowserConfig:Browser").Value == "Firefox")
{
return Browser.Firefox;
}
if (_configuration.GetSection("BrowserConfig:Browser").Value == "Edge")
{
return Browser.Edge;
}
if (_configuration.GetSection("BrowserConfig:Browser").Value == "IE")
{
return Browser.InternetExplorer;
}
return Browser.Chrome;
}
public static bool IsHeadless()
{
return _configuration.GetSection("BrowserConfig:Headless").Value == "true";
}
public static string GetEnvironment()
{
return _configuration.GetSection("EnvironmentSelected")["Environment"];
}
public static IConfigurationSection EnvironmentInfo()
{
var env = GetEnvironment();
return _configuration.GetSection($#"Environments:{env}");
}
}
public void Login()
{
var environment = Configuration.EnvironmentInfo();
Email.SendKeys(environment["username"]);
Password.SendKeys(environment["password"]);
WaitForElementToBeClickableAndClick(_driver, SignIn);
}
Another possible solution:
var MyReader = new System.Configuration.AppSettingsReader();
string keyvalue = MyReader.GetValue("keyalue",typeof(string)).ToString();
I have been trying to find a fix for this same issue for a couple of days now. I was able to resolve this by adding a key within the appsettings tag in the web.config file. This should override the .dll file when using the helper.
<configuration>
<appSettings>
<add key="loginUrl" value="~/RedirectValue.cshtml" />
<add key="autoFormsAuthentication" value="false"/>
</appSettings>
</configuration>
extra : if you are working on a Class Library project you have to embed the settings.json file.
A class library shouldn't really be directly referencing anything in
app.config - the class doesn't have an app.config, because it's not an
application, it's a class.
Go to the JSON file's properties.
Change Build Action -> Embedded resource.
Use the following code to read it.
var assembly = Assembly.GetExecutingAssembly();
var resourceStream = assembly.GetManifestResourceStream("Assembly.file.json");
string myString = reader.ReadToEnd();
now we have a JSON string we can Deserialize it using JsonConvert
if you didn't embed the file inside the assembly you can't use only the DLL file without the file
I'm using Visual Studio for Mac version 17.0.6.
As you can see on this screenshot it is not possible to add a reference to System.Configuration.
Solution:
install NuGet Package - System.Configuration.ConfigurationManager.
Create app.config file and set "Build action" to "EmbeddedResource"
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="name" value="Joe"/>
</appSettings>
</configuration>
using System.Configuration;
enjoy)
string name = ConfigurationManager.AppSettings["name"];
BTW: Do not add an app.config for a library
I found the answer in this link https://stackoverflow.com/a/1836938/1492229
It's not only necessary to use the namespace System.Configuration. You have also to add the reference to the assembly System.Configuration.dll , by
Right-click on the References / Dependencies
Choose Add Reference
Find and add System.Configuration.
This will work for sure.
Also for the NameValueCollection you have to write:
using System.Collections.Specialized;
Here's an example: App.config
<applicationSettings>
<MyApp.My.MySettings>
<setting name="Printer" serializeAs="String">
<value>1234 </value>
</setting>
</MyApp.My.MySettings>
</applicationSettings>
Dim strPrinterName as string = My.settings.Printer
I installed System.Configuration.ConfigurationManager -Version 4.7.0 in one of my project that is as a class library project and then I added app.config file in it.
I've applied ASP.NET Core 3.1 in my project.
Now I want to get value of section.
For this purpose I did it like this:
namespace Alpha.Infrastructure.PaginationUtility
{
public class PagingInfo
{
public virtual int DefaultItemsPerPage { get; set; } = int.Parse(System.Configuration.ConfigurationManager.AppSettings["DefaultItemsPerPage"]);
}
}
But I got "ArgumentNullException: Value cannot be null" error!
How can I solve this problem?
App.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DefaultItemsPerPage" value="3"/>
</appSettings>
</configuration>
SOLUTION
To solve your problem add the App.config file to the ENTRY POINT project.
This is your executable project like WinForms or WPF or Console App.
Not to the Class Library project.
The reason is when the app compiles the App.config gets renamed to "MyProjectName.Ext.config".
For example if you have Class Library project called ConfigUtils the file will be output as ConfigUtils.dll.config.
But ConfigurationManager expects the name of the entry point plus config.
So if your ConfigUtils is referenced from let's say MyApp Console project. Then the ouput file will be MyApp.exe.config
So for the ConfigurationManager to work right off without any further meddling you need to place your App.config file in the entry point project.
.NET CORE WAY
I recommend NOT to use ConfigurationManager...
Just use the new way of doing it!
To demonstrate how to do it in .NET Core I created a console app using .NET Core 3.1.3
I added also an extension method to wrap up the functionality for reusability.
First my code:
using Microsoft.Extensions.Configuration;
using System;
class Program
{
private static IConfiguration _configuration;
static void Main(string[] args)
{
_configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.Build();
var itemsPerPage = _configuration.GetValue<int>("appSettings", "DefaultItemsPerPage");
Console.WriteLine("Items Per Page:" + itemsPerPage.ToString());
Console.ReadLine();
}
}
public static class ConfigExtenstions
{
public static T GetValue<T>(this IConfiguration configuration, string configSection, string keyName)
{
return (T)Convert.ChangeType(configuration[$"{configSection}:{keyName}"], typeof(T));
}
private static T GetValue<T>(string configSection, string configSubSection, string keyName)
{
return (T)Convert.ChangeType(Configuration[$"{configSection}:{configSubSection}:{keyName}"], typeof(T));
}
}
My appsettings.json file looks like this:
{
"appSettings": {
"DefaultItemsPerPage": 3
}
}
The confuguration file can be modeled however you want. In this case I made it look like your app.config file.
Also I right clicked on the appsettings.json file in visual studio and set to "Copy Always".
For all of this to work you need to add 2 NuGet packages like this:
NOTES:
You can use other "Providers" to pull configuration from XML, INI and other types of files and sources. For that you need to add other NuGet packages etc.
This link even though it talks about ASP.NET Core Configuration it is very useful because the same concepts apply.
I want to use a .NET settings file in an external dll library. This article explains exactly what I am trying to do.
partial class LastState
{
public LastState() : base(new ConfigurationFileApplicationSettings("LastState.config", typeof(LastState))) { }
}
Unfortunately, using this implementation, it is not possible to save settings back to the config file. If I try to use Save(), SetPropertyValues throws a NotSupportedException. Is there any way to save a .NET settings file from an external dll library?
I would use custom configuration files.
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = #"d:\test\justAConfigFile.config.whateverYouLikeExtension";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel)
Have a look here for more détails.
You can save with
config.AppSettings.Settings["YourThing"].Value = "New Value";
config.Save();
I am attempting to create a custom ASP.NET MVC4 template. I start from the Basic MVC4 template, make my modifications, and then use the "Export Template" wizard to create the template zip file. Right now (almost) everything is working smoothly. When I use the template to create a new MVC application, it recreates all of my settings the way I want them except one. For some reason, it changes the project properties for my web application to have a Start Action of "Current Page" instead of "Specific Page" (like it was in the original template and like it is in my template). This setting is in the project properties under the Web tab. Here is what it is set to in my template application (before I generate the actual template zip file):
And here is what it is like when I create a new project using that template:
How do I modify my template to set this setting properly (or more accurately, how do I force it to remember what I set initially)?
Edit: answer revised due to misunderstanding of both original request and behavior of previously proposed solution.
To set the Start Action of a custom MVC project template, you'll need to create a dll with a class that implements the Microsoft.VisualStudio.TemplateWizard.IWizard interface. To use the wizard dll, you'll either need to copy it to Visual Studio's probing path, which is (VS2010 Install Dir)\Common7\IDE, (VS2010 Install Dir)\Common7\IDE\PrivateAssemblies, or (VS2010 Install Dir)\Common7\IDE\PublicAssemblies. If you don't put the compiled dll in one of those directories, you'll need to strong name and sign the dll and add it to the GAC and get the publickeytoken of the dll and add it to the Assembly element in the vstemplate file.
In testing the following code I copied the dll to (VS2010 Install Dir)\Common7\IDE\PrivateAssemblies, so the dll is not signed.
Wizard code
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;
namespace WarrenG.StartAction {
public class Wizard : IWizard {
private readonly Dictionary<string, object> data = new Dictionary<string, object>();
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary,
WizardRunKind runKind, object[] customParams) {
if (replacementsDictionary.ContainsKey("$wizarddata$")) {
string xml = replacementsDictionary["$wizarddata$"];
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach (XmlNode node in doc.ChildNodes) {
data.Add(node.Name, node.InnerText);
}
}
}
public bool ShouldAddProjectItem(string filePath) {
return true;
}
public void RunFinished() {
}
public void BeforeOpeningFile(ProjectItem projectItem) {
}
public void ProjectItemFinishedGenerating(ProjectItem projectItem) {
}
public void ProjectFinishedGenerating(Project project) {
if (data.ContainsKey("WebApplication.DebugStartAction")) {
project.Properties.Item("WebApplication.DebugStartAction").Value =
data["WebApplication.DebugStartAction"];
} else {
project.Properties.Item("WebApplication.DebugStartAction").Value = 1;
}
}
}
}
Add wizard specific elements to vstemplate file of custom MVC project template
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateContent>
<!-- various template content -->
</TemplateContent>
<!-- add the following -->
<WizardExtension>
<Assembly>WarrenG.StartAction, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=null</Assembly>
<FullClassName>WarrenG.StartAction.Wizard</FullClassName>
</WizardExtension>
<WizardData>
<WebApplication.DebugStartAction>1</WebApplication.DebugStartAction>
</WizardData>
</VSTemplate>
The start actions on the project page appear to be numbers 0 through 4, following their display order. A value of 1 corresponds with Specific Page.
Unfortunately, or fortunately, depending on the side of the coin you're on...
Like the "Startup Project" setting, that setting is NOT part of the project file or the template file that's generated. It is stored in the "SUO" or Solution User Options, file. The SUO is not included by the template generator.
Some background on the SUO file: http://msdn.microsoft.com/en-us/library/bb165909(v=vs.80).aspx
I am trying to update a custom configuration section of a web.config file during the installation of my product in a custom action. I wanted to use the actual configration classes to do this however when the installer runs it loads my installer class but then the
Configuration.GetSection throw a File Not Found exception as it is trying to load my custom section class from the windows system directory. I managed to get this to work by copying the required assemblies into the windows system directory but this is not an ideal solution as I cannot guarantee I will always have access to that directory.
How else can I solve this problem?
My update code looks like this
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public override void Install(System.Collections.IDictionary stateSaver)
{
//some code here
webConfig = WebConfigurationManager.OpenWebConfiguration("MyService");
MyCustomSection mySection = webconfig.GetSection("MyCustomSection") //<--File Not Found: CustomConfigSections.dll
//Update config section and save config
}
}
My config file looks like this
<configuration>
<configSections>
<section name="myCustomSection" type="CustomConfigSections.MyCustomSection, CustomConfigSections" />
</configSections>
<myCustomSection>
<!-- some config here -->
</myCustomSection>
</configuration>
Hope you would understand the answer the way it is intended.
Assuming that you have setup the installer to have your project output. If Not
Right Click on installer Project click add->Project Output->select your project
and then you can continue using your code.
Moreover if you are using dll except the .net Ones make sure to change there
properties to copylocal = true
If You want to read the element Before Installation use BeforeInstall Event
Handler and try reading your file. ihope your problem will be solved
If in case You want to read the element after installation Right Click On
installer project Click view->customActions->On Install Click Add Custom Action
->Select Application Folder -> Select Primary output from your project and click
ok .
Now Click on primary output and press F4 and in Custom Action Data write
/DIR="[TARGETDIR]\"
and after that write your code as follows.
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
public ProjectInstaller()
{
this.InitializeComponent();
}
private void InitializeComponent()
{
this.AfterInstall += new InstallEventHandler(ProjectInstaller_AfterInstall);
}
void ProjectInstaller_AfterInstall(object sender, InstallEventArgs e)
{
string path = this.Context.Parameters["DIR"] + "YourFileName.config";
// make sure you replace your filename with the filename you actually
// want to read
// Then You can read your config using XML to Linq Or you can use
// WebConfigurationManager whilst omitting the .config from the path
}