I have an application, a survey. The way I'm testing it is I opened the survey with first tab, then I opened a new survey with the second tab. On the query string/URL, they have different IDs. I answered all the questions on the first tab but I don't submit yet. Then I'll answer the questions on the second tab, but not submitting it yet. Now, I will submit the answers from my first tab. If I checked on the database, it will get all the answers I put on the second tab. So that means the global variables were overwritten whatever last input I made. How will I prevent this, how do I make sure that I'm opening two surveys at a time with different sessions?
I haven't used Session yet, I'm just assuming that it will be the solution for my problem. Maybe someone could direct me on how to use sessions or suggest other solutions to in preventing my problem.
Public Class GlobalSessionVariables
Private _Zone_ID As String = "ZONE_ID"
Public Property ZONE_ID() As Integer
Get
Return HttpContext.Current.Session(_Zone_ID)
End Get
Set(ByVal value As Integer)
HttpContext.Current.Session(_Zone_ID) = value
End Set
End Property
End Class
Public Function Insert(ByVal zondeID As String) As Boolean
Try
'Calling a DB command to store value in the DB
Result = Insert(_Application_Component_Number, zondeID )
Catch ex As Exception
End Try
Return Result
End Function
Private BO_Survey As New MaintainBusinessClass(_AppComponentNum)
Private _GlobalSessionVariables As New GlobalSessionVariables
Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click
Try
Page.Validate()
If Page.IsValid Then
'Get the page 1 Answers
_GlobalSessionVariables.ZONE_ID = CInt(txtAnswer1.Text) 'ZoneID for Question-1
End If
Catch ex As Exception
End Try
End Sub
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Try
Page.Validate()
If Page.IsValid Then
BO_Survey.Insert(_GlobalSessionVariables.ZONE_ID)
End If
Catch ex As Exception
End Try
End Sub
Well, it not at all clear why you have some class to simply place some value into Session, and then pull the value out.
I mean, why not just go
Session("ZoneID") = some value
And to get the value back, then just go
some value = Session("ZoneID")
So, you have to explain why you going to all that trouble to build a class when simple use of Session("some value") should suffice.
The next issue is having some "ID" in the URL. I recommend you don't use URL query parameters for things like database ID values, since the user can change or type in different values, and that means they may well be able to view or save to an ID that does not belong to the current user.
So, there are several options to persist values, and session is "global" to the one current user. However, if you build a page that works from some ID value, then if two pages are open, and open to a different ID in session, then you going to have trouble. Those pages may well be based on the current page ID, or the user might even have two or three copies of the browser open, and thus any and all Session() values will be the same.
However, you can adopt ViewState for storing a few values. ViewState is per page, and not global per user.
Hence, often I will have a set of variables for a given page, and since using a whole bunch of Session() variables in such pages does not work well? (too many session values to keep track of).
Hence, the VERY instant you have multiple pages open, then session() will be the same for all pages, and thus code behind does not work well when using session().
And I really beyond strongly recommend you don't open multiple browser tabs, since that often means the user will get lost as to what the next step or option to use on a given page, since now you have multiple pages open.
In fact, all the rage today is called SPA's (Single page applications, and here you are now building an application with multiple tabs being open, and that's simply a bad design choice).
In fact, ask yourself what web application have you used in which multiple tabs are used and opened? For example, you are reading this post on SO, and does it work by opening a new tab for each post you view? Answer = no, it does not.
However, we still often need a set of persisting values and variables to allow a page to correctly work. And we often still need to pass a set of values from one web page to the next.
Since ViewState is per web page, and not global to the one user, then I often adopt the following design pattern:
To pass values from one page to the next, and not have some messy (and not secure) ID values in the URL?
I use Session() to pass the values to the next page, but on first page load, I then transfer Session() values to ViewState().
This in near all cases then allows you have multiple pages or tabs open to the one same URL, and allows multiple pages to work correctly, since now the persisted values for that one page are limited to the one web page, and not global Session() to that given user.
Hence, say I have about 6-10 values that the code behind needs, so often I create a simple class for this purpose.
I recommend a simple class to hold all such values for a given page, since then you don't have to remember if that Session() value is being used by some other page, and thus breaking code behind in such pages when multiple copies of that page are open.
Hence, say this simple class:
<Serializable>
Public Class clsProjectInfo
Public ContactID As Integer = 0
Public ContactGeneralID As Integer = 0
Public PortalComp As String = ""
Public ProjectHeaderID As Integer = 0
Public QuoteNum As Integer = 0
Public InvoiceNum As Integer = 0
Public UpLoadGroup As Integer = 0
Public txtNotes As String = ""
Public ProofID As Integer = 0
Public DocketNum As Integer = 0
Public PONumber As String = ""
Public ProjectComponentID As Integer = 0
Public PortalID As Integer = 0
Public ShipLocatonID As Integer = 0
End Class
So, say in some search page, the user selects a project. I will setup the above class values and save into Session(). And thus in place of having a bunch of seperate Session() values, having one class to contain and pass such values around means only one Session() key value to keep track of.
Then on the target page we navigate to, I assume then Session() is correctly setup with that class that holds all the required values.
As noted, I then transfer the Session() object to ViewState(). Now, that page and code behind works from ViewState(), and thus I don't care if the user has 1 or 5 copies of that page open, it will continue to function correctly, and the values used in that page (code behind) are not Session() and are not global to the one user, but scoped to the one web page in question.
Hence, you see code like this in my page load event:
Public cPinfo As New ControlMIS.clsProjectInfo
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
cPinfo = Session("ProjectInfo")
ViewState("ProjectInfo") = cPinfo
Else
cPinfo = ViewState("ProjectInfo")
End if
Now, anywhere in code for that page, I'm free to use any and all of my persisted values for that one page.
Hence:
GetUserInfo.SetProjectHistory(cPinfo.ProjectHeaderID)
So, I have a current ProjectHeaderID (it is the primary key value from the database).
Hence, not only do I have a nice grouping of all the values required for the page to operate, I don't mess with Session() or ViewState() over and over on that page. Once page load has pulled the class from ViewState() (or first time Session, transferring into ViewState()), then all of my required code values for that one web page are persisted, and I simply use cPinfo in that code behind:
Hence, passing a hodge podge set of values to the next page becomes rather easy.
Those values having been transferred from Session() to ViewState() means that page does not use Session() anymore, but uses ViewState(), which as I pointed out is "per web page", and not "per web user".
And note in the above screen capture, how I have about 8 values that I can pass to the next web page, and I have ZERO need to place such values in the URL, which as I pointed out are often VERY dangerous, since the user is free to change such values the URL. Hence users will not be able to change things like the ID value in the URL. Far worse can occur by users changing such ID values, and this can result user's working on someone's else's data.
So, for database ID values, they should not be exposed in the URL, since the user with great ease can change that ID value. So, pass values between pages using Session(). And if you have a bunch of values to pass, then create a class, and use Session() to pass that class and "bunch" of variables to the next page.
Then on page load, transfer into ViewState(), and now you have a persisted set of values scoped to the one page. The result is the user can open 5 copies of their browser, and all copies on the same URL will work just fine, since ViewState() is scoped to the one page, not the user like Session() is.
Do use some caution, since ViewState() saves the values into the client-side browser, where as Session() is server based. So, don't place huge objects, or even table data into ViewState(), since such values become part of the page post-back, and thus large ViewState() objects will hurt performance in a significant way.
So, adopt the above design pattern.
Hence, for one value, just use Session("SomeValue") = some value.
For a bunch of values, create a class, and pass that.
And then on first page load, transfer the Session() values (our class) into ViewState(), and now you have per page persisting of such values for code behind to use.