0

我的 Web.Config 文件中有一个条目,指示我所在的连接字符串和垃圾环境:

<add key="AppEnv" value ="2" /> <!--(0 = Dev, 1 = test, 2 = prod)--> 

我正在寻找一种在发布时提醒开发人员的方法,以确保他们已检查此键/值,以便他们不会将“测试”发布到“产品”服务器,反之亦然。

谢谢

4

8 回答 8

1

我已经提出了我自己的(可能是非常规的)解决方案来解决这个问题。我们为许多不同的客户开发了许多不同的 Web 项目,并且由于我们在多个 web.config 文件中遇到的所有问题,或者在发布前需要进行编辑,因此将它们全部迁移到这种方法。

基本上,我们让我们的应用程序根据传入的 URL 告诉我们它在哪个环境下运行。我们在第一个请求时对其进行初始化,并将其存储在应用程序生命周期的内存中。通过这种方式,我们可以将每个环境特定的配置值存储在同一个配置文件中,并使用 Development、Staging、Production 等来限定它们。任何在环境之间没有差异的设置都不需要限定。

首先是一个示例 web.config:

<appSettings>
    <add key="DevelopmentHost" value="dev.trackmyhours.com" />
    <add key="StagingHost" value="staging.trackmyhours.com" />
    <add key="ProductionHost" value="www.trackmyhours.com" />
  </appSettings>

  <connectionStrings>
    <clear />
    <add name="DevelopmentConnectionString" connectionString="your dev conn string" providerName="System.Data.SqlClient" />
    <add name="StagingConnectionString" connectionString="your staging conn string (mine is typically same as staging)" providerName="System.Data.SqlClient" />
    <add name="ProductionConnectionString" connectionString="your production conn string" providerName="System.Data.SqlClient" />
  </connectionStrings>

接下来我们有一个“App”类,它使我们能够访问我们的“Site”类,但是您可以按照您认为合适的方式构建您的类。

Public Class App

    Private Shared _Site As New Site
    Public Shared ReadOnly Property Site() As Site
        Get
            Return _Site
        End Get
    End Property

End Class

Imports System.Configuration
Imports System.Web

Public Class Site

    Public Enum EnvironmentType
        Development
        Staging
        Production
    End Enum

    Friend Sub New()

        If HttpContext.Current IsNot Nothing Then

            Dim URL = HttpContext.Current.Request.Url.DnsSafeHost

            Select Case URL
                Case ConfigurationManager.AppSettings("DevelopmentHost"), "localhost"
                    _Environment = EnvironmentType.Development
                Case ConfigurationManager.AppSettings("StagingHost")
                    _Environment = EnvironmentType.Staging
                Case ConfigurationManager.AppSettings("ProductionHost")
                    _Environment = EnvironmentType.Production
            End Select

        Else
            'probably getting called from a winforms/console app, or unit tests
            _Environment = EnvironmentType.Staging

        End If

        _ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString

    End Sub


    Private _Environment As EnvironmentType
    Public Property Environment() As EnvironmentType
        Get
            Return _Environment
        End Get
        Set(ByVal value As EnvironmentType)
            _Environment = value

            _ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString

        End Set
    End Property

    Private _ConnectionString As String
    Public ReadOnly Property ConnectionString() As String
        Get
            Return _ConnectionString
        End Get
    End Property

End Class

我们将类放入 Biz Object 类库中。我们刚刚决定不必确定每个请求的环境,因为它在应用程序的生命周期内确实无法更改。此外,这允许我们在库中的代码或后面的代码中从 ANYWHERE 引用 App.Site.Environment。如果您需要在代码中添加一些条件逻辑,这也很有帮助——比如在开发/暂存中运行时不向真实的人发送电子邮件。

最后一件事 - 对于我们的 Linq2SQL 或 EF Data/ObjectContexts,我们不会将连接字符串存储在文件中,而是重载构造函数,以便我们可以提供正确的环境连接字符串,如下所示:

Partial Class SampleDataContext
    Sub New()
        MyBase.New(App.Site.ConnectionString)
    End Sub
End Class
于 2009-05-21T04:51:34.757 回答
0

这是一个解决方案:将该文件存储为“ Web.Config.in”在源代码管理下。

在每台服务器(开发、测试、登台、生产)上,复制Web.Config.inWeb.Config并仔细编辑该AppEnv值。

在从一个环境到下一个环境的每次后续推送中,排除Web.Config文件。也就是说,不要覆盖该特定文件。例如,编写运行rsync --exclude WebConfig的部署脚本。

于 2009-03-16T18:54:02.640 回答
0

如果网站未处于生产模式,我在页面顶部以粗体红色字母显示该站点处于何种模式。

我还有一个诊断页面,其中列出了正在运行的服务器以及它连接到的数据库。

您还可以在每个数据库中放置一个查找表,以确保您连接了正确的标志。(在测试数据库中将其标记为 1 并检查 Application_Start 值是否匹配)

于 2009-03-16T18:58:31.177 回答
0

每当有一个过程总是需要不止一个步骤时,我知道我至少有一半的时间会搞砸它。出于这个原因,我喜欢 MSBuild。

MSBuild 的盒子中有很多有用的任务,例如AspNetCompiler 任务,它似乎是一步编译/发布操作。

还有几个项目为各种目的聚合了大量“自定义”MSBuild 任务。MSBuild 社区任务项目有一个 XmlMassUpdate 任务,可用于对 xml 格式的文件进行多项更改。换句话说,非常适合更新 web.config 文件。

我在这里找到了一个将 XmlMassUpdate 任务与 Web 部署项目结合使用的示例。

于 2009-03-16T19:49:48.200 回答
0

一个不断出现的永恒问题!我猜几乎任何认真的 ASP.NET 开发人员都曾在某些方面对此表示反对。

对于 ASP.NET 4.0,有一些帮助 - 改进的 Web 部署选项将提供一个称为“web.config 转换”的功能。

查看有关该主题的第 9 频道视频- 尚未找到任何体面的书面参考资料...

马克

于 2009-03-17T06:27:35.360 回答
0

我将任何在测试和生产中不同的密钥放入一个全新的 .config 文件中。我将测试设置放在测试上,将生产设置放在生产上,并且从不将此文件从测试复制到生产。然后,在您的常规 web.config 中,您可以像这样指定这个新的 .config 文件:

<appSettings file="ExternalWeb.config>
    .... common keys go here
</appSettings>

在测试服务器上,“external.config”将包含特定于该服务器的值,在生产中,它将具有 prod 值。这允许您在两台服务器之间复制整个 web.config,而无需手动更改文件。

于 2009-03-17T12:42:47.767 回答
0

我认为在 web.config 中存储连接字符串是不好的做法,而是在我的网站之外的一个常见的已知位置创建一个单独的配置文件,例如

C:\xxxx\config.xml

然后我将所有与机器相关的设置存储在那里。因此,在我的实时服务器上,我有我的实时设置,在测试数据库的测试服务器连接字符串和我的开发机器上,我有我的本地设置。然后,这些设置也可以在该服务器上的所有网站和 .net 应用程序中继续使用。数据库更改时只有一个地方需要更新。

完美的!

于 2009-05-09T08:19:14.330 回答
0

将您的 Web.Config 设置为“只读”,因此在发布到这些服务器时不会被覆盖。

权衡是您必须手动维护每台服务器上的 web.config,并且您的发布将声称失败,因为它无法覆盖远程服务器上的 web.config;但恕我直言,这比每次上传时都修改配置更可取

于 2009-05-29T00:30:44.577 回答