I have a website where people send each other messages
Recently I noticed that sometimes the same message is sent more than once
For example, a message is sent four times within three seconds or twice within a second
I do not understand how this could happen, once the user clicks on the button that sends the message
So all the window switches and a message showup saying "the mail is sent successfully."
I checked that if the user refreshes the page after it sends a message, then really the message is sent again.
But I do not think that's the case, becouse the message is sent twice within one second.
I am writing in vb.net and using mysql data base.
Maybe it's related to the queue for the db, i do not know.
I need to know where to look
Hope for your help
Here's the code:
Function calls:
Call GlobalFunction.update_mailbox_table(user_id, receiverId, txtMessage.Text, private_picture)
the insert function
Public Shared Sub update_mailbox_table(ByVal user_id As Integer, ByVal receiverId As Integer, ByVal message As String, ByVal privatePicture As Integer)
' update mailbox table
Dim connString As String = ConfigurationManager.ConnectionStrings("mysql_ConnString").ConnectionString
Using mysqlconn As New MySqlConnection(connString)
Dim sqlCommand As String = "INSERT INTO mailbox_table (FromId,Message,ToId,SendingDate,MsgStatus,PrivatePicture) VALUES (#FromId,#Message,#ToId,#SendingDate,#MsgStatus,#PrivatePicture)"
Dim mysqlcmd As New MySqlCommand(sqlCommand, mysqlconn)
Try
mysqlconn.Open()
mysqlcmd.Parameters.AddWithValue("#FromId", user_id)
mysqlcmd.Parameters.AddWithValue("#Message", message)
mysqlcmd.Parameters.AddWithValue("#ToId", receiverId)
mysqlcmd.Parameters.AddWithValue("#SendingDate", Date.Now)
mysqlcmd.Parameters.AddWithValue("#MsgStatus", 0)
mysqlcmd.Parameters.AddWithValue("#PrivatePicture", privatePicture)
mysqlcmd.ExecuteNonQuery()
Catch ex As Exception
sendToLog(ex, "problem to update mailbox table")
End Try
End Using
End Sub
The problem is not in the database code, my psychic debug power tells me that your user double of quad clicks on your submit button.
Are you using Javascript to show the message client side (i.e. actually before the message has been sent), or are you showing the message when the page reloads after sending the message?
If you are not hiding the button using client script, the user can easily click several times before the page reloads. Each click will send a request to the server, but the browser only shows the response for the last click.
Related
I am trying to store the UserId or/and UserName of the user. This is used to record user ID against any changes they make to data, insert, updates and deletes etc.
I have created a module and in that module added a Public variable vUserID. Here Lei the problem.
User A logs in and his id vUserID = 'A'. Another user (User B), the other side of the world logs in User 'B' and that vUserID then = 'B'. So now anything User A does gets recorded as he is User 'B', or that is how I understand it, as a Public variable will be accessible from anyone who logs in.
I understand the problem, or I think I do, please correct me if not, but what I am struggling with is the solution. I have tried to use a Protected and Protected Friend but these do not seem to be accessible throughout the program(website) when a user is logged in.
For completeness I get the User details by the following code which seems to work fine:
Dim mu As System.Web.Security.MembershipUser = System.Web.Security.Membership.GetUser()
Module1.vUserID = mu.ProviderUserKey.ToString()
Well, the issue is that you have ONE web server.
And the web server (for the most part) will process ONE web page at a time.
So, when a user clicks a button on a web page, before they click on a button, the web page is sitting on their desktop computer. it is NOT on the web server.
(and more important, all the code variables (code behind) are GONE! They do not exist yet!).
So, think of a web server as ONE computer. And say 5 users are going to use YOUR computer to edit a word document.
The first user sits down, opens word document, types in some text, and then closes word!
The next user sits down, opens word document, types in some text, and then closes word!
Remember, you don't have a computer for each user, but have ONE computer - the web server, and it has to "some how" service all users.
So, all the web server can do, is "process" a web page, one that is sitting on each end users computer (running the browser).
So, you have this:
And you do NOT have this:
In other words, the web page is NOT sitting "loaded" on the web server. it is out of scope.
Think of when you call a sub, use some variables in that sub, when you return/exit from that sub, ALL VARIABLES are gone!! (out of scope).
You MUST think of web pages like that sub - when you exit, they are gone, don't exist anymore.
So, you don't have this:
the web page is NOT in memory on the server, it is NOT loaded.
Thus, you don't have this either:
So, with above in mind, lets create a super simple web page to show this:
We will have a simple string variable, called MyZooVar.
We will put a button and label on the web page to set this varible.
we will then put another button on the form to show the value of the variable.
So, this:
<asp:Button ID="cmdSetZoo" runat="server" Text="set varable to zoo" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<br />
<br />
<asp:Button ID="cmdGetZoo" runat="server" Text="get value of var zoo" />
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
and the code behind is this:
Public MyZooVar As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub cmdSetZoo_Click(sender As Object, e As EventArgs) Handles cmdSetZoo.Click
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
End Sub
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Note VERY close in above, the MyZooVar - we defined it at the top of module, so all buttons and code can use that MyZooVar.
So, we will click the first button, this code:
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
And then we have a 2nd button, and this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
what will happen when we run?
We see this:
So, in above, this is what occured:
we START with this:
You click a button, YOUR web page (not the 20 other users) is sent to the web server.
the page travels up to server,
You now have this:
Now and THEN your code behind runs. When done, your code behind MUST finish, else the page stays stuck up on the server side. When done, the whole page page makes the trip down back to the browser. And THEN the page is re-displayed and THEN any js code can run.
So when done? Your page makes the trip back down to the browser like this:
Note on the server side? Your web code (and MORE important variables) and EVERYTHING is disposed.
We now have this again:
Note HOW THE WEB PAGE IS NOT on the web server!!!!
the web server is waiting now for ANY post-back of a web page from ANY user, not just you the one user!!!!
So, now that I clicked the button to set the variable MyZooVar?
What happens if I click on the 2nd button, this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Well, the whole process starts over again!!!
We will find that the variable MyZooVar is gone, out of scope, and does not have our value!!!
So, the "term" for the above is what we call "state-less".
In other words, your code behind can't assume, hope, pray that the varibles in the web page will persit.
Now you can hope/pray/try to put some variables in a global code module, but as you found out, they are shared amoung all users. But WORSE, the web server will often say, hey, I don't need that memory, I'm just sitting here waiting for someone to click a button and send me THEIR web page.
As a result, not only will you find those so called global variables in that public code module shared between all users, you find that they OFTEN will not even stay in memory all that long. So, your code "sort of works" to try and use some global variables, but you find they OFTEN go out of scope, and will not even stay in memory.
So, web based software is VERY different then desktop software.
One big difference is that for desktop software, each user, each workstation has their OWN copy of the code.
With a web server, you have ONE web server, ONE computer, and it sole job is to process incoming web pages (that occurs due to a page post-back).
the process of a simple button click, whole web page travel up to web server, page is processed, and then whole page is send back to user? We call this a round trip.
So, you really do not have global variables in a web based application. You can try to use some, but as noted, they will be the same for all users, but MUCH worse, is they tend to go out of scope, and can be disposed (go away) at any old time - you have no control over this, and thus you simple can't adopt global variables in a web based system - they are "off limits", and the above so called round tripping, and that you have ONE computer and ONE web site that somehow has to service many users - not just you!!
So, in your case?
Why do you need to store/save the user ID in some variable?
You "already" are able to get the user id with the code you shared:
You can use this:
dim UserID as integer
UserID = Membership.GetUser().ProviderUserKey
So, since you can get the "user" id any old time with above ProviderUserKey, then no need exists to try and "save" the user id into some global variable, but as you found out, you can't rely, or even design your software based around a concept of global variables.
However, you can if you wish place values into what we call "session".
Session is in effect global to the ONE user, and it DOES persist between those so called round trips.
so, you could do this:
Session("MyUserID") = Membership.GetUser().ProviderUserKey
And then in code, any time, use
Session("MyUserID") to get the user "id"
But, since you have ProviderUserKey, then even session() should not be required here.
Label is not visible in the following code . I need to show a message please wait when the user clicks login.It shows before but after adding the time interval its not showing
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
System.Threading.Thread.Sleep(5000)
Form2.Show()
Hide()
Else
MsgBox("Sorry, The Username or Password was incorrect.", MsgBoxStyle.Critical, "Information")
End If
End Sub
Thread.Sleep on the UI thread will cause your form to "freeze". It sounds like you want some sort of waiting indicator while the background code is running.
What you should do is execute your long running code asynchronously, show your label, wait for the asynchronous code to finish, then do something (e.g. hide the label).
Using your code, it'd look something like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Show()
If (TextBox1.Text = "Akilan" AndAlso TextBox2.Text = "123") Then
Dim t = Task.Run(Sub() Threading.Thread.Sleep(5000))
t.Wait()
Label3.Hide()
Else
MessageBox.Show("Sorry, the username or password was incorrect", "Invalid Credentials", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
The way to do this is to hide/show the label text client side. Then when the page travels up to server and your code behind runs, the client side will still show that message. When you code behind is done, then the whole page now travels back down to the client side is re-load + re-display.
Grasping the above so called "round trip" is REALLY important here.
Since your code behind never interacts with the user, but only that copy of the web page that JUST traveled up to the server, and the code behind can play with, change and modif that page - but client side can ONLY see such updates AFTER the page travels all the way back down to client side. That's why this code can't work:
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
System.Threading.Thread.Sleep(5000)
Form2.Show()
Hide()
The above code will set Label.visible = true, but the whole page has not yet done its code, and the whole page is still on the server side. ONLY AFTER all your code is done, does the page travel back to client side, and show the label - but ALL code has to complete before page travels back down to client side.
However, this code will work just fine:
So lets look at above:
First up, we do NOT use visible=false for the label. The reason is that if you do that, then the label is NOT rendering in the markup.
Next up, we added a onclient click event to the button.
And we have our button code that has this code:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Thread.Sleep(3000)
End Sub
So, when you run this, you see this for 3 seconds:
So what happens?
Well, you click on button - the OnClient code (javascrt client side) will run and THEN the post back of the page up to the server occurs.
So, since that label is now "show", then it will display. Now the web page is up on the server - your code behind runs. When code behind is done?
The WHOLE page now makes the trip back to browser client side. And this ALSO means our label message will automatic hide again - since the page is re-plotted with the whole new page that the server just send back to the client side.
Do note, that in above, I assumed jQuery is installed. If not then your script will have to be this:
function ShowLabel()
{
lbl = document.getElementById("lblMessage")
lbl.style.display = "inline"
}
Note also close how I set the id mode of lable = static - I often do that, since then referencing controls in js becomes a lot easier.
So, the real trick here?
We display the label client side, and then whatever and how ever long the server takes is the amount of time the label will display. And when that whole new fresh web page comes back down from the server, then the label will re-vert back to being hidden (display:none).
So, do keep in mind this VERY important concept of round trip. When you code runs behind and changes values or controls on the page? The end user does NOT see such changes until ALL code behind is done, AND THEN the page travels back down to the user. In fact, then your code behind to hide or show, can become before or after the delay in code - it will NOT update client side and in fact the order that that change label and delay will NOT matter (since the web page is STILL up on the server). So all your changes you make to the page remain up on the server until all code is done, and THEN the whole page comes back to client side to show such changes.
The other way would be to consider ajax calls - but baby steps here first, right?
You can make Button Click event asynchronous.
The following code works for me:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label3.Visible = True
If TextBox1.Text = "Akilan" And TextBox2.Text = "123" Then
Label3.Text = "Please wait"
Await Task.Delay(500)
Label3.Text = ""
Form2.Show()
Hide()
Else
MsgBox("Sorry, The Username or Password was incorrect.", MsgBoxStyle.Critical, "Information")
End If
End Sub
Also check:
Async (Visual Basic)
When to use Task.Delay, when to use Thread.Sleep?
I am in the beginning stages of working with paypal checkout in my website and I am trying to use a sandbox account to test some things out. I am able to go through and purchase the item with another sandbox account but after I purchase the item, it stays on the paypal checkout page and tells me that I have completed my payment and I will receive an email notification. I need it to return to some other website url so that I can try to get details of the transaction in my code behind. My code posted below is very basic and I do not have anything in the code itself about the return URL, I have filled it in under my sandbox account settings.
The second part of the problem is that I have not published my website yet, I am using the visual basic debugger to view and test my site in a browser and when I attempt to put my "local host" url into the return url it gives an error: "We were unable to validate the URL you have entered. Please check your entry and try again." an example of the url I am trying to put in is
http://localhost:11111/WebSite1/Parts_Catalog.aspx
As a test url just to attempt to start getting data back from the transaction I just put in google.com thinking that it would at least return to google with either an error or the returned query strings but it doesn't attempt to load any pages at all after the transaction.
How can I get the paypal sandbox return url to actually return to a URL? How can I enter my local host URL into the website preferences return url and actually get it to recognize my url as listed above?
Here is the markup code
<asp:ImageButton ID="AddToCartBtn" runat="server"
RowIndex='<%# Container.DisplayIndex %>'
ImageUrl="~/Pictures/ShoppingCart.png"
OnClick="AddToCartBtn_Click" />
Here is the code I have so far for my addToCart button, I don't know if I need to add anything here or not for the return url
Protected Sub AddToCartBtn_Click(sender As Object, e As ImageClickEventArgs)
Dim Item As String = "Test"
Dim price As String = cost
Dim business As String = "test#aol.com"
Dim itemNumber As String = str2
Dim itemAmount As String = price
Dim currencyCode As String = "USD"
Dim addItem As Integer = 1
Dim ppHref As StringBuilder = New StringBuilder()
ppHref.Append("https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_cart")
ppHref.Append("&business=" + business)
ppHref.Append("&item_name=" + itemName)
ppHref.Append("&item_number=" + itemNumber)
ppHref.Append("&amount=" + itemAmount)
ppHref.Append("¤cy_code=" + currencyCode)
ppHref.Append("&add=" + addItem.ToString("#0"))
Response.Redirect(ppHref.ToString(), True)
Dim ReturnQaunity As String = itemAmount
GetRouteUrl("/v1/payments/orders/<Order-Id>")
End Sub
I don't currently have anything in my page load event that deals with paypal.
Andre is right, the return URL must be accessible to PayPal.
What you can do is use a generic URL (I guess google.com would work but it might be better to use one of your own) then edit the URL in the browser window.
So return to something like http://www.test.com/return.html?paypalparms...
Then when it displays in your browser change the URL to
http://localhost/return.html?paypalparms...
Then press enter.
I have used a similar technique with PayPal PDT and IPN testing and it works fine.
I would have replied to your comment but I haven't yet reached the dizzy heights of 50 reputation which allows me to comment everywhere.
I am using ASP.NET in Visual Studio 2010.
I have a website that features a shopping cart, the user can signup which has validation using the RequiredFieldValidator control meaning they must enter something for certain fields e.g. Address 1 / E-Mail. This is also tied to a Database which for these fields does not allow null values.
My issue that is after logging in, adding items to cart, quantities etc, I have a confirmation order page - similar to most online shopping websites were the shopping basket is displayed along with the user's Customer Details, which is shown through a DetailsView, connected to a SqlDataSource which is running a query that just displays their shipping details as previously entered.
However, if I say select Edit, which is using the DetailsView's own property and change the Address1 line to nothing, the DetailsView sends it as null value after accepting and as a result the whole thing crashes.
I have tried examples like:
Protected Sub DetailsView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewPageEventArgs) Handles DetailsView1.PageIndexChanging
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
Protected Sub DetailsView1_ItemUpdating(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
Protected Sub detailsView1_ItemUpdated(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
Try
Catch ex As Exception
lblError.Text = "Please verify changes made to Customer Details."
End Try
End Sub
So basically Try / Catch statements which has worked for everything else. But because I can't get access to any proper code behind for the DetailsView since it's just taken from Visual Studio I'm stumped. Has left me curious now, looked about here and elsewhere and couldn't find much, anything seemed similar to what I've tried there but they don't make a difference.
I want to try and create/find some form of Error Handling for this situation, similar to registering, either not proceeding with sending to the server if left blank or display a message.
This is the main part of the error:
[SqlException (0x80131904): Cannot insert the value NULL into column 'Address1', table 'C:\USERS\xxxx\PROJ (2)\PROJ\APP_DATA\ORDERS.MDF.dbo.Customer'; column does not allow nulls. UPDATE fails.
The statement has been terminated.]
Something simple I'm missing? Was considering the option of creating text boxes instead and connecting to the database individually, but that's a completely different route to this and there is quite nice, simple customizable options with the DetailsView.
Well...typical after spending weeks confused by this one I managed to get it just after posting the question.
For anyone interested in this I used the 'If e.Exception Is Nothing Then' statement within the code similar to the two bottom examples I tried, THEN, used a Try/Catch statement.
Just now getting into the asp.net environment with VB 2010. I have designed an intranet page that we will be using to auction off old equipment to employees. I've had some very good luck getting the whole thing working, but I have hit a snag on one minor issue: I would like to keep a database table of user logins and times.
Several methods have presented themselves, but so far none of them have been adequate. The main problem seems to be that regardless of the event I use to record the login, they fire multiple times resulting in as many as 4 or 5 entries in the login database for the same login event, not to mention additional times when something on the page changes for whatever reason.
The system uses Windows Authentication, so the user must login with his/her company credentials.
I can't remember what all I have tried, but the first thing I tried was the Page_Load event because it seemed obvious. I've learned that because the page updates the display every ten seconds, Page_Load event fires numerous times throughout the session.
Fighting my way through other ideas, all of which failed, I came to the WindowsAuthentication_OnAuthenticate event in the Global_asax class, shown below:
Imports System.Web.SessionState
Imports System.Data.SqlClient
Imports System.Web
Imports System.Web.UI.WebControls
--------------------------------------------
Public Sub WindowsAuthentication_OnAuthenticate(ByVal sender As Object, ByVal args As WindowsAuthenticationEventArgs)
Dim strLoginName = args.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End Sub
which also seems to fire multiple times. I then tried to work a way where setting a Boolean value to TRUE upon authentication so that the data would be written to the database only once:
Public Sub WindowsAuthentication_OnAuthenticate(ByVal sender As Object, ByVal args As WindowsAuthenticationEventArgs)
If Not boolUserIsLoggedIn Then
boolUserIsLoggedIn = True
Dim strLoginName = args.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End If
End Sub
and subsequent authentication iterations would skip the database write code; but then I needed to find a way to clear the Boolean value when the user logged off or closed the session. I couldn't figure out how to trap a "Logged Off" event, and the Session_End and Application_End events didn't work as I had hoped.
I feel like this is getting too convoluted to make sense. To put it simply, I just need a way to record a user's login name and date only once per session. Can anyone help?
[Edit: Although this is not really an essential element of the page, it has become a crusade for me to get it to work if not for any other reason than to understand the process.]
Researching more about JDB's suggestion using the session ID property, I discovered another property that seems to be doing exactly what I need: The IsNewSession property.
With that in mind, I have this code in my default.aspx's Page_Load event:
If Context.Session.IsNewSession Then
Login()
End If
Which calls the Login sub that writes the login information to the database:
Protected Sub Login()
Dim strConnectionString As String = "Data Source = toponet\sqlexpress; initial catalog = TopoAuction; Integrated security = True"
Dim strLoginName = System.Web.HttpContext.Current.User.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End Sub
So far, testing has shown that it fires only once per session. Even if the browser moves to another site and comes back, it will not count that as a new session. This seems to be the perfect solution.
I'm open to hear any comments or concerns about this, anybody?
I think, perhaps, you are getting hung up on the request/response cycle of a web page. If you have only ever used WebForms and come from a desktop development background, the statelessness of the HTTP protocol can be very confusing.
Essentially, the client (the browser) requests information from the server (where your .NET code is running). Each request is completely independent from every other request - the server maintains no memory of prior requests.
Now, WebForms was an attempt to bridge the gap by shoe-horning on a sort of pseduo-statefullness on top of HTTP. This is where ViewState and other similar concepts come in. Basically, WebForms includes additional information about the state of the web application in each Response, which is then included again in following Requests, maintaining the application's state and giving the appearance of statefulness. There are other tricks too, like server variables, which can be used to maintain some "memory" of past transactions.
However, this statefulness is easily broken. For example, if you include a basic anchor tag (not an ASP.NET server control), and you redirect to another page (or even the same page) without including the view state, then you will lose some of your application state. Even if you are using server controls and maintaining your view state, you must pay careful attention to the WebForms Page lifecycle. If you are handling the wrong event (such as Page_Load) or attempting to access a property at the wrong time (before the web page has had a chance to reload it's state), you may not get the results you are expecting.
In this scenario, I recommend you check the user's Session ID. It changes very infrequently. If you have a user ID coming in with a session ID you've not seen before (or that's not been associated with that user in some amount of time - say 30 minutes), then you probably have a unique logon event. If you have seen that user ID/Session ID combo, then that user has probably already "logged in" and you don't need to record it again.
Alternatively, just store the user's login state in a session variable. You can check that variable on each Page_Load and branch (using an If statement) based on your needs.