Property in viewstate different on one page to another - asp.net

This is really weird error i'm getting and i'll try and explain as best I can.
I have two pages - Page 1 (form) and Page 2 (completed page)
From page 1 I put a variable into a database and then do a server.transfer to page two like so...
Server.Transfer("Page2.aspx", True)
On page 2 I then grab the variable called paymentOnHold which is set on Page 1 and goes into the database...
Here is how I set paymentOnHold on Page 1
Public Property paymentOnHold() As String
Get
Dim _paymentOnHold As Object = ViewState("paymentOnHold")
If _paymentOnHold IsNot Nothing Then
Return CType(_paymentOnHold, String)
Else
Return Nothing
End If
End Get
Set(ByVal value As String)
If Not String.IsNullOrEmpty(value) Then
ViewState("paymentOnHold") = value
Else
ViewState("paymentOnHold") = Nothing
End If
End Set
End Property
...
paymentOnHold = Date.Now.ToString("yyyyMMddHHmmss")
Here's how I grab the value on Page 2...
Dim myValue As String
If TypeOf PreviousPage Is Page1 Then
myValue = DirectCast(PreviousPage, Page1).paymentOnHold
End If
In my development environment where the databases are local the value in the DB and the value on page 2 both match - as you would expect...
In live environment the DB value is 3 or 4 seconds different (before) the one on Page 2 - even though I do not reset it or anything?
This has been driving me crazy for the last few hours and cannot work it.
Does anyone have any ideas/suggestions as to what might be causing this?
Thanks in advance

This could be an issue of saving the view state in first Page (form-1)
In asp.net Page lifecycle
1. Initalization (controls raise their Init event)
2. Load ViewState (Only on post back)
3. Load PostbackData
4. Load
5. Raise PostbackEvent
6. Save View State
7. Render
Server.Transfer() stops rendering the current page and starts rendering another one.That's why Server.Transfer() cannot be used to redirect to pages served by another server.
If you are doing Server.transfer before Event--> 6. Save View State you are not saving viewstate on the form-1
Solution
Response.redirect and session cache, as it is intended to exist per user and across multiple pages in the application.

Using ViewState in this manner is a brittle solution, because ViewState is not intended to exist outside of the scope of the page it was initiated in, much less passed between pages, which I realize you are not quite doing, but you are getting dangerously close to doing it.
The better approach is to use Session cache, as it was intended to exist per user and span multiple page requests.
Try this:
To store in Session, do this:
Session("PaymentOnHold") = [Date].Now.ToString("yyyyMMddHHmmss")
To retrieve a value from Session, do this:
' First check to see if the value is in Session cache or not
If Session("PaymentOnHold") IsNot Nothing Then
' Everything in Session cache is stored as an object so you need to cast it to get it out
Dim datePaymentOnHold As DateTime = TryCast(Session("PaymentOnHold"), DateTime)
End If
Now the Session value will be available no matter how you navigate to pages (Server.Transfer or Response.Redirect).

Related

Loosing session variable data from one page to the other in VB.NET

