Understanding configuration files in multiproject (interoperable) .NET solutions - c#

Scenario
Consider having a solutions with 4 projects in it:
1) ProjectSql: This is a project, whose compilation output is set to Library, and this is responsible of accessing a SqlServer database and do something. The final library will be able to provide APIs in order to manage persistency for the final application.
2) ProjectWCF: This is a project, whose compilation output is set to Library, and this is responsible for defining service contracts, data contracts and service implementations to let my application host a service.
3) ProjectMiscellaneous: This is a project, whose compilation output is set to Library, and this is responsibe to provide APIs for other things.
4) ProjectApp: This is a project, whose compilation output is set to Executable (Exe), and this is responsible for creating the business logic of my application. Suppose this to be a simple Console application. This projects has references to all the other ones.
Assumption: Consider that every project has its own configuration file. ProjectSql, for example, defines connection strings to connect to a database and so on...
Problem: Configuration
Well, my problem is the following: consider that my application project ProjectApp uses ProjectSql, well, every call to a operation in ProjectSql needs to connect to database, in these calls the ProjectSql configuration file is referenced to get connection strings (a simple call to System.Configuration.ConfigurationManager....).
I think that if my ProjectApp, with its own configuration file, makes a call to an operation in ProjectSql, then, that operation will reference to its own configuration file.
My question is:
What I said, is it true???
Do configuration files respect the project hierarchy.

System.Configuration.ConfigurationManager can be told which config file to read. Any given app will normally have one config like appname.exe.config or web.config.
So the answer to you question is NO.
When you call System.Configuration.ConfigurationManager for any of the class libraries, it is the ProjectApp.exe.config file that is read.

Related

Adding Service Reference to WCF does not always create .datasource files

In some projects when I add a service reference to a WCF service, it creates datasource files for classes shared in a common class library, however in others the datasources are not created. The Reference.cs file is different where in the first case the types are from the class library and in the latter it's in the Reference.cs file it self. These are not compatible.
What is it that triggers the automatic generation of the datasource files in this case? Advanced options in Add Service Reference dialog are identical so something else must be playing tricks on me.
UPDATE: Turns out the datasource files are not needed. It's the code generated in the Reference.cs file that makes the whole difference. I can manually edit the parameters for the methods to point to the class-library, and it works. This is of course not a solution in the long run, since I have to do this every time I update the Service Reference. Hopefully someone will come along who knows the trigger of this problem.
The file is created by VS when you add a service reference. It's used to enable client UI components to bind to the models (data contracts). I don't know why they are not created for "all" services (but I guess it depends on how that service defines and uses data contracts (as in: no contract no data file)).
Here are some useful links:
https://msdn.microsoft.com/en-us/library/ee373840.aspx
What are the WCF Service Reference .datasource files?
UPDATE: You are right it should not depend on the consumed service. Here are two related links (that impliece that the files are included by VS):
http://objectmix.com/dotnet/797048-wcf-service-reference-datasource-file-name-length-problem.html
Disable automatic generation of datasources file when updating service references
So it looks like the file is created by VS, if you don't wan/need it you can exclude it by creating the proxy with svcutil.exe

Dynamically switch the configuration file (web or app config)

