Change the Default AppConfig at runtime with custom config sections - c#

I essentially am in charge of a DLL for my project that uses lots of external resources. I want to have a config file for my project named infrastructure.config that clients projects can copy in their project without having to cut and paste into their own app or web configs. I tried the following suggestion at:
Change default app.config at runtime
That solution worked well until I tried with Log4Net which utilizes a custom section. I received an unknown configuration section when I tried to use the code in the above mentioned link. When I use the same configuration file without the above mentioned code it works fine. Interestingly enough, it blew up when I was trying to use TransactionScope. So some combination of using TransactionScope and having configurationSections in my config made it fail. Any suggestions?
I want each client app or web site to have their own config for its own values while my infrsatucture.dll should be able to have a combination of its own values, custom SOAP Bindings and Log4Net.

Sound like what Dependency Injection is good for solving.
I would highly suggest that instead of creating an application/dll that relies on a config file (app settings or sections), that your interface expose what it needs to do it's work. These can be external class/interfaces exposed by other DLLs (log4net) or you can create your own and allow other developers to derive concrete classes based on your required abstract/interfaces classes.

Related

How to use environment dependent app.config file

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)

Best way to store settings (special requirements)

I found a lot of information for saving different kinds of application/user settings in different places but getting confused what could be the best way for me.
My problem has different dimensions:
The application will have some User-Roles (Admin, StandardUser, ...), where every User (based on Windows-Logon) will belong to one role.
The Admin is allowed to setup everything for everyone.
The settings have different categories:
Application settings (should be the same for every user on the computer)
User-Role-specific settings
User-specific settings
The application has several projects where different projects have to access the settings.
(4. The application is written in C#)
I don't want to mention the things that I have read because I don't want to steer your thoughts into a (maybe wrong) direction.
So, how would you handle this scenario?
Thanks a lot!!
Joerg
EDIT 1
Some more things after the first answers that I hope can clarify my question:
my question doesn't focus on the authentication of the users, it focusses on create/edit/save settings
my first attempts for solving the problem were:
using the Visual Studio Settings.Settings file
... doesn't work because I have several projects that have to have access to the settings AND I couldn't find a way to make the ApplicationSettings writeable (they are readonly)
use the ConfigurationManager-Class
... I am not experienced with this one but as far as I understand this class it is just another class that gives me access to my ApplicationSettings (and has the same problems like #1)
... maybe a link to a good tutorial will help
invent something on my own
... I still hope to find something ready-to-use
I guess in this kind of scenarios you probably have a database. When you incorporate users, user rights, etc in there it is probably also a good place to save your application settings.
I always love the database centric solutions, since there are widely available (when you want to create a new UI based on the same system, you can reuse the settings there).
I think the entity–attribute–value model is a good design strategy to consider.
You can create a view with triggers on them hiding system only properties, enabling the admin to change all, and the user to only change theirs.
By your description I'd say you want Role Based Authentication. It's something that has been asked before. I'd go to the link specified in that answer to find an overview and some code samples of how to approach this problem.
Microsoft has done a great job adding some abstractions with the Membership Providers and now the ASP.NET Identity Framework (in case you have a Web Application). Regardless of what you choose to do, database or config files are going to be involved (take a look here to learn how to manage those) and some sort of claim derived system.
Assumption: You already have figured out how you are going to handle roles, and your question is only about storage/retrieval of settings.
Point #3 means you can't use a Settings file for Application and User scoped settings combined with a custom configuration section for holding the role specific settings (optionally encrypted).
My next suggestion would be a WCF endpoint that exposes the settings, either in their entirety (security trimmed contents of Application + User specific + Role specific) or by some sort of dictionary lookup equivalent. Additionally:
The endpoint would need to require Windows Authentication (or possibly Claims) so that it could determine the user specific/role specific part.
Each application would then need to have knowledge of the WCF endpoint, either through configuration or potentially through WCF Discovery.
Update:
Note that WCF doesn't solve your storage question, but it helps with your point #3 - multiple projects that need to use the same settings. A WCF endpoint allows a single project that encapsulates the storage/retrieval of settings to be re-used by multiple clients. WCF can be complicated to read about, but in practice it's pretty easy to setup - you just decorate an interface and host it in IIS. You could also host it yourself in something like a windows service if you were adverse to using IIS, but deploying it to IIS would be a lot easier. You can then consume it in your other applications by adding a Service Reference to your project, and then you call the interface code as if the code was in your own project.
In case you are talking about a single application with multiple class libraries:
What I'm describing above assumes you are making multiple applications that all need to share settings. If you are actually talking about a single application with multiple class library projects, the built-in Settings can still be used - there is just one manual step you need to do to make it work across projects. After adding settings to both your application project and your class library project(s), you should copy the app.config section containing the settings in your class library and copy/paste it into your application's app.config. Visual Studio isn't very clever and it will only sync the class library Settings changes to an app.config within the class library project, even though an app.config for a class library isn't a "real thing", since only the app.config for the application consuming the class library is actually used by default (which is why you need to merge it into your application's app.config).
If you need multiple class libraries (including the main application project) to use the same settings, you could make a dedicated class library project just to hold the settings (note you can add multiple Settings files to this project to make the settings more modular), and then all the other projects could reference the common settings project (to avoid circular dependencies, you wouldn't hold any Settings in the main application project that a class library needed).
Overriding a user's settings
The Settings object has a mechanism you could use to override settings (say, with value's specified by an administrator). When you add a Settings object to your project, it creates a Settings partial class with some example code for wiring into the SettingsLoaded event. In this event, you could load your administrative settings (either through a WCF call, or perhaps from a know location on the file system) and apply any overrides.

Multiple Webservices with shared web.config logging to separate flat files with Ent Lib

I'm working on a project where I'm required to use Enterprise Library v.3.1.1.0 Logging block (wish it was log4net or nlog, but I don't get a choice). We have an IIS application where several WCF webservices are hosted, and they share a single web.config file. This is also something I'm not at liberty to change.
None of these services had any logging implemented previously.
So it's pretty straight forward to use the Ent Lib Config utility to set up a rolling flat file listener, and log to a text file the way I want. The problem I'm having is configuring it properly though so each service can have their own separate log file, while they still all share the same web.config.
I've gone through several tutorials, but I'm not understanding how to do this.
Any tips?
The configuration in the web.config is static so there will be one file per configured trace listener. One approach to achieve one file per service is to have each service log to a different category and each category uses a different trace listener. This could even be done programmatically so that services can add their own trace listener's at runtime although this is a bit more advanced than updating the configuration file manually (e.g. ensure service is added only once as well as ensuring that when the configuration is updated it is thread-safe).
Enterprise Library does not have anything analogous to log4net's hierarchical loggers so there is no out of the box way to use reflection to route log messages based on the originating class. It might be possible but you will have to write some code. You could write a Logger facade class to set the category based on the callers namespace. (Also note that there is no namespace wildcard matching like log4net.)

Using .NET ConfigurationManager to read settings from a string instead of an app.config file

We are running multiple instances of our service (implemented as a .exe file) on different machines in our data center. However, we would like to store configuration parameters for this .exe file in a central location (as opposed to being in the .exe.config per machine).
To do this, we are planning to move the content of the .exe.config files to an attribute in a central repository (Active Directory or SQL) and make the .exe's running on all machines read from this repository.
I would like reuse all the existing classes used for reading/writing configuration information (using ConfigurationManager, ConfigurationProperty etc., basically using the entire .NET Configuration framework) - however, instead of loading it from the .exe.config file (which it does by default - I want it to load it from a string value of the XML blob that I will retrieve from that central repository.
I was trying to find ways to do it using the ConfigurationManager API but couldn't find anything that could load a Configuration Section from a string. Any pointers?
I suppose you could write your own ConfigurationSection that will then load the real config data from your central repository.
Alternatively, do you have some sort of centralized deployment system in place for installing software on your various servers? How does your service get deployed? Rather than adding complexity to your software you should look for existing tools that already solve your problem.
Although I doubt this is what it was intended for, we've done this in our project using ProtectedConfigurationProvider. Basically, this class is supposed to allow you to encrypt your configuration file but we simply have the Decrypt method connect to our database and return the configuration information. See this for notes on implementing. This felt a little hacky, but we couldn't find any other way without completely rewriting all of the configuration parsing logic.

Configuring log4net in a VSTO

I've set up my VSTO Excel add-in to use log4net for logging. Unfortunately I'm (seemingly) not able to make it configure itself from the app.config (which I deliver together with the add-in via ClickOnce).
I have read http://www.darinhiggins.com/?p=13 which lists some ways to get the file name of the app.config and then configure log4net with
log4net.Config.XmlConfigurator.Configure(fileInfo)
However the approaches this blog lists seem very error-prone to me (they "smell bad").
Things like
ConfigurationManager.GetSection
make me believe the .NET framework knows exactly where to get the file and there must be a way to retrieve this information from the framework instead of having to figure it out on my own. However, the XmlConfigurator in turn only accepts a file name, stream or xml node...
(Why I believe it's not working at the moment: I have configured it to use a RollingFileAppender with the file name being H:\Data\Debug.log, but after a GetLogger(...).Debug(...), there is still no Debug.log in place...). I have used the exact same configuration in other places, successfully.
XmlConfigurator.Configure(); uses the app.config file. That should work since the ConfigurationManager seems to be able to read the config file.

Categories

Resources