2013-03-14 65 views
3

我有用C#4.0编写的ASP.NET Web应用程序。应用程序引用自带配置文件的类库。在运行时,类库使用类似于下面的代码加载这个具体配置:IIS Web应用程序和类库配置 - 配置文件部署时丢失

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

这样做是因为该库已加载其捆绑的配置,而不是应用程序配置。应用程序配置不应该关心库的设置,不应该能够改变它们。

现在,还有一些其他事情需要完成这个概念的工作。我必须将库的配置文件构建操作设置为属性窗口中的内容,并将副本设置为Copy AlwaysCopy If Newer。到目前为止,文件自动进入到类库的bin目录和web应用程序的bin目录中,并且从App.config正确地重命名为CustomLibrary.dll.config(假定库的DLL是CustomLibrary.dll)。

现在我面临两个问题。

1)当我将Web应用程序发布到文件系统位置(映射到IIS)时,CustomLibrary.dll.config在发布的应用程序的bin文件夹中显示为App.config。好的 - 我将在类库项目中重命名它以符合预期的约定 - 并解决问题。

2)即使发布,IIS也会再次编译应用程序并将其存储在ASP.NET Temporary Files中。有一个花哨的目录结构,其中包含专用于每个组件的文件夹。与CustomLibrary.dll相对应的文件夹不包含其中的配置文件。由于this.GetType().Assembly.Location将返回到临时文件夹的路径,应用程序无法加载配置并崩溃,因为它应该。

我需要保留在类库中具有配置的模式,并且能够使其在Web应用程序中工作。手动将.config复制到临时文件夹时,该应用程序可以正常工作,但请参阅,我真的很讨厌手动复制到随机命名的文件夹。

有没有办法阻止IIS使用临时文件夹,或使它沿着配置文件复制?我相信我面临的问题是配置相关而不是概念性的,因为当配置文件就位时应用程序按预期工作。我宁愿不要乱用配置文件的硬编码物理路径。


编辑:

使其更清晰,我会指出什么,为什么我想要实现。这个想法是,库和Web项目将作为独立的产品开发 - 在库的配置中不会有用户或应用程序特定的信息,因此不会因不同的使用场景而改变。它也是特定于类库功能而不是最终应用程序。对我来说,保持库中的配置信息是合理的(类似于Java,其中spring上下文xml文件或属性文件与库的jar捆绑在一起)。我想避免必须复制消费者应用程序的每个app/web配置中的配置。有些情况下,消费者应用程序是由第三方开发的,我不想依赖于他们配置我的东西的权利工作。同样,这里唯一的问题是没有将配置文件复制到正确的位置。

+0

这就是.NET一直以来的工作原理。您需要从类库配置文件复制设置并将它们粘贴到web.config中。 – 2013-03-15 01:15:30

+0

我明白了,我仍然相信自己已经非常接近我需要实现的目标(请参阅我的重访帖子,了解我的原因)。唯一的拦截器是文件不被临时文件夹中的IIS复制。 – 2013-03-15 08:59:04

回答

1

如果这些都是静态的,那么任何人都不应该看到或更改的内部设置,那么将类型库中包含的配置作为嵌入式资源的文件不是更好吗?无论是那个或只是一个静态类的设置。

这样你就可以确定没有人改变它,这在你的场景中似乎是一个加号。

+0

好主意!我已经将配置文件标记为嵌入式资源(复制总是不再需要),我只是将其提取到临时文件夹,并使用'ConfigurationManager.OpenMappedExeConfiguration(exeConfigPath,....)'加载它' – 2013-03-16 13:49:38

+0

注意:一个重要的缺点是配置会在程序集内编译,为使更改生效,库必须重新构建,但在这一点上这不是我关心的问题。另外,应用程序应该能够写入OS临时文件夹,以便将配置保存为物理文件,因为无法将其作为流加载。 – 2013-03-16 13:52:27

+1

正确。但是,您有另一种选择,即不使用配置API,而是直接从嵌入式资源将XML反序列化为对象模型。这样你就避免了需要对文件系统进行写访问,处理临时文件夹等问题。 – 2013-03-16 23:18:38

0

简短的回答是:你不能。您必须合并两个配置部分,并将所有设置放在应用程序的主配置文件中。在web应用程序中,它将是web.config。阅读this

+0

这正是我想要避免的 - 请参阅我的帖子的重访细节。事实上,上面的代码只是我想要的方式,问题是在临时asp.net文件中缺少的配置 – 2013-03-15 22:30:22

1

我已经出现了一种围绕所述问题开展工作的方式,对我的要求来说仍然不是一件令人愉快的事情。

解决方案是利用始终可用的应用程序配置(Web应用程序中的web.config或app.config)。我已经为设置添加了每个库的配置文件的绝对路径。所以我结束了:

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

和类库现在使用下面的代码加载其配置:

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; 
    } 
} 

虽然这个作品,我会等待,如果可能的一个更好的解决方案。不过,我不必将整个ClassLibrary.dll.config复制到web.config文件中,但现在我必须管理文件系统位置并了解应用程序设置名称。我真正想要的是ClassLibrary.dll的消费者应用程序不以任何方式处理其配置。如果它是一个桌面应用程序,我已经介绍了这一点,因为Visual Studio会正确地复制ClassLibary.dll.config。我希望有一种方法可以使Web应用程序顺利运行。