I have a web application that refers to a DLL. This DLL has certain config values, which are normally part of the web.config.
There is a requirement to invoke this DLL under different configurations, from the web application. The DLL is third-party and cannot be changed.
Have tried the below and failed.
Have different copies of DLL (named a.dll, b.dll) and load it by reflection. The problem here is that it’ll still look for the web.config and not the a.dll.config. Also, since same Types are referenced in the main program as well as the reflected assembly, it goes crazy.
Change the config on the fly using AppDomain.CurrentDomain.SetData("WEB_CONFIG_FILE", #"Config\Path") and switch it back after the call. The problem here is that after the first time, it doesn’t load the config section again even if I switch.
Use ConfigurationManager.RefreshSection(#"configuration\mysection") to force a refresh. This doesn’t seem to work and people say this call is buggy in .NET
I've seen some recommendation to update the web.config, but this may not be a good choice for me because the switching of values would happen fairly frequently
Is there anything else I can do?
Host the DLL in a separate process and communicate using COM (or .Net remoting or a web service or similar).
I.e. create a host process a.exe using C# (say) which exposes classes as COM objects, the classes in turn calling the DLL methods/classes. Register as COM objects.
Then create b.exe the same (but with different CLSIDs).
You can now have different configuration files for a.exe and b.exe (in different folders), yet both can use the DLL services.
You could also do something similar by having two internal web apps and using SOAP or something to talk to them.
But the bottom line is if the DLL works on web.config, you have to put at least one of them into a separate process in a separate folder.

.NET App.Config issues across multiple projects

I have a solution that contains two projects. One project is a Windows Service that contains a few classes for performing various functions. The other project is a Windows Form Application that is meant for doing various testing and performing task that the service accomplishes on demand. For instance, the service will do a few various task at a certain time interval, but if you wanted to perform one of those task before the time interval has elapsed, you could load the Windows Forms Application and execute one of the task immediately. The Windows Form Application (from here referred to as the tester) references the Windows Service (from here referred to as Service) project. When the Tester loads, it creates an instance of one of the classes from the Service. Whenever buttons are pressed to perform the task, it references that instance that was created and calls the various methods of the class. The Service has uses application settings for the configuration, and thus has an app.config. The configuration settings are accessed using [ProjectName].Properties.Settings.Default.[SettingName]. When the configuration settings for the tester are changed on its own app.config (or exe.config after release), the settings are refreshed without a problem. If the tester is closed, configuration is modified, and then reopened, the new settings will be populated. If the Reload method is called on the Settings, the configuration is refreshed without a problem. The Service performs in the same way. The configuration settings are can be updated without a problem.
The problem is that if configuration changes need to be made on the service, when the service methods are called from the tester, the configuration does not take the new settings. Whatever settings the project was built with will be used. I cannot get the tester to recognize that the app.config/exe.config for the service has changed, and the new configuration should be reloaded and used instead of whatever configuration was used when the project was built in visual studio. Perhaps it I am not educated enough about this topic, but it seems to me that the app.config is rolled up into the .exe file created by the Service whenever it is built.
I have tried encapsulating the Reload method for the Service and calling it, and it doesn't seem to make a difference.
I have an example project that performs as is described above on a very basic level. The ideal goal is to be able to modify the exe.config file or files on the fly and have both the Service and the Tester pick them up without any problems. If you would like to see exactly what I mean from a coding perspective, an example project can be found here: example solution
Any help would be greatly appreciated. Thanks you for your time.
Update
I have managed to find A solution to this, but I am still curious if there is a better way. By using an app.config that is shared between both projects and using the Configuration Manager instead of App Settings, everything works as it is expected to. I prefer to use App Settings if at all possible; however it will work to use a shared app.config and the Configuration Manager pointed at that app.config.
One option is having both programs load from the same configuration file:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.openexeconfiguration.aspx
Found the solution. An app.config must be added to the solution as is described above in my update. Once linked like that, you can add a settings file to the project and add settings/configuration to the project and they will be added to the solutions settings file. This will move with the build and fix the problem I was having.

How Do I Manage Data Connection From Within A Class Library in a Solution With Both Website and Form Apps?

This is a common problem for me. I have a solution that contains a Form App or two, a couple of websites(Intranet, External site kinda thing) and a class library where I want to store my data objects to be shared among the other project mentioned.
Normally, I'd have my connection strings stored in web.config and app.config files. However, with the class library, this isn't really possible. Not without passing in configuration information each time I want to access data. I'd prefer not to do that.
What's the best way to solve this problem?
If you put your connection strings in the web.config and the app.config of the referencing applications the Dll's will read them fine. If you want them shared you can put them in a machine config. You could also put them in a separate file and reference them from each web and app config.

Application Wide Settings Available to All Projects

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.

Categories