Solution with different project and shared configSections - c#

I have a solution with three projects.
Project1 (Windows Application)
Project2 (Windows Application)
Project3 (Class Library)
Project1 and Project2 have their own app.config files with appSettings. Now I want the add some appSettings in the Project3. But I don't want the write the new settings in both app.config files. I want a new configfile/section for my shared solution.
How can I create my own config file in Project3 and reference from Project1 and Project2?

Have you tried:
<appSettings configSource="shared.config">
</appSettings>
Then in shared.config
<?xml version="1.0"?>
<appSettings>
<add key="foo" value="bar" />
</appSettings>

Here is a working example. It's not perfect, but it's working:
Create a share.config in Project3
<?xml version="1.0" encoding="utf-8" ?>
<shareConfig
config1="value1">
</shareConfig>
Create a ShareConfig.cs file in your Project3
public class ShareConfig : ConfigurationSection
{
[ConfigurationProperty("config1", IsRequired = true)]
public string Config1
{
get { return (string)base["config1"]; }
set { base["config1"] = value; }
}
}
Add the config File as a Link the Project1 and Project2
Add the following code in your app.config (Project1 and Project2):
<configSections>
<section name="shareconfig" type="[classname], [projectname], Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<shareconfig configSource="App.Share.config"/>
Now you can use your new config Section like this:
ShareConfig config = (ShareConfig )ConfigurationManager.GetSection("shareConfig ");

Related

C# - The configuration section was not found error using aspnet_regiis.exe

I am trying to Encrypt sensitive connection string information inside my app.config file for a C# applicaiton that I am developing. I am using the following command from the VS command promt running as administrator:
aspnet_regiis.exe -pef "Credentials" "C:\Users\.....\MyProjectFolderDir"
This is the structure of my app.config file:
<?xml version="1.0" encoding="utf-8" ?>
<config>
<configSections>
<section name="ApplicationSettings" type="sometype"/>
<section name="WebSettings" type="sometype"/>
<section name="Credentials" type="sometype"/>
<section name="SQLServerSettings" type="sometype"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<ApplicationSettings Mode="mymode"
FileSearchMode="myfilemode"
SubtractHoursDebugging="0"/>
<WebSettings WebApiServers=""
CredentialMethod="mymethod"/>
<Credentials
Domain="mydomain"
UserName="myusername"
Password="mypassword"/>
<SQLServerSettings
ConnectionString="Server=***********"/>
</config>
However, I keep getting the following error:
Encrypting configuration section...
The configuration section 'Credentials' was not found.
Failed!
How can I get this to encrypt my section?
Your config file should start with <configuration> element and not <config>. Since it's <config> aspnet_regiis.exe thinning Credentials as nested element and thus the error. With your current config file the command should be
aspnet_regiis.exe -pef "config\Credentials" "C:\Users\.....\MyProjectFolderDir"
First of all here's an answer that you can learn from about custom configuration section How to create custom config section in app.config? and here is an example from msdn https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
Second, the type usually refer to a real model so you should enter the namespace and the class that you created to model the type of configuration you would like to use like so:
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<sampleSection setting1="Value1" setting2="value two"
setting3="third value" />
</configuration>
Hope it helps
So as it turns out, aspnet-regiis.exe is exclusively for web.config files. It doesn not work with app.config files unless you rename to web.config. Instead of renaming my app.config everytime I wanted to encrypt/decrypt, I ended up creating a class that would handle this each time I ran the application. Make sure you are using the following:
using System.Configuration;
using System.Web.Security;
Class:
internal class Crypto
{
internal static AppSettingsSection GetEncryptedAppSettingsSection(string exeConfigName)
{
// Open the configuration file and retrieve
// the connectionStrings section.
System.Configuration.Configuration config = ConfigurationManager.
OpenExeConfiguration(exeConfigName);
AppSettingsSection section =
config.GetSection("appSettings")
as AppSettingsSection;
EncryptConfigSection(config, section);
return section;
}
internal static ConnectionStringsSection GetEncryptedConnectionStringsSection(string exeConfigName)
{
// Open the configuration file and retrieve
// the connectionStrings section.
System.Configuration.Configuration config = ConfigurationManager.
OpenExeConfiguration(exeConfigName);
ConnectionStringsSection section =
config.GetSection("connectionStrings")
as ConnectionStringsSection;
EncryptConfigSection(config, section);
return section;
}
internal static void EncryptConfigSection(System.Configuration.Configuration config, ConfigurationSection section)
{
//Ensure config sections are always encrypted
if (!section.SectionInformation.IsProtected)
{
// Encrypt the section.
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
// Save the current configuration.
config.Save();
}
}
}

