سؤال

Yes there are a lot of posts about this issue and I have tried the suggestions in many of them and none of them have worked. Please do not tell me that this has been asked already.

I have been asked to update an internal website that interacts with a database. It was originally created in VS 2003, which we do not have access to anymore so it necessitated an upgrade of the project to VS 2012. I have one last problem to fix. The original designer of the site used the following block of code to set the environment so that the correct database could be connected to:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' Fires when the application is started
    Select Case LCase(HttpContext.Current.Request.ServerVariables("SERVER_NAME"))
        Case "localhost", "development_domain"
            DB_Environment = "DEVELOPMENT"

        Case "staging_ip", "staging_domain"
            DB_Environment = "STAGING"

        Case "external_prod_domain", "external_prod_ip", "internal_prod_domain"
            DB_Environment = "PRODUCTION"
    End Select
End Sub

The various environments are in the process of being upgraded to IIS 7.5. This means that this site now blows up in the dev environment because HttpContext.Current is no longer supported in IIS 7 and later.

Many of the suggested fixes talk about moving the functionality to Application_BeginRequest method. I'm not really interested in having this fired off every time a request is made as it is unnecessary, and also it seems to cause issues with the application.

Part of my problems is I cannot try some of the suggestions as they are coded in C# (with which I am very familiar) and the application is coded in VB (with which I am not so familiar).

Can anyone point me in the right direction as to how I can retrieve the domain to hold in the DB_Environment variable without using the HttpContext.Current method?

هل كانت مفيدة؟

المحلول 2

To clarify one point first: HttpContext.Current is still available in IIS 7, it's just not available in Application_Start because there is not necessarily an incoming request from an external user that causes the event to fire.

Now, to the problem:

You did not show how DB_Environment is defined, but I suspect it is just a standard Property, i.e.

Public Property DB_Environment As String

If this is the case, you can easily and seamlessly address your problem by changing DB_Environment to a readonly property with a backing member variable and then perform the initial configuration if the backing store property has not been set. In this design, it will only be initialized when needed and it should only be needed when an external user makes a request, thus ensuring an HttpContext.

Here is the proposed design:

Private m_DB_Environment As String = Nothing
Public ReadOnly Property DB_Environment As String
   Get
       ' If we haven't retrieved the setting yet and there is a current context, 
       ' retrieve the appropriate setting
       If m_DB_Environment Is Nothing AndAlso HttpContext.Current IsNot Nothing Then
          Select Case LCase(HttpContext.Current.Request.ServerVariables("SERVER_NAME"))
              Case "localhost", "development_domain"
                  m_DB_Environment = "DEVELOPMENT"

              Case "staging_ip", "staging_domain"
                  m_DB_Environment = "STAGING"

              Case "external_prod_domain", "external_prod_ip", "internal_prod_domain"
                  m_DB_Environment = "PRODUCTION"
          End Select
       End If

       Return m_DB_Environment
   End Get
End Property

نصائح أخرى

if (System.Environment.MachineName == "xxx")

Although, the preferred way of doing that is to have a base web.config file, and creating XLST transforms for your different environments that change the values based on how you publish your project. For example, we have web.config, web.release.config, web.debug.config, and web.staging.config. We have different values for caching, output caching, the debug attribute, connection strings, email server settings, etc for each environment and they all get swapped out at publish time.

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' Fires when the application is started
    Select Case LCase(System.Environment.MachineName)
        Case "localhost", "development_domain"
            DB_Environment = "DEVELOPMENT"

        Case "staging_ip", "staging_domain"
            DB_Environment = "STAGING"

        Case "external_prod_domain", "external_prod_ip", "internal_prod_domain"
            DB_Environment = "PRODUCTION"
    End Select
End Sub

You will need to find out the names of your various machines instead of the requested URL for this to work, but it is likely the quickest fix to upgrading your old code.

Move your code into an abstraction. Have that code query HttpContext.Current.Application["DbEncironment"], store it if it doesn't exist and return. That way it will get set when first accessed, and read all other times.

Public Class DbEnvironment

    Public Function Shared GetEnvironment() As String

        Dim e = HttpContext.Current.Application["DbEnvironment"]

        If (e = Nothing) Then
            Select Case LCase(HttpContext.Current.Request.ServerVariables("SERVER_NAME"))

                Case "localhost", "development_domain"
                    e = "DEVELOPMENT"

                Case "staging_ip", "staging_domain"
                    e = "STAGING"

                Case "external_prod_domain", "external_prod_ip", "internal_prod_domain"
                    e = "PRODUCTION"
           End Select

           HttpContext.Current.Application["DbEnvironment"] = e
        End If

        Return e

    End Function

End Class

Now where you need to access your environment call

DbEnvironment.GetEnvironment()

and it will always work. You can make it a property as well, if that is more your style.

How proliferate is the use of the DB_Environment parameter in the application? If it isn't too extensive, I'd recommend changing the system out to take advantage of web.config transforms. By doing this, you'd essentially replace your DB connection string/Application Setting variables with a call to their "normal" name (ConnectionSting, MagicPath, etc.) and then you can maintain those values through the web.debug.config, web.release.config, etc. files.

The advantage of this is you can treat your app as an app and not a "Environment X App" for which one wrong configuration (or naming of a server) can mess things up and really be hard to maintain.

If you really need to "hack this out" You could add a AppSettings key called "Environment" in your web.config, utilize the transforms, and then have your method listed above simply read from there (done in 1 line or 2). That way you can still maintain your environment settings without fancy coding.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top