What is the difference between configuration.Save(ConfigurationSaveMode.Modified, true) and configuration.Save()?
Background: I have a programme, where I manipulate a web.config, which I use for configuring WCF Services. I load it into a Configuration object, change some attributes and save it back. When I use configuration.Save(ConfigurationSaveMode.Modified, true) I get an Exception like this:
"It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level..."
When I use configuration.Save(), then it works! The reason for the exception may be the section <serviceActivations> in my web.config (the exception points to this section)
The default parameters to Save are:
Save(ConfigurationSaveMode.Modified, false);
So the only difference would be that you force saving the configuration, even if it was unchanged. See http://msdn.microsoft.com/en-us/library/ms134089.aspx for more information.
Why woyld you write configuration.Save(ConfigurationSaveMode.Modified, true) when:
ConfigurationSaveMode.Modified means:
Causes only modified properties to
be written to the configuration file,
even when the value is the same as
the inherited value.
true means: true to save even if the
configuration was not modified;
otherwise, false.
Isn't the first option the opposite of the second?
ConfigurationSaveMode.Modified only saves the parts of the configuration that are different to the application/system configuration to a user local or roaming configuration (i.e. using ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel) with ConfigurationUserLevel.PerUserRoaming or ConfigurationUserLevel.PerUserRoamingAndLocal).
Since ASP.NET doesn't have user levels (and user isolated storage) this doesn't make sense.
From the documentation is not clear if any of the Configuration.Save overloads will really work in the case of ASP.NET which uses a completely different configuration setting inheritance model to non-ASP.NET .NET applications. In practice using one of the WebConfigurationManager to load the configuration manager is likely to be a necessary pre-condition to saving the file.
Another approach might be to explicitly load a explicitly designated file with ConfigurationManager.OpenMappedExeConfiguration.
Related
The storage admins where I work have bought and configured a new huge NAS system.
Over time all current storage will migrate over there. This means that various network paths will change and this will break some in-house applications. We are reviewing a bunch of old apps the find the ones that use current paths like: \\old-file-system.company.com\Users so that we can modify them.
The old apps I have found all set these paths as strings in the project web.config file. My question is: are these paths compiled into the executable or are they read at runtime from this config file? Can we just modify the paths in the config files and not have to potentially rebuild them or upgrade them to newer .Net versions?
Cheers
The values are read from the config file.
That is precisely the point of config files: to provide the ability to alter these values without needing to redeploy the application.
Note that this may need you to restart the app pool on IIS after making changes. Usually, it should automatically do that when it detects changes to the config file, but from historical experience this sometimes breaks without you noticing.
As an aside: don't forget about alternative config storage methods such as databases.
yes, they are!
it will then depend on the code.
So, As a general rule no.
However, if you added new config items, then they may well not show up.
And if the code used the built in class in place of often used configuration manager to get values?
then you have to re-compile.
But, we also might use this:
vb.net:
Dim rstData As New DataTable
Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
So, in place of config manager, I often use My.Settings.TEST3.
(you get intel-sense). So on build, a class is created for some of those web config files.)
In c#, the above is:
Properties.Settings.Default.TEST3
And again often used due to intel-sense in place of configuration manager.
That class is re-build at compile time. So, if the code used to get web.config values is always configuration manager, then you would/should be ok.
However, if code used the built-in class like above?
The values ARE pulled from web.config at compile (build) time.
the class is called
c#
Settings.Desinger.Cs
vb.net
Settings.Desinger.vb
So, I would check the above two files. That class tends to come from here:
Now the above when we add say a connection string to the project?
The above DOES update and put the above settings into web.config.
However, the class created (settings.Desing.cs/vb?
It is re-generated each time, and it DOES COPY the values from web.config.
So this means that after changing the settings in that project, you REALLY do have to re-build.
As noted, if one came from desktop land, then we just add settings to above, and use them. They actually are created in web config, but we often use the above - since as noted ANY new setting we add to the project now has intel-sense.
So, I would search the source code for:
vb:
My.Settings.TEST3
(search for My.Settings.)
or
c#
Properties.Settings.Default.TEST3
(search for Properties.Settings.)
if either of above are used in the code?
Then yes, you have to re-build since they are re-created at compile time into a class, and the values ARE pulled from web.config at compile time.
If configuration manager was used in all cases, then you are ok.
however, if the designer class was used, then a re-build is required, and worse a change in web.config will not be reflected in that class until a re-build.
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.
My configuration code is setup in a way that default values are provided, and configuration files can be used to override these defaults.
For Azure Worker Roles I use the CloudConfigurationManager to read the configuration from the ServiceConfiguration.*.cscfg files for overriding the defaults.
A common reason for overriding the defaults is to provide different storage (blob,table,queue,etc) names during testing.
Unfortunately as far as I can tell, once a Setting has been defined in the ServiceDefinition.csdef file it must be provided in all ServiceConfiguration.*.cscfg files.
This wipes out the advantages of having less configuration to create and reducing the chance of errors creeping in while creating that configuration.
Is there a way to make a Setting optional?
Or is there another alternative place I can get deployment-specific configuration values from that works the way I want?
I have implemented a custom file configuration, that uses custom sections, using C#.
The main issue i have is with implementing some kind of version aware configuration loader.
Confgiurations change, but we need to make them usable anyway.
Is there any documentation that points in the direction of having some kind of versioning in configurations?
I'll give you two examples on what my issues are:
- key["key1"] changes from boolean type to int type.
- key["key2"] mandatory ceases to exist
thanks.
My tendency would be to add some kind of version header to the configs and keep a history of their schemas in the app. It could be troublesome in some ways, but at least you don't have to guess what an old value meant.
You could have the concept of default values for each setting. If you introduce a new setting and an old config file doesn't have it then it would use the default value. Similarly, if you remove a setting from the code then its existence in the config file would be harmless, it would just be ignored.
If you want to change how a given setting works (the type or the format) then it's a little more tricky. You could try to parse the value and if it's not in the right format you could ignore it and use the default value.
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