How to get a public variable (in a Module) to NOT

2019-02-28 14:26发布

问题:

I'm working in an ASP.NET (VB) Web Application with Windows/Active Directory Authentication

I am using a module so that I can call public subroutines and functions, and reference variables, without having to instantiate a new object to access them on each page.

Within that module, I have some Public variables that I am using in multiple pages throughout the web application. I've recently realized that the values for these public variables in the module get shared between all users.

THE GOAL: I want the value for these global variables to be specific to a single user and not shared between all sessions, and I do not want to have to instantiate a new object/class on every page that uses the variable.

THE CATCH: I don't want to store the value in a client-side variable such as a cookie or session. I want the value to be stored on the SERVER but specific to each client/user.

The only thing I can think to do is setup a global collection/dictionary and store the variables with the authenticated user names, but then I need to have specific functions to get and set the values. While this will work, it requires all the references to these variables on all pages in the application to be updated.

EXAMPLE OF THE PROBLEM: The below code shows how I am creating the public variable within the module and how the value is being set from one page and used on another. I'd like to continue to use this variable in the same way and share it's value between pages, but the value of the variable needs to NOT be shared between users.

-- MODULE.VB --

Public Module MyMod  
    Public myVariable as String = ""  
End Module  

-- MAINPAGE.VB --

  Partial Class _Default  
        Sub Page_Load() Handles MyBase.Load()  
           myVariable = "HELLO WORLD"  
        End Sub  
    End Class  

-- NEXTPAGE.VB --

  Partial Class _Default  
        Sub Page_Load() Handles MyBase.Load()  
           Response.Write(myVariable)  
        End Sub  
    End Class  

There are a LOT of pages in this application that will need to be manually updated if I have to use my userID-indexed collection solution, so I'm hoping there is a way to simply scope these variables differently or a way to disable the sharing between sessions. Thanks in advance!

回答1:

You didn't indicate whether or not the variables need to be persisted across page round trips or whether they are just used within each page's lifecycle.

If they are not persisted across pages, then perhaps the easiest solution is to have all of your pages inherit from a based page class and then move the values from the module into the base page. This way you won't have to change any variable references, only page inheritance.

If you do want to persist the values, completing the above changes makes it much easier to implement. You can then turn the member variables on the base page into properties and embed your user specific caching and fetching in the getter and setter.

For example, instead of:

Public MyVariable As String = ""

You would have something like:

Public Property MyVariable As String
    Get 
       Return GlobalMyVariableCache(UserNameKey)
    End Get
    Set (Value As String)
       GlobalMyVariableCache(UserNameKey) = Value
    End Set
End Property


回答2:

The problem you are coming across is a very common one in web programming. A Module's members are static - meaning there is one instance of them across the entire AppDomain of your application. Every user that accesses these will get the same object - you have already learned this.

Your options are exactly what you described. You could possibly replace the public variable in your module with a property whose getter you write to access a user-specific field in a dictionary (please remember thread safety when writing this getter code).

The much easier solution would be to use the Session. Session values are stored server-side and are user specific. The only thing that get's sent client side is the session key, and if you are using .Net authentication, this is likely already getting sent.

Good luck,