I am a bit new to VB.NET. I have a page that sets 2 session variables and does a redirect to second page. The second pages is at least using one of the session variables. I can tell because on the second page, if the session variable is not correct the user is redirected to an access denied page. The second page also uses the session variable in question. It will read it an fill a gridview based on the value of the variable. I set the variable like so
Session("ID") = Convert.ToInt32(a_value)
and on the second page I retrieve the variable like this
a_page_variable = Session("ID")
What I find strange is that when I run this code in visual studio it works as expected but when I deploy and run it, I get 0 from my session variable instead of the true value of "a_value". I have tried a few things like making sure the data types match up from page to page and trying different ways to retrieve the variable such as
Session("userID")
and
CType(Session.Item("userID"), Int32)
I've also tried to see what is coming in to the second page by using
Response.Write
I also tried to use SQL Profiler to see what kind of call is being made to fill the gridview but I haven't had any luck. The gridview gives me an empty dataset and the Profiler does not detect a call being made from the application. I thought working with session variables was pretty straight forward but obviously, I am missing something.
Thanks for your help,
Billy
One possibility (and the only one that could be guessed at with how little information we have) could be the response.redirect causing the application to terminate due to an exception.
When redirecting, you want to always pass a false, and then call complete request.
Response.Redirect(urlstring, False)
Response.CompleteRequest()
not following these steps can cause exceptions, which may drop session.
Additionally, resolve virtual paths, as some browsers (mobile especially) can see those redirects as new requests entirely, thus generating new session tokens.
Dim urlstring As String
urlstring = Page.ResolveUrl("~/default.aspx")
that said, there are a number of possible causes for this situation.
Application Pool restarts
App Domain restarted
Code changing value unexpectedly
AV tinkering with files
deployed to web farm
With the description provided above, we just don't have enough information to really troubleshoot.
Thank you ADyson, Stephen Wrighton and everyone else who took a stab at helping me figure this out. I was able to find out what was going on by adding code that wrote to a log file on the server. Found the logging code here. I found that I never reached the code that set the session variable and that is the reason it never populated on the second page. I was trying to get the logon name for the user by using Environment.UserName which will return the user name of the person who is currently logged on to the operating system. But what I really wanted to do was get the logon name of the user that was visiting my site. For this I used User.Identity.Name. This works great when you need to know which user from an Active Directory domain is visiting your site.

Execute VB Script on page_load

I am having VB Script in ASPX page.I need to use that Script in codeBehind in Page _load with in a For loop,for each iteration.
My Code is :-
(.ASPX Page with VB Script. )
<script type="text/vbscript" language="vbscript" >
sub wordit()
'Opens Word application and does some process
end sub
</script>
VB Code Behind Part:-
For i As Integer = 1 To colSelRowIndex
CheckboxTemplateId = colSelRowKeys(i).ToString 'I get the ID from here
ViewState("TemplateID") = CheckboxTemplateId 'I need to send the value to the sub routines
hen()'sub
den()'sub
cs.RegisterStartupScript(cstype, csname1 & i, "wordit();", True)
Next
I need to open a word doc for an ID and another document for another ID from the loop.
Try this:
For i As Integer = 1 To 10
cs.RegisterStartupScript(cstype, csname1 & i, "wordit();", True)
Next
That second argument in that function call is looking for a unique key. This is a feature, to prevent accidentally programmatically adding the same script more than once. If you want to do it on purpose, you need a unique key each time.
But that you want to do this at all indicates a possible fundamental misunderstanding about what's going on. While your server code (including Page_Load) is running, your client page in the web browser doesn't exist. The purpose of the server code is always to generate an html response to web request. The server code can never directly manipulate a page DOM.
Obviously this is true for a first request to a page in session: the server must first generate the initial page to send the client. But even on subsequent postbacks, the browser will destroy the prior instance of a page. The server must rebuild the entire page from scratch. Every. Time. While this happens, the page you're looking at in your browser window is only a sort of after-image. The browser has already destroyed any prior DOM, and is waiting for the server to supply a whole new set of HTML.
I also wonder at your use of vbscript, rather than javascript. Using vbscript pretty much guarantees you're page will only work with Internet Explorer.

Custom cache not caching querystring

