3
votes

I have an ASP.NET web application written in C# 4.0. The application references a class library that comes with its own configuration file. At runtime, the class library uses similar to the following code to load this specific configuration:

var exeConfigPath = this.GetType().Assembly.Location;
var config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);

This is done because the library has to load its bundled configuration rather than the application configuration. The application configuration should not be concerned of the library's settings and should not be able to alter them.

Now, there are a few other things that need to be done for this concept to work. I have to set the library's configuration file build operation as Content in the properties window and the Copy to be Copy Always or Copy If Newer. So far so good - the file gets automatically both into the class library's bin directory, and the web applications's bin directory, and is correctly renamed from App.config to CustomLibrary.dll.config (as supposed, the library's dll is CustomLibrary.dll).

Now I am facing two issues.

1) When I publish the web application to a filesystem location (mapped in IIS), the CustomLibrary.dll.config appears back as App.config in the bin folder of the published app. OK - I will rename it in the class library project to match the expected convention - and problem solved.

2) Even when published, the IIS compiles the application again and stores it in the ASP.NET Temporary Files. There is a fancy directory structure with a folder dedicated for each assembly referenced. The folder corresponding to the CustomLibrary.dll does not contain the config file in it. Since this.GetType().Assembly.Location will return the path to the temp folder, the application fails to load the configuration and crashes as it should.

I need to preserve the pattern of having the configuration in the class library, and be able to make it work in the web application. When manually copying the .config to the temp folder, the app works, but see, I really hate manual copying to randomly-named folders.

Is there a way to either prevent IIS from using the temp folders, or to make it copy along the config files? I believe the problem I am facing is configuration-related rather than conceptual since the application works as expected when the config file is in place. I'd prefer not to mess with using hard-coded physical paths to the config file either.


Edit:

To make it clearer, I will point out what and why I want to achieve. The idea is that the library and the web project will be developed as separate products - there will be no user or application specific information in the configuration of the library, so it will not change for different use scenarios. It is also rather specific to the class library functionality rather than the end application. It makes sense for me to keep the library's configuration information bundled within it (similar to Java, where a spring context xml file, or a properties file, get bundled with the jar of the library). I'd like to avoid having to copy the configuration in each app/web config of the consumer application. There will be cases where the consumer application is developed by third parties, and I do not want to rely on them doing their configuration right for my stuff to work. Again, the only issue here is not having the config file copied to the right place.

3
This is simply how .NET has always worked. You need to copy the settings from the class library config file and paste them into the web.config.John Saunders
I see, still I believe I got pretty close to what I need to achieve (see my revisited post for my reasons). The only blocker is the file not being copied by IIS in the temp folders.Ivaylo Slavov

3 Answers

1
votes

I have come along a way to work arround the described issue, still not a very pleasant one to my requirements.

The solution is to take advantage of the application configuration (web.config in web apps, or app.config) which is always available. I have added as settings the absolute paths to the config file for each library. So I ended up with:

<!--
THIS IS IN THE WEB.CONFIG FILE
-->
<appSettings>
    <add key ="ClassLibrary_ConfigPath"
         value ="{My Publish Output Folder}\ClassLibrary.dll.config"/>
</appSettings>

and the class library now uses the following code to load its configuration:

Configuration config = null;
try 
{
    var exeConfigPath = this.GetType().Assembly.Location;
    config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception e)
{
    if (!IsConfigurationNotFoundError(e)) 
    {
        // IsConfigurationNotFoundError logic skipped for brevity
        var exeConfigPath = 
            ConfigurationManager.AppSettings["ClassLibrary_ConfigPath"];
        if (exeConfigPath != null) 
        {
            config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
        }
    }
    else
    {
        throw;
    }
}

While this works, I will wait for a better solution if possible. Still, I do not have to copy the entire ClassLibrary.dll.config into the web.config file, but now I must manage filesystem locations and be aware of app-setting names. What I really want is the consumer app of the ClassLibrary.dll not to deal with its configuration in any way. If it were a desktop app, I have this covered, as Visual Studio copies the ClassLibary.dll.config appropriately. I hope there is a way to make it work smoothly for web apps.

1
votes

If those are static, internal settings that nobody should see or change, wouldn't you be better off having a file with the configuration included within the class library as an embedded resource? Either that or just a static class with the settings.

That way you'd be certain that nobody alters it, which in your scenario seems to be a plus.

0
votes

The short answer is: you can't. You have to merge both configuration sections and place all settings in the main configuration file of your application. In case of the web application it would be the web.config. Read this