Getting a ConnectionString from app.config

I have a Web project which calls a library project (DataAccess) to retrieve some data from the database. I added an App.config file (Add -> New Item -> Application Configuration File) to the DataAccess project and added a connectionString section like this:
<configuration>
<connectionStrings>
<add name="local"
connectionString="Data Source=.\sql2008;Initial Catalog=myDB;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
In the DataAccess project, I have the BuildConnection method:
internal static SqlConnection BuildConnection()
{
string connectionString = ConfigurationManager.ConnectionStrings["local"].ToString();
return new SqlConnection(connectionString);
}
When I call the method from the Web project, it throws a null exception complaining that the "local" connection string doesn't exist. After debugging it for a while I added the same connection string to the Web.config of the Web project, and now it works fine. The problem though is that I want to isolate the DataAccess project from the Web project, in other words, I want the DataAccess project to use its own app.config file no matter who calls it. Is this even possible? Any help would be appreciated.
at runtime, there is just one config file. so the config file of the active project is only
considered. also, you cannot have a class library project as an active/startup project i.e.
say you have 4 Projects in your solution, and each of them has a config file, then when you run the application, only the active project's(the one which is your startup project) config file is recognized.
Now what can you do?
if you just want to isolate the sections of the config file, then you can have config file in each of your Projects, which in turn, are referenced in the main projects config i.e.
Web.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings file="YourSettings.config">
<add key="KeyToOverride" value="Original" />
<add key="KeyToNotOverride" value="Standard" />
</appSettings>
<system.web>
<!-- standard web settings go here -->
</system.web>
YourSettings.config:
<appSettings>
<add key="KeyToOverride" value="Overridden" />
<add key="KeyToBeAdded" value="EntirelyNew" />
</appSettings>
read more about it here
if you want to have separate config files for your active project itself, than that's whole different story altogether.
its kind of ugly tweak, but read about it here
An app.config is used when you use in an Application. For a library project using a app config file not helps. Even you put it reference library the code will be in web server.
So this type isolation has no sense for any security issue.
But approach of putting things to the right place you are right, the problem is when you reference a dll it doesn't include the dll project's config.
If you want more :) Just read app.config in your lib project and using a code generator create a connection string object such as public static string ConnectionString = $GeneratedCode$;
Yes, it's possible.
Your app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="foo" value="bar"/>
</appSettings>
</configuration>
Your DataAccess layer:
namespace MyApp.DataAccess
{
public class DB
{
public string cfg;
public DB()
{
var asmName = System.Reflection.Assembly.GetAssembly(this.GetType()).GetName().Name;
var asmPath = System.Web.HttpContext.Current.Server.MapPath(#"bin\" + asmName + ".dll");
var cm = ConfigurationManager.OpenExeConfiguration(asmPath);
this.cfg = cm.AppSettings.Settings["foo"].Value;
}
}
}
Here's how to use it:
namespace MyApp.WebApp
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var db = new MyApp.DataAccess.DB();
Response.Write(db.cfg);
}
}
}
When you compile data access project, it'll generate a MyApp.DataAccess.dll.config out of your app.config content. Add MyApp.DataAccess.dll.config and MyApp.DataAccess.dll to your web app project and make sure to mark Copy To Output Directory to Copy if newer for MyApp.DataAccess.dll.config.

Read AppSettings from MEF plugin

