What's the difference between the WebConfigurationManager and the ConfigurationManager?
When should I use one over the other?
UPDATED
I just looked at the WebConfigurationManager, and for some reason, you can't access the connection strings as you do in the ConfigurationManager (like an array). Can anyone tell me why MS made it like this? It seems to be a pain to get the connection string you need using the WebConfigurationManager.
UPDATED AGAIN with CAVEAT!
If you don't have a reference to the System.Configuration namespace added to your project, then Visual Studio will show an error when you try and access the WebConfigurationManager.ConnectionStrings like an array!
WebConfigurationManger knows how to deal with configuration inheritance within a web application. As you know, there could be several web.config files in one applicaion - one in the root of the site and any number in subdirectories. You can pass path to the GetSection() method to get possible overridden config.
If we'd looke at WebConfigurationManager with Reflector then things are clear:
public static object GetSection(string sectionName)
{
...
return ConfigurationManager.GetSection(sectionName);
}
public static object GetSection(string sectionName, string path)
{
...
return HttpConfigurationSystem.GetSection(sectionName, path);
}
WebConfigurationManager is made specifically for ASP.NET applications.
WebConfigurationManager provides additional methods to load configuration files applicable to Web applications.
ConfigurationManager provides also methods to load configuration files applicable to ".exe" applications.
I’d suggest taking a look at WebConfigurationManager and see if it provides you with anything you simply cannot do with ConfigurationManager and use it instead, otherwise using ConfigurationManager will make it far easier to have your code be used seamlessly between web and desktop aps.
Not sure what you mean about the connection strings.
Calling WebConfigurationManager.ConnectionStrings returns a System.Configuration.ConnectionStringSettingsCollection, which is the same as you would get if you called ConfigurationManager.ConnectionStrings.
Otherwise, as XOR says, it's designed to handle multiple hierarchical web.configs, combining them as required as you move around the folders in an application.
Although WebConfigurationManager is located in the System.Web assembly the ConnectionStringSettingsCollection that it returns is located in System.Configuration.
If you are getting the error
Cannot apply indexing with [] to an expression of type
'System.Configuration.ConnectionStringSettingsCollection'
while trying to access the array index...
WebConfigurationManager.ConnectionStrings["Name"].ConnectionString
make sure you have a reference to assembly System.Configuration
Related
I have a C# project that outputs a dll: foo.dll. This foo.dll internally uses a legacy library legacy.dll. Here is how my library foo.dll will be used: first I upload these files: foo.dll, legacy.dll, and legacy.dll.config to a third party; then the third party starts up a process which loads my main library foo.dll and executes some functions. When foo.dll is being run, I see exception thrown in legacy.dll saying some configuration "baz" cannot be found. However, I can verify that the configuration "baz" is defined in the legacy.dll.config file. So I think the file legacy.dll.config is not loaded by the process.
So I wonder how config.dll files are used. In my case, considering foo.dll is the only thing within my control, is there a way to load the legacy.dll.config file?
One solution is to place the configuration section that your legacy.dll requires in the configuration (app.config or web.config) for the application that references it.
Do you have control over your legacy application - in other words, are you able to modify it? One occasional challenge is that when all of these extra values are dumped into the configuration it can be more difficult to tell where they are used. They can even get left in the configuration long after you stop using legacy.dll because no one knows what they are and they're afraid to remove them.
Going the other way, if the values are missing from the configuration, it's best not to throw a confusing NullReferenceException or configuration exception that requires someone to dig into the legacy code and figure out why it doesn't work.
There are a few things you can do to make this easier:
One is that your legacy.dll can look for configuration values that are distinct and separate from the rest of your configuration.
That could mean a separate configuration section like
<section name="stuffTheLegacyDllNeeds" type="Legacy.LegacySettingsConfiguration, Legacy" />
<stuffTheLegacyDllNeeds>
....
</stuffTheLegacyDllNeeds>
Or you can disambiguate the appSettings keys with some convention like
<add key="myLegacyLibrary:someSetting" value="true" />
You can also make it easier for other developers by throwing useful exception messages if a required key is missing, like "Legacy requires appSettings key 'xyz' which was not found." They still have to figure out where to find the values but at least they have a clear understanding of the problem.
Also, if you find that Legacy.dll doesn't change settings often or ever, you can code it to replace missing values with default values. That way they can override the defaults if they need to by adding configuration values. But if they don't need the defaults they can just not supply configuration values.
One more approach - this is the one I personally prefer:
Make your legacy class depend on an interface for settings like
public interface ISettings
{
bool SomeSetting { get; }
int SomeOtherSetting { get; }
}
and make your legacy class require an instance of ISettings in its constructor. Now the app that references it "knows" about the settings because it can't use the class without providing it. Your legacy library can provide an implementation like
public class ConfigurationSettings : ISettings
that reads from configuration, and the referencing app could choose to use it. Or it could supply another class that implements the interface. It could also provide a class that contains default values which the referencing app could change. It could also have a set of defaults that it uses internally if the referencing app doesn't provide any values.
Now,
The referencing application knows that your class needs these settings.
The referencing application can choose how to provide them.
Your legacy library no longer depends on the configuration. It depends on an abstraction - ISettings - which can be implemented using configuration or some other way. That means your legacy library will be easier to unit test. Code that explicitly depends on configuration values is much harder to test, or likely never even gets tested.
We are a group of C#/.NET 4.5 developers working on the same application.
The application has a set of configurations related to each developer machine, like the connection string to the DB, network related settings (proxies, IPs, credentials) and a LOT MORE.
Because the application has grown we are incurring in a lot of environment related configurations like for example:
If this is MyPC then load the connection string for my PC.
If this is the XDeveloperPC then specify proxy’s settings.
Also if new developers leaves or join the group, then the process to update the file becomes a total head ache. Maintaining the file has become very hard and is a possible source of bug and errors.
I was thinking in having specific app.config files related to each developer environment like:
app_MyPC.config
app_XDeveloperPC.config
And when the application builds or executes then specify which one to load as if it where the default app.config of the application. Then, when the application or any class or method refers to a given configuration (like the connection string) is access to this configuration file as if it where accessing to the app.config default file.
I would not want to create a Configuration class that builds immediately when the application starts because then I should have references from every place to this class and the application is quite large, with a bunch of projects and dlls.
I rather prefer to hear some opinions and what do you think should be the best way to achieve this.
Is it possible to achieve this?
How?
Do you know a better approach?
FYI, please note that .NET only loads one config file for the whole application. You could try multiple config files something as like specified here,
Multiple App.Config Files in .NET Class library project
Hope this helps...
You can specify sections of app.config to be loaded from another file. See this answer
However, you might have to customize the above solution, the app.config files and the way configs are organized.
Another approach is to use a custom settings file instead of app.config. This will need some code change to use the config file. This config can either be an XML or a JSON file (JSON is easy to deal with). You can use an inheritance model wherein generic settings come from one file, specific settings come from another file and so on. Also, you can load settings from such file at runtime and change application behavior on the fly.
If you decide to use custom config file, and if you already have lot of code written considering App.config file, you can abstract the app.config calls to a method and let that method deal with where to pull the settings value from. That way you can minimize the code change and keep everything tidy.
Maybe you can use the machine.config file (C:\Windows\Microsoft.NET\Framework\your Framework version\Config\machine.config)
I have two applications that have many common configuration properties. When a configuration property of one changes, I want the other to change as well. Does anyone have a sensible way to accomplish this before I start off down the wrong track?
EDIT: I'm using .NET 2.0
You can create and reference a common configSource for the configuration section(s) involved. For instance, if you wanted a common set of AppSettings, copy your current appSettings to a new file (say appSettings.shared.config) and replace them in both app configs with this:
<appSettings configSource="appSettings.shared.config"/>
Here's more documentation: http://sunali.com/2008/01/23/configsource-property-dividing-configuration-files-into-pieces/
Far as I know, this cannot be done for an entire file, only sections, and each section will need its own file (and the section must still be declared in the configurationsections element of the app.config). But, this has a number of really cool uses; for instance, you can separate your connection strings into files geared towards different environments (local, development, testing, staging, production) and by changing one filename in one place you've now pointed your app at the different environment.
One easy way to accomplish this is to use the configSource attribute in the app.config in both applications, and point this to a common file. Bingo, change one file, all apps are updated.
Check the MSDN documentation on it here.
there are a couple of different ways you could do this:
use the registry
use a config file in a common location
use a configuration table in a database
I have a Winform app that has 16 SQL Connections currently stored in the DAL Projects Settings.settings.
I am trying to write a "Manager" class to simplify this(like here). However, most of the examples I find on the web seem to use ConfigurationSettings.AppSettings["something"]. While, I WAS using Properties.Settings.Default.something.
Can someone, please, explain which is considered CORRECT and why for a Desktop applications?
I think the correct way is to use the app.config file and store them in the connectionStrings section?
Then you can access them like:
ConfigurationManager.ConnectionStrings["something"].ConnectionString
You could write a wrapper around that easily if that is too "ugly".
public class ConnectionManager
{
public string Something
{
get
{
// TODO: check to make sure the configuration exists and throw an exception perhaps
return ConfigurationManager.ConnectionStrings["something"].ConnectionString;
}
}
}
Oops...as pointed out I meant to do ConfigurationManager and not ConfigurationSettings.
I've never been a big fan of putting sql connection strings into configuration files for software. Users have a habit of goofing them up out of curiosity or stupidity (or some combination of the two). I like to put all of my connection strings (development, model, production, whatever) into the Properties of my data access library, and include within it a ConfigurationSettings class that I use to access them based on some property that is set by the consuming application:
public class ConfigurationSettings
{
public static string MyConnectionString
{
get
if(ConfigurationSettings.TestMode)
return Properties.Settings.Default.MyConnectionStringTest;
else
return Properties.Settings.Default.MyConnectionStringProd;
}
}
// I typically only have test and not-test. This could
// easily be some other combination of values to satisfy
// multiple environments.
public static bool TestMode { get; private set;}
}
This allows me to call the static properties of this class through a common name and have all connection strings available depending on some criteria. This gets your specific datasets, entities, whatever data model you're using from being in the business of worrying about connection strings and the settings can be compiled into the .dll (and no longer need to worry about them). This method can also be modified to pull settings from an app.config (which I do for ASP.Net sites) in a similar method.
UPDATE: There really is no "correct" way as you imply. The app.config was designed to hold configuration settings that are modifiable without rebuilding the application. Property Settings were designed to hold settings that are not modifiable. So both are perfectly valid. Probably the most "correct" way is a way that makes sense both for your application and for your development team.
We prefer to use Properties.Settings (aka. settings.settings) because it's strongly typed. Don't try to do fancy tricks that have different environments (dev/prod) in the same config file. It is much easier to have a separate config file per environment, and to rename the configs when you deploy them. i.e.
app.config
app.stage.config
app.test.config
app.prod.config
We use PowerShell scripts (batch files on steroids) to do our deployments. I'll simplify what we do as a traditional batch file - (pseudo code/untested sample):
#echo off
:: %1 is the environment name (first parameter)
setlocal
set source=c:\tfs\project\bin\release\
set target=\\server\share\path\
xcopy /s/e %source% %target%
:: Using a copy command to rename/overwrite the env specific version
if exists %target%\app.%1.config copy /y %target%\app.%1.config %target%\app.config
Properties.Settings.Default are generally used to save application internal state like the color of the background, to remember user settings.
ConfigurationSettings is actually the "Manager" class you were talking about and can access other custom sets of settings from the app.config file, including connection strings.
I have an asp.net mvc project that uses some search methods in a seperate library.
This library needs to know the location of my lucene index files.
private static string lucenePath = ConfigurationManager.AppSettings["lucenePath"];
public static ColorList SearchColors(Query query) {
return new ColorList(
new IndexSearcher(Path.GetFullPath(lucenePath)),
query);
}
This correctly reads my configured lucenePath from the web.config's application key node.
But how can I get the correct full path from this relative path? Path.GetFullPath gives me a completely incorrect path.
--Conclusion--
If you want to go full-out, tvanfosson's answer is probably for you.
I, however, kept it a little more brain dead by using the following:
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
ConfigurationManager.AppSettings["luceneIndex"].TrimStart('\\'));
This will look in the caller's app.config for an appkey called "path" and combine its value to the caller's path. The TrimStart() makes sure that the config file can both contain a leading \ or not.
Server.MapPath(string);
Since you are referencing this from a separate library, you might have to jump through a bunch of hoops to get access to the HttpServerUtitity or introduce some coupling to classes that are difficult to mock. You might want to consider having a single configuration class that loads properties from the web configuration that gets injected into your library via constructor/setter. To make it easier to test against, you could define an interface that could be mocked in your unit tests and have it implement that. The configuration class could use the HttpServerUtility to obtain the absolute path and store it internally to be reused.