0

I've done a lot of research on this, and tried a number of approaches, but I'm beginning to think that what I want to do can't be done. To wit -- I am building an application that will be used by multiple clients. Each client will have their own database connection requirements, and their own set of customizations to control some of the behaviour of the application.

What I want to do is to create a .config file for each individual client, then use a command-line argument that will specify which .config file to load. Each config file will have its own section, and its own . I've gone through much of the documentation con ConfigurationManager and the Configuration classes and tried a number of different approaches, all of which have failed.

The basic question is "when I open a .config file, how do I tell the application to make this .config the default configuration?" For example, when I later make reference to a value in appSettings, or a database connection string, how do make sure that these references will each map to the custom configuration I have loaded, and not the one created by default by Visual Studio?

I have found all kinds of references to loading configuration files, but nothing that tells me how to dynamically replace the standard one with the one I just loaded. I keep ending up with null reference exceptions and running headlong into brick walls.

npowroz
  • 11
  • 5
  • Why do you want to use a config file? Why not store the configuration in the database? You cant replace the app.config its locked to the name of the assembly. But you can at startup load a specific Configuration file and have that accessible to the whole application through a singleton or such. – Andrew Harris May 08 '17 at 01:40
  • Have you seen this? http://stackoverflow.com/questions/505566/loading-custom-configuration-files – Evan Trimboli May 08 '17 at 01:41
  • Depending on how many items/clients you have, one simple approach is to just use one config and prefix the keys for each app setting with the client ID. Then access the app setting items with prefixed key strings: `'CLIENT1-ConnectionString'`, `'CLIENT2-ConnectionString'`, and so on... – Troy Carlson May 08 '17 at 01:42
  • You cannot tell a .net app to use another .config file. Perhaps a small bootstrapper app can copy the .config file into place, but you'll certainly fight access right. The option to [refer to another file](http://stackoverflow.com/questions/3638163/how-to-include-a-config-file-for-net) doesn't sound useful. Do consider that this just not a feature you actually want. Your client *do* modify this file by themselves, without you knowing about it, possibly long after you stopped paying attention. – Hans Passant May 08 '17 at 02:45
  • Storing the connection strings for all customers in one config-file, potentially accessible by all of the customers, sounds like a bad idea. Generate a Web.config for the specific customer upon building your application by using config file transformations: http://stackoverflow.com/questions/34735132/how-to-add-config-transformations-for-a-custom-config-file-in-visual-studio – J.N. May 08 '17 at 02:54
  • You can re-write the config file, and restart the app. Have it triggered in first load and have a back door to trigger the behavior again later. You could even use command line switches so that the user tells you at run time which client they are so you can simplify knowing which config file you need to write. Avoid writing the file every time the app runs though. – blaze_125 May 08 '17 at 03:36
  • @Andrew Harris I can't store the configuration in the database because I don't know which database to use for which client. That's why I want to place all of that in a config file. As I said in my original post -- each client gets a configuration, and the command-line says which client is running this instance of the application. – npowroz May 08 '17 at 04:15
  • @Hans Passant You are assuming that the client has access to the config file. In fact they won't. The application will be hosted on a server to which they do not have the access necessary to change anything. – npowroz May 08 '17 at 04:16
  • @blaze_125: The multiple config files will be static, not generated by my application. I will be responsible for the content of each config file. The whole idea is that the application will decide which config file to load based on a command-line argument, then control its operation by loading everything else out of the file. – npowroz May 08 '17 at 04:20
  • @J.N.: There would not be multiple connection strings in one file, IF I can do what I need. As well, customers will not see these connection strings, or any other run-time data, since the application will be installed on a server to which they will not have access. – npowroz May 08 '17 at 04:21
  • @Evan Trimboli: Yes, I had seen that reference. And yes, I could take the approach of simply treating the config file as an XML file and plumbing it for my information. I might end up doing that, although it means that I would have to forgo the built-in ConfigurationManager functions, such as AppSettings and ConnectionStrings handling. My hope was to be able to say "when I call AppSettings, get the data from the config file I've specified." – npowroz May 08 '17 at 04:29
  • @Troy Carlson: This approach would certainly work as an alternative. I could still pass the clientID as a command-line argument and then use that to determine which connectionstring to use. It would mean making sure that all the string names follow a very consistent naming convention, but it woud work. – npowroz May 08 '17 at 04:43
  • Short of re-writing the file at run time, which does work since I have one that's been running like that for quite some time. You could have "multiple text file" that you'd rename at run time, then restart the app to load it. `app.config.1` `app.config.2`, then you just rename the one you need to `app.config` then restart the application. – blaze_125 May 08 '17 at 12:55
  • My thanks to all who responded. I now have a very workable solution, although it will take more effort and won't be quite as elegant. What counts is getting the job done. – npowroz May 08 '17 at 14:25

1 Answers1

0

You can have multiple connection strings defined in your config file, then refer to them by name. Example:

<configuration>
    <connectionStrings>
       <add name="client1Connection"
            connectionString="Data Source=(local);Initial Catalog=dbclient1;Integrated Security=True"
            providerName="System.Data.SqlClient" />
       <add name="client2connection"
            connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=dbclient2;Integrated Security=True"
            providerName="System.Data.SqlClient" />
       ...
     </connectionStrings>
</configuration>

You can refer to them in you c# code by:

string client1ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["client1Connection"].ConnectionString;
string client2ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["client2connection"].ConnectionString;
DDan
  • 8,068
  • 5
  • 33
  • 52
  • I know all about multiple connection strings in one config file, and how to use them. I've been doing web applications in C# for years, but this isn't a web application. – npowroz May 08 '17 at 04:11
  • No this is exactly what I was suggesting. Its not limited to Web applications, you can use it in app.config as well. We have a similar situation where the application is passed purely a Client ID. We then have a single connection string to a configuration database. We can then look up the clients connection string from a table in the configuration database. Once we have our connection to the client database, each client has a configuration table for their own unique config values. – Andrew Harris May 08 '17 at 04:57
  • It doesn't have to do much with web applications. I have purely console based applications containing settings for connecting to multiple databases. – DDan May 08 '17 at 05:12
  • @Andrew Harris: I get what you're suggesting, and that would work although it would involve additional complexity. I wouldn't be able to use the standard ConfigurationManager stuff, which makes it a little less elegant. The application will have its own support database, so I can cram all the config data into that, including connection strings. Those connection strings will then point to the user databases and I can store any number of unique configuration values. It's not what I was hoping for, but it is completely workable. Maybe MS will add something like this in future (.NET 9, perhaps). – npowroz May 08 '17 at 14:23
  • On the point of not having the use of the built in ConfigurationManager classes...They aren't particularly complex. In the application I mentioned before, we built our own equivalent Manager Factory which allowed you to just ask for a particular config option and it gave you a typed value back. Let your imagination run wild. – Andrew Harris May 08 '17 at 21:23
  • If you handle client as an entity in your system and store things about them, feel free to add their own connection string or "connection keyword" (has of connection string) and you can write handler yourself. The config file is just a simplified help to keep the connection strings for you, and I don't think there is a need for multiple config files. If you are concerned about security of the conn string, you can encrypt the section in your config file. (http://stackoverflow.com/questions/1706613/encrypting-connection-string-in-web-config) – DDan May 09 '17 at 00:59