【问题标题】:IIS Web application and class-library configuration - config file is lost when deployedIIS Web 应用程序和类库配置 - 配置文件在部署时丢失
【发布时间】:2013-03-03 13:49:16
【问题描述】:

我有一个用 C# 4.0 编写的 ASP.NET 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 临时文件中。有一个花哨的目录结构,其中包含一个专用于每个引用的程序集的文件夹。 CustomLibrary.dll 对应的文件夹中不包含配置文件。由于this.GetType().Assembly.Location 将返回临时文件夹的路径,因此应用程序无法加载配置并正常崩溃。

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

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


编辑:

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

【问题讨论】:

  • 这就是 .NET 一直以来的工作方式。您需要从类库配置文件中复制设置并将它们粘贴到 web.config 中。
  • 我明白了,但我仍然相信我已经非常接近我需要实现的目标(请参阅我重新访问的帖子以了解我的原因)。唯一的阻碍是 IIS 未将文件复制到临时文件夹中。

标签: asp.net configuration


【解决方案1】:

如果这些是没有人应该看到或更改的静态内部设置,那么将类库中包含的配置文件作为嵌入式资源使用不是更好吗?或者只是一个带有设置的静态类。

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

【讨论】:

  • 好主意!我已将配置文件标记为嵌入式资源(不再需要复制),我只是将其提取到临时文件夹并使用 ConfigurationManager.OpenMappedExeConfiguration(exeConfigPath, ....) 加载它
  • 注意:一个重要的缺点是配置是在程序集中编译的,为了使更改生效,必须重新构建库,但这不是我关心的问题。此外,应用程序应该能够写入操作系统临时文件夹,以便将配置保存为物理文件,因为无法将其作为流加载。
  • 正确。但是,您还有另一个选择,即不使用配置 API,而是直接从嵌入式资源将 XML 反序列化为对象模型。这样您就可以避免需要对文件系统进行写访问、处理临时文件夹等。
  • 是的,但由于我们有自定义配置部分,我已经与配置 API 绑定太多了。此外,配置文件可以更轻松地将首选项构造为可读的 xml。
【解决方案2】:

我已经找到了解决所描述问题的方法,但对我的要求来说仍然不是很愉快。

解决方案是利用始终可用的应用程序配置(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 应用程序中顺利运行。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 这正是我想要避免的——详情请参阅我的帖子的重新访问。事实上,上面的代码按我想要的方式工作,问题是临时 asp.net 文件中缺少配置
    猜你喜欢
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 2016-09-10
    相关资源
    最近更新 更多