Come assicurarsi che pubblichiamo la produzione sul server di produzione e testiamo sul server di prova

StackOverflow https://stackoverflow.com/questions/651668

  •  19-08-2019
  •  | 
  •  

Domanda

Ho una voce nel mio file Web.Config che indica l'ambiente in cui mi trovo per le stringhe di connessione e la posta indesiderata:

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

Sto cercando un modo per avvisare lo sviluppatore, al momento della pubblicazione, per assicurarsi che abbiano controllato questa chiave / valore in modo da non pubblicare il "test" sul server "prod" e viceversa .

Grazie

È stato utile?

Soluzione

Ho trovato la mia soluzione (probabilmente non convenzionale) a questo problema. Sviluppiamo molti progetti Web diversi per molti clienti diversi e li abbiamo migrati tutti a questo metodo a causa di tutti i problemi che abbiamo riscontrato con più file web.config o delle modifiche necessarie prima della pubblicazione.

Fondamentalmente, lasciamo che la nostra app ci dica in quale ambiente è in esecuzione in base all'URL in arrivo. Inizializziamo questo alla prima richiesta e lo memorizziamo in memoria per la vita dell'app. In questo modo possiamo memorizzare ciascuno dei nostri valori di configurazione specifici dell'ambiente nello stesso file di configurazione e qualificarli semplicemente con Sviluppo, Staging, Produzione, ecc. E qualsiasi impostazione che non differisce tra ambienti non deve essere qualificata.

Prima un esempio 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>

Ora abbiamo un'app " App " classe che ci dà accesso al nostro " Sito " classe, ma potresti progettare le tue classi come meglio credi.

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

Mettiamo le nostre classi nella nostra libreria di classi Biz Object. Abbiamo appena deciso che non è necessario determinare l'ambiente su ogni singola richiesta, dal momento che non può cambiare durante la vita dell'app. Inoltre, questo ci consente di fare riferimento a App.Site.Environment da ANYWHERE nel codice nella libreria o nel codice dietro. Ciò è utile anche se è necessario cospargere una logica condizionale nel codice, ad esempio non inviare e-mail a persone reali quando si esegue in sviluppo / messa in scena.

Un'ultima cosa: per i nostri Linq2SQL o EF Data / ObjectContexts, non memorizziamo la stringa di connessione nel file e sovraccarichiamo il costruttore in modo da poter fornire la nostra stringa di connessione all'ambiente corretta in questo modo:

Partial Class SampleDataContext
    Sub New()
        MyBase.New(App.Site.ConnectionString)
    End Sub
End Class

Altri suggerimenti

Ecco una soluzione: archivia quel file come " Web.Config.in " sotto il controllo del codice sorgente.

Su ciascun server (sviluppo, test, gestione temporanea, produzione), copiare Web.Config.in in Web.Config e modificare AppEnv valore attentamente.

Ad ogni spinta successiva da un ambiente all'altro, escludere i file Web.Config . Cioè, non sovrascrivere quel particolare file. Scrivi ad esempio script di distribuzione che eseguono rsync --exclude WebConfig .

Ho in grassetto rosso nella parte superiore della pagina in quale modalità si trova il sito se non è in modalità Produzione.

Ho anche una pagina di diagnostica che elenca su quale server è in esecuzione e a quale database è collegato.

Puoi anche inserire una tabella di ricerca in ogni database, per assicurarti di avere il flag giusto collegato ad esso. (nel DB di prova contrassegnarlo come 1 e verificare su Application_Start che i valori corrispondano)

Ogni volta che c'è un processo che richiede sempre più di un passaggio, so che lo rovinerò almeno la metà delle volte. Per questo motivo, adoro MSBuild.

Esistono numerose attività utili fornite con MSBuild, come attività AspNetCompiler , che sembra essere un'azione di compilazione / pubblicazione in un solo passaggio.

Esistono anche diversi progetti che aggregano un gran numero di "personalizzato" Attività di MSBuild per vari scopi. Il MSBuild Community Tasks Project ha un'attività XmlMassUpdate utile per apportare diverse modifiche a un file in formato xml. In altre parole, perfetto per l'aggiornamento dei file web.config.

Ho trovato un esempio dell'utilizzo dell'attività XmlMassUpdate in concerto con un progetto di distribuzione Web qui .

Un'eterna domanda che continua a spuntare! Immagino che qualsiasi sviluppatore ASP.NET serio abbia in qualche modo sbattuto la testa contro questo.

Per ASP.NET 4.0, ci sono alcuni aiuti in arrivo: le opzioni di implementazione web migliorate offriranno una funzione chiamata " trasformazioni web.config " ;.

Dai un'occhiata a Video del canale 9 sull'argomento - non ho ancora trovato alcun riferimento scritto decente ...

Marc

Prendo tutte le chiavi che saranno diverse nel test e nella produzione e le inserirò in un file .config completamente nuovo. Ho messo alla prova le impostazioni di prova e le impostazioni di produzione in produzione e non ho mai copiato questo file dalla prova alla produzione. Quindi, nel tuo normale web.config, puoi specificare questo nuovo file .config in questo modo:

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

sul server di prova, " external.config " conterrà i valori specifici per quel server e in produzione avrà i valori prod. Ciò consente di copiare l'intero web.config tra i 2 server senza mai modificare manualmente il file.

Penso che sia una cattiva pratica archiviare stringhe di connessione in web.config, invece creo un file di configurazione separato al di fuori dei miei siti Web in una posizione nota comune come

C: \ xxxx \ config.xml

Quindi memorizzo tutte le impostazioni dipendenti dalla macchina. In modo che sul mio server live ho le mie impostazioni live, sulle stringhe di connessione del server di prova al DB di test e sulla mia macchina Dev ho ottenuto le mie impostazioni locali. Queste impostazioni possono quindi essere ridimensionate lungo tutti i siti Web e le app .net su quel server. Solo un unico posto da aggiornare quando il DB cambia.

Perfetto!

Imposta il tuo Web.Config su " Sola lettura " ;, pertanto non verrà sovrascritto durante la pubblicazione su questi server.

Il compromesso è che dovrai mantenere manualmente i tuoi web.configs su ciascun server e la tua pubblicazione dichiarerà di fallire perché non potrebbe sovrascrivere web.config sul server remoto; ma IMHO è preferibile per modificare la configurazione ogni volta che esegui un caricamento

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top