I'm using custom cache on a page, leaving a timestamp to follow cached versions.
I have
<%# OutputCache Duration="1200" VaryByParam="None" VaryByCustom="myCache" Location="ServerAndClient" %>
on the page, and the code-behind of Global.asax has (simplified)
Public Overrides Function GetVaryByCustomString(context As HttpContext, arg As String) As String
If (arg = "myCache") Then
If context.Request.QueryString("Type").ToString() = "1" Then Return "cache-1"
If context.Request.QueryString("Type").ToString() = "2" Then Return "cache-2"
If context.Request.Cookies("Type").Value = "1" Then Return "cache-1"
Return "cache-2"
End If
cache-2 is default state for when no querystring request has been made and cookie doesn't say otherwise. The page saves the cookie with value of Type.
When I call the page with either ?Type=1 or ?Type=2 the page isn't saved to cache - each refresh the timestamp changes.
I found that if I call the page without the Type parameter cache is saved and then exists when I call the page with the parameter as well.
Is there an explanation? Moreover - in Global.asax I couldn't access Response object or file system to log what's happening. Is there a way?
UPDATE
e.g. calling <url>?Type=1, then <url> gives me cache for next calls of <url>?Type=1, but gives same cache for <url>?Type=2.
UPDATE
I now have Return "cache" & context.Request.QueryString("Type"). While sending a request without Type in the querystring gives a cached version of the page, sending Type does not cache, though the result (cache1 or cache2) is the same and page should get cached.
follow up
I've found sending Type=3, or anything besides 1 and 2 does cache the page as desired. Page_Load acts upon values 1 & 2 - could there be any connection?
Answers to this question seem to explain a lot. Workaround is a separate question.

ASP.NET ScriptManager History url hash lost after redirect