I would like to access the values in the ConfigurationManager.AppSettings object from a MEF plugin which has its own app.config file.
However, the keys from the app.config file are not present in AppSettings after the plugin is loaded.
The keys from the application loading the plugin are still present.
I noticed that using a Settings.settings file allows this behaviour, via the app.config file, so the file must be being loaded somehow.
My plugin looks like:
[Export(IPlugin)]
public class Plugin
{
public Plugin()
{
// reads successfully from app.config via Settings object
var value1 = Settings.Default["Key1"];
// returns null from app.config via ConfigurationManager
var value1 = ConfigurationManager.AppSettings["Key2"]
}
}
The app.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="..." >
<section name="Plugin.Settings" type="..." />
</sectionGroup>
</configSections>
<appSettings>
<add key="Key2" value="Fails" />
</appSettings>
<applicationSettings>
<Plugin.Settings>
<setting name="Key1" serializeAs="String">
<value>Works</value>
</setting>
</Plugin.Settings>
</applicationSettings>
</configuration>
I can manually load the app.config file with:
var config = ConfigurationManager.OpenExeConfiguration("Plugin.dll");
var value = AppSettings.Settings["Key2"].Value
but this seems more like a workaround than a solution.
Is there a way to access a MEF plugin's <appSettings> directly, from inside the plugin?
If not, what is recommended?
By default the ConfigurationManager loads the .config for the entry assembly, i.e. the assembly that started the currently executing process.
The correct way to do this would be something like this:
[Export(IPlugin)]
public class Plugin
{
public Plugin()
{
var config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
var value = config.AppSettings.Settings["Key2"].Value;
}
}
This would make the plugin automatically open the .config for the DLL it was compiled in, and fetch values from there.
I'd recommend you to use a dependency injection tool like Unity, in order to provide to your plug-ins the configuration they required. By proceeding in this way, your plug-ins will no longer need to reference System.Configuration.dll.

dll Configuration file (dllName.dll.config)

I am developing a plugin for a .NET 4 application and I want to add a config file to the dll as I dont want to put the configuration in the main config file.
I have added the app.config t the project and it is correctly compile and dllName.dll.config generated.
Here is my configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="MyTabsConfig" type="NewApp.UI.MyTabsConfigHandler, NewApp.UI" />
</configSections>
<MyTabsConfig>
<MyTabs>
<MyTab Name="First" Leads="2" />
<MyTab Name="Second" Leads="4" />
<MyTab Name="Third" Leads="1" />
</MyTabs>
</MyTabsConfig>
</configuration>
Now I have 1 problems:
If I copy the file in the ExtraPlugins directory of my main application, NewApp.UI.dll cannot be found when calling GetSection("MyTabsConfig"). I think it is looking in the main application folder.
Thanks.
Have you tried something like this?
ConfigurationSection section = ConfigurationManager.OpenExeConfiguration("myConfig.config").GetSection("mySection");

How to define a ConfigurationSection

So this a new one for me.
I'm trying to define a ConfigurationSection class in my class library that pulls from App.Config in my WinForms app. I've never done this before but from following examples this is where I've got to.
app.config in my WinForms app
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ReportEngineConfig" type="Optima.ReportEngine.ReportEngineConfig" allowDefinition="Everywhere" allowLocation="true"/>
</configSections>
<ReportEngineConfig>
<ReportObjectVariableRegEx value="test" ></ReportObjectVariableRegEx>
</ReportEngineConfig>
</configuration>
And my ConfigurationSection class in my seperate class library.
using System.Configuration;
namespace Optima.ReportEngine
{
public class ReportEngineConfig : ConfigurationSection
{
[ConfigurationProperty("ReportObjectVariableRegEx")]
public string ReportObjectVariableRegEx
{
get
{
return (string)this["value"];
}
}
}
}
So any chance anyone can point out where I've gone wrong
Thanks!
Your type tag needs to reference the assembly name, not just the type name:
type="Optima.ReportEngine.ReportEngineConfig, Optima.ReportEngineAssembly"
Where the section after the comma is the name of the assembly containing ReportEngineConfig. You'll also have to make sure the application that is using this app.config has referenced the same assembly containing ReportEngineConfig.
Also you can get rid of the allowDefinition and allowLocation tags... you've put the defaults in.

Categories