I have a Solution with 3 projects in, each project needs access to certain settings. I'm looking for a way to have these setting values available to any project from 1 distinct source. I cant use the .Config file as that is relevent to that particular project.
I could use the database but have been told this is not good practice (Without an reason)
Any ideas?
You could do this:
create a solution.config in your solution folder
in each project's app.config, add this to your <appSettings> node:
<appSettings file="solution.config">
....
</appSettings>
You would have to put symbolic links to your common solution.config in each project folder - but you could have one single physical file that you share amongst the projects.
The <appSettings> node is the only one that allows that sort of "cummulative" settings - those from the file specified in the file= will be added to your app settings, but potentially overwritten by anything you specify explicitly in your app.config.
On the other hand, yes, of course, you could use the database. We do that, too, in most of our projects, since we typically do have access to the database, but not to the file system in the client's server machines. I don't see why that should necessarily be a bad thing - we have settings for DEV, TEST and PROD in a table - so you have all your settings in one place - and we pick those settings we need when we need them. Works just fine - of course, some settings like the connection strings to the database cannot be stored there - but the bulk of our config info is. Again: I really don't see any reason why this should be a bad choice per se - so unless your source can back his/her statement up with some facts and reasons, I'd ignore it.
You can define configSource attribute in a defined configSection, to reference an external file from which to load your properties.
Here you can find an example:
Is there any way for an App.config file to reference another full config file? (.NET)
You can also use a DB of course, but that would probably involve developing some kind of configuration console, since it's not a good practice to manage config attributes directly into DB.
Otherwise you can create your config file (an xml, or yaml for example) and create your own shared config parser.
I create a class to hold system-wide settings using either a Singleton pattern, or a Global instance (whichever you preference is).
If another project is in the solution, it can see the class (when references are added).
This also decouples the presentation of the settings from the storage mechanism (database, config file, custom XML file, whatever), and if you design to the interface, it makes unit testing more flexible, too.
You could add an entry into each projects .config file that points to the global one. You would need to read that in three places though.
Another solution that springs to mind is to put your common settings into their own assembly with it's own .config file. You then include that assembly in each of your projects. The .config file is read in the assembly and you can read out those values you need.
What kinds of settings?
You can use the system wide machine.config and web.config files for settings that apply across an entire machine.
\Windows\Microsoft.NET\Framework[64]\[version]\config\machine.config
\Windows\Microsoft.NET\Framework[64]\[version]\config\web.config
You could use the registry if you have access to it. Then all you would need is a class to read them out (and possiblty one to put them in) and each project could use that class to read them.
The major downside though is that you would have to add the settings to each machines registry that you run your solution on.
Related
We have a web application running on-premise at a variety of customers. The web.config contains lots of
stuff which is "part of our application" (such as most of the <system.web> and <system.webServer> blocks) and
stuff which needs to be customized (connection strings, app settings, and various custom tags).
During updates, part 1 should be replaced and part 2 should be left as it is. Ideally, I'd have a web.app.config and a web.custom.config, so I can replace only the first one. Of course, IIS would need to magically "merge" those at run time, which it does not do.
I found the following approaches:
Put the custom stuff in external files, i.e. <appSettings configSource="appSettings.config"/>.
I cannot use that, because it can only be used for complete sections. But, for example, the aspnet:MaxHttpCollectionKeys setting is a value that should be controlled by the application, whereas other app settings values should be customizable.
Parameterization or Web.Config Transformation.
I cannot use that, because our customers have various versions of our application installed. Thus, I need to replace the application-specific parts of web.config rather than transforming individual tags. In addition, I'd like to avoid adding msdeploy to our deployment process (xcopy plus some scripts to create the IIS apps and configure them work great at the moment). Oh, and I'd still have one big web.config with application-specific and customer-specific stuff meshed together.
Is there some elegant solution that I've missed?
It's true that configSource is used for complete sections, but appSettings has a special attribute called file which can be used to reference a file to be 'merged' into the appSettings list. See https://msdn.microsoft.com/en-AU/library/ms228154(v=vs.85).aspx for more details. I've used extensively to merge in an appSettings.config file with environment specific values - either local dev values (as contained in the repo) or a file that is dumped onto the server with environment specific settings. Helpful when promoting a build artifact through qa, uat, prod environments etc. For you, that file could contain your customer specific values and would not change when you deploy updates.
An alternative approach would be to refactor your customer specific configuration into a Custom Configuration Section. As well as giving you typed access to the configuration values, you can load it from a section in the web.config, load it from a section in the web.config that references another file via configSource, or you can load it directly from a separate file.
You can then leave your application configuration in the appSettings, or move it into a separate custom configuration section.
This related question has an answer which describes including/referencing additional config files from the default config file: How to read values from multiple Configuration file in c# within a single project?
Is that the only (sensible) way to do this or does C# allow me to freely access different config files? Is there something inherently special about app.config?
My personal experience with Config files is that if you want to read them programatically or to add extra fields, etc, you have to work a lot. That is why I usually just create my own configuration code. It might sound as reinventing the wheel, but the configuration needs to be easily read and modified by people. Also its format might change. Depending on your config needs a simple text file or a json style config might be more accessible.
If you want to do it with .NET's method, the ConfigManager class allows you to open/change .config files, assuming you have all the elements described as classes somewhere.
So, I inherited a project that seems to be using Spring.net extensively to do dependency injection. Every executable module implements a method where it goes to the Application config file for the given module and pulls a value along the lines of assembly://Config/Company.Protocol.Config/DIConfig.xml with the middle bit of "Company.Protocol.Config" being slightly different for different executables, bearing a name similar, but not identical to, the project. That XML file seems to be contained within a Config directory at the base of the solution holding the project. While I feel that things are a bit overcomplicated, I see what they're aiming for, storing references to various processing routines in that DIConfig.xml file so that they can be injected.
The problem I'm running into is that I can't actually seem to navigate to those XML files with the specified path above, and my attempts to understand Spring.net don't seem to go far enough to understand where they plan to go with the "Assembly://" bit. I get a Could not resolve resource location error. I've tried contacting the person who last worked with the code, but apparently they inherited it too, and have avoided messing with it for fear of breaking it.
I think that the intent of the line above is to go to the base of the assembly, then the Config directory or project, then get the DIConfig.xml there, but when I try to use that, it can't find the file. I've tried removing the bit between Config and DIConfig.xml just in case this was a matter of there used to have been directories in between, but no dice. I can get it to "work" by dropping the DIConfig.xml file into the same location as the executable and changing the file to be read to simply "DIConfig.xml", thus in the same directory, but of course, that's not very extensible, particularly when I try to run the service that uses this.
The assembly:// tells Spring.net to use the "assembly" protocol to locate the resource. It has the general format assembly://<AssemblyName>/<NameSpace>/<ResourceName>. So in the case of assembly://Config/Company.Protocol.Config/DIConfig.xml there should be an assembly named Config (not necessarily the same as the project name; check the properties). The xml file is contained in the source project that holds the source for the assembly.
Folders in the project can add to the namespace; so if the root namespace of the project is Company.Protocol, then you'll find your xml file in a folder named Config.
The xml file should be marked as an embedded resource. See section 5.2.2.1 of the docs for more.
Ok so i have 2 classes so far that i want to put in my common dll, logger and db. im moving them from my current project to a new class library project and changing their namespaces and whatnot. The issue I am having is that I wish to use the app config of my application (or any app that I want to reference my commonlib.dll) but I dont know how to use the referencing projects app.config. Is there any way to do this?
The OpenExeConfiguration() methods of ConfigurationManager are your ticket. One of them will take a path to the executable, allowing you to open the app config of a specified application (even a different one; you can use this technique to change the configuration of another application before launching it with Process.Start()). The other one will open the app.config of the current application (even if your library is used by multiple apps) for a specified user level (All users, current roaming user, and current roaming and local user). Usually, when dealing with an actual app.config, you want the one that applies to all users; the per-user configs are stored in each user's AppData folders.
Also, one last thing; unless your library has its own config file, the ConfigurationManager properties, like AppSettings, will be populated based on the current executable's app.config. So it could be as simple as using those properties. Keep in mind that those properties are read-only and only loaded once at program startup, so if you make changes to your config during program execution that you want to be effective immediately, it's better to explicitly load/save config files.
We have many environments and thinking of creating dynamic application configuration as part of CI. The configuration values will be stored in Database using WPF. Operation team manages the app for new app config entries.
The problem I am facing is how can I dynamically create the config and validate it? Opinions..? Thanks in advance.
If the number of configurations is finite and known (test, UAT, production desktop, production mobile, etc), you can take advantage of the configSource attribute found on the AppSettings, ConnectionStrings and ConfigSection elements. Here's the basic premise; create an AppSettings.xyz.config file for each configuration, where xyz is the name of the configuration ("local" "test", "uat", "prod", etc). Create a single app.config file that uses a <!ENTITY config "xyz"> definition, and has configSource attributes for various sections set similar to:
<appsettings configSource="appSettings.&config.config">
Now, in deployment logic, you change one thing; the string literal defined by the entity. This change is simple enough that you don't even really need XML parsing to make the change; just slurp the file into memory with a FileStream, find the entity definition, make the change and spit the new content back out into the file. If you're using an installer, you can control which child configs are installed, or just put them all out there for simplicity.
Take a look at T4. You can create a skeleton .config file with certain variables that are filled from the database to generate the environment-specific file.