I have seen several posts online complaining that Firefox maintains the history url hash after redirecting.. That is the behavior I am hoping for - and it happens in Firefox (11.0), Chrome (18.0), and Opera (11.61), but not IE (9) or Safari (5.1.2).
On my page, I have ASP.NET 4.0 history points set up and working (has been working for a couple years). I also pass a few querystring params to the page. What I am trying to do now is check the value of a new querystring param, and if it does not match what I am expecting, redirect to the same page with an updated value. I am using this mechanism to track the session of individual tabs of a browser so that when they have the same page open in multiple tabs, the session values dont step on each other from tab to tab.
Anyway, I have everything working correctly including the back/forward using ASP.NET History points - and when I visit a bookmark and the querystring param does not match, I redirect and change the querystring param to track the session, and the history state that is in the url of the bookmark is then used to reload the page to the state I want. But that only works in Firefox, Chrome, and Opera. Not IE which is the big one for me (based solely on our user base), and not Safari.
I have identified that in addition to (or perhaps because of) the fact that the url history state is not present, ScriptManager.Navigate is not called after the redirect in IE or Safari.
Is there a setting/option that I can set on the ScriptManager or during the redirect to maintain the History state in the url? If the history state was in the url, I could call ScriptManager.Navigate directly if I needed to, but the values are not present in the url.
If it helps at all, here's a listing of where I do the check and redirect. The ReportRunID is then appended to the session variable keys that need to be unique to each tab. I keep a listing of previous ReportRunIDs to keep track and to clean them out (after a certain time period, or when more than [MAX] ids are encountered) so that I dont overload server memory with these session entries.
Private Sub Page_PreInit(sender As Object, e As System.EventArgs) Handles Me.PreInit
If IsPostBack = False Then
Dim rrid As String = Request.QueryString("RRID")
If ReportRunIDExists(rrid) = False Then
ReportRunID = Now.ToString("_HHmmssfff")
Dim url As String = Request.Url.PathAndQuery
If String.IsNullOrEmpty(rrid) Then
Response.Redirect(String.Format("{0}&RRID={1}", url, _reportRunID))
Else
Dim idx As Integer = url.IndexOf("&RRID=")
Response.Redirect(String.Format("{0}&RRID={1}{2}", url.Substring(0, idx), _reportRunID, url.Substring(idx + 6 + rrid.Length)))
End If
End If
End If
End Sub
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
'save current RRID/Page/Time to session
UpdateSessionReportRunID(_reportRunID)
End Sub
...
If my bookmarked url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_095224678#&&state1=abc&state2=def...
In FF/Chrome/Opera after the redirect, my url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_102176253#&&state1=abc&state2=def...
But in IE/Safari after redirect, my url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_102176253
Any ideas?
After much more searching, I have come to the realization that History State hash is not sent to the server. It is stored in the querystring so that it is included in bookmarks, but it is accessed by the client-side scriptmanager which causes a postback to load the state values. Since the Server never sees the hash value in the querystring, I have no way of finding those values when a user follows a bookmark to that page.
This problem was introduced as I was trying to start tracking the session state of different browser tabs individually. In my code above, if the RRID parameter is empty or invalid, I have to redirect to self with a new RRID value. When I do that redirect the History State hash was being lost for IE and Safari (but not for the other browsers).
My workaround:
The problem is that I needed to include the hash value in my redirect, but that is not available from the server, so I decided to inject some javascript to the page to perform the redirect from the client where the hash is available.
I already had a Client Redirect extension helper method that I have used in different scenarios, and I modified it to include the current hash value:
<System.Runtime.CompilerServices.Extension()>
Public Sub ClientRedirect(ByVal Response As HttpResponse, ByVal url As String, Optional ByVal target As Target = Nothing, Optional ByVal windowFeatures As String = Nothing, Optional includeCurrentHash As Boolean = False)
If IsNothing(target) Then
If windowFeatures = String.Empty Then
target = ResponseHelper.Target._self
Else
target = ResponseHelper.Target._blank
End If
End If
Dim page As Page = CType(HttpContext.Current.Handler, Page)
url = page.ResolveClientUrl(url)
Dim script As String
script = "window.open(""{0}"", ""{1}"", ""{2}"");"
script = String.Format(script, url & If(includeCurrentHash, "#"" + window.location.hash + """, String.Empty), target.ToString, windowFeatures)
If target = ResponseHelper.Target._self Then
'execute after page has loaded
page.ClientScript.RegisterStartupScript(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
Else
'execute as page is loading
page.ClientScript.RegisterClientScriptBlock(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
End If
End Sub
Then in my Page_PreInit where I do the redirects, I changed that to do the ClientRedirect including the current hash, and that has gotten the desired result:
Redirecting the browser while maintaining the History State hash on all browsers.
'redirect from the client so that we keep the History State URL hash
Response.ClientRedirect(String.Format("{0}&RRID={1}", Request.Url.PathAndQuery, _reportRunID), , , True)

Share Session between Page in Page to Page Request

My application is simple, I have 2 pages:
RSSProducer.aspx: A page that generates RSS (XML) feeds
RssConsumer.aspx: A page that retrieves the RSS feeds and displays it to the user in a repeater control. To do this I am using the System.Xml.XmlTextReader to fill a DataSet with tables based on the RSS-XML retrieved from the RSSProducePage. A table within the DataSet is bound to the repeater control.
For example, this is what I have in my RssConsumer.aspx page:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Session("permittedToViewSomeDetail") = True
Dim url = "http://localhost/DevSite/RSSProducer.aspx"
Dim reader As New System.Xml.XmlTextReader(url)
Dim ds As New DataSet()
ds.ReadXml(reader)
myRssRepeater.DataSource = ds.Tables(2)
myRssRepeater.DataBind()
End Sub
My problem is that user-authorization details are stored in Session in the RssConsumer page that need to be accessed in the RSSProducer page (in this example it would be Session("permittedToViewSomeDetail") that I need to access in the RSSProducer page); however, the Session identifier is not common between the two. This means that I cannot access the authorization details in the RSSProducer page.
The reason for why is fairly clear to me:
User's browser makes a request to
the RssConsumer page
Server generates a Session ID (which is stored in a cookie) if
there is no existing Session
Identifer
The RSSConsumer requests the RSSProducer page...which generates a
new Session ID every time because no
session identifier is ever going to
be found.
I tried using cookieless session so that I could pass the SessionID via the URL to the RSSProducer page as an experiment but for some reason the XmlTextReader doesn't work well with this method (but the desired shared session does work).
I've hit a brick wall here.
Does anyone know how to share session between pages when one page makes a request to the other?
Thanks,
-Frinny
I ended up taking a different approach to solving this problem. I moved the code out of the RssProducer.aspx page into the RssConsumer.aspx page. I am now able to apply the correct authorization to the feature and it's actually more efficient this way because I don't need to produce/consume RSS-XML any more.
Thanks to everyone who took the time to help me with this.
-Frinny

Resources