Я придумал собственное (возможно, нетрадиционное) решение этой проблемы. Мы разрабатываем много разных веб-проектов для множества разных клиентов и перенесли все из них на этот метод из-за всех проблем, которые у нас были с несколькими файлами web.config, или из-за необходимых изменений перед публикацией.
По сути, мы позволяем нашему приложению сообщать нам, в какой среде оно работает, на основе входящего URL. Мы инициализируем это по первому запросу и сохраняем в памяти на всю жизнь приложения. Таким образом, мы можем хранить каждое из значений конфигурации, специфичных для нашей среды, в одном и том же файле конфигурации и просто квалифицировать их как «Разработка», «Подготовка», «Производство» и т.д.
Сначала образец 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. Мы просто решили, что нет необходимости определять среду для каждого отдельного запроса, так как она действительно не может измениться за время существования приложения. Кроме того, это позволяет нам ссылаться на App.Site.Environment из ЛЮБОГО ГОДА в коде в библиотеке или коде позади. Это также полезно, если вам нужно добавить в ваш код некоторую условную логику - например, не отправлять электронные письма реальным людям при работе в dev / staging.
И последнее: для наших Linq2SQL или EF Data / ObjectContexts мы не храним строку подключения в файле, а вместо этого перегружаем конструктор, чтобы мы могли предоставить нашу правильную строку подключения к среде, например:
Partial Class SampleDataContext
Sub New()
MyBase.New(App.Site.ConnectionString)
End Sub
End Class