0

We have an ASP.NET WebForms site.

Page 1 (Main) has a form with several fields.

A menu option on Page 1 (Main) opens a login dialog called Page 2 (Login).

Once Page 2 (Login) authenticates, it stays open and launches a third dialog called Page 3 (Grid) with a GridView of tickets owned by the person.

Values selected on Page 3 (Grid) need to update the form on Page 1 (Main) while Page 3 is still open. This is to allow the person to see if they have selected the correct row.

On Page 1 (Main), I have created delegates and the static/shared method RefreshDataGrid(csrWhere As String):

Private Shared _me As frmMain

Delegate Sub RefreshDelegate(sender As Object, e As EventArgs)
Delegate Sub SelectWhereDelegate(item As String, number As Int32)

Private _selectWhere As SelectWhereDelegate
Private _refresh As RefreshDelegate

Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
    _me = Me
    _selectWhere = AddressOf SelectWhere
    _refresh = AddressOf Refresh
    _loadClaims = AddressOf LoadClaims
End Sub

Public Shared Sub RefreshDataGrid(csrWhere As String)
    If _me IsNot Nothing Then
        _me._selectWhere.Invoke(csrWhere, 0)
        _me._refresh.Invoke(_me, EventArgs.Empty)
    End If
End Sub

Private Sub SelectWhere(ByVal cWhere As String, ByVal nSortBy As Int16)
    ' databinds with the database, fills textboxes
End Sub

Private Sub Refresh(sender As Object, e As EventArgs)
    _me.Context.Server.Transfer("frm2000.aspx")
    HttpContext.Current.Server.Transfer("frm2000.aspx")
    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString(), True)
End Sub

On Page 3 (Grid), I call the static/shared method from Page 1 (Main):

Private Sub gridView_Click(sender As System.Object, e As EventArgs) Handles cmdGo.Click
    If dgInvoice.SelectedIndex > -1 Then
        Dim csrWhere As String = String.Format("WHERE ClaimKey = '{0}'", dgInvoice.Items(dgInvoice.SelectedIndex).Cells(15).Text)
        frmMain.RefreshDataGrid(csrWhere)
    End If
End Sub

When RefreshDataGrid is called on Page 1 (Main), it correctly calls SelectWhere: It reads the data and populates the textbox fields as I step through the code.

However, the form Page 1 (Main) does not refresh until I trigger something that fires runat="server", like switching to a different tab or selecting something on a DropDownList.

Currently, I am trying to find out how to refresh the page using a second delegate RefreshDelegate to call the private method Refresh(sender As Object, e As EventArgs), but so far everything I try has failed.

  • _me.Context.Server.Transfer("frm2000.aspx"):

System.Web.HttpException: 'Error executing child request for frmMain.aspx.'
Inner Exception
NullReferenceException: Object reference not set to an instance of an object.

  • HttpContext.Current.Server.Transfer("frmMain.aspx"):

No error here, but this loads frmMain.aspx in my Page 3 (Grid) window, which is not what I want.

  • HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString(), True):

This one results in my session being expired, requiring me to log back in.

Is there any way to call this static/shared method from Page 3 (Grid) so that Page 1 (Main) refreshes?

screenshot

9
  • Why does "Page 2" need to stay open? You could get the user to log in and then the session would be logged in and the appropriate information could be shown on "Page 1", including the "GridView of tickets owned by the person". Commented Nov 21, 2024 at 21:34
  • @AndrewMorton - that's the way their whole enterprise website was written. To change it means that lots of changes have to be made to the whole project, and that has not been authorized. The reason I included it here is so you know that I can not call javascript's document.opener.reload(); Commented Nov 21, 2024 at 22:07
  • To add to the project resources problems, please note that there is an SQL injection vulnerability in concatenating a value in csrWhere. Instead, you could pass the string and an array of SQL parameters. Commented Nov 21, 2024 at 22:23
  • @AndrewMorton, but how do I get the Main page to refresh and show those results? That is the issue I am having now, and why I posted this. Commented Nov 21, 2024 at 22:52
  • In ASP.NET, Shared is (almost) always the wrong thing to use. And as Albert pointed out, the site doesn't work in the way you seem to think it does. You'll need a client-side solution so that JavaScript on one page can notify JavaScript on the other page to reload the data. If you can't use the window.parent or window.opener properties, maybe try a BroadcastChannel. Commented Nov 22, 2024 at 9:10

1 Answer 1

2

You are forgetting the page life cycle here.

Remember, when a page is rendered and sent to the client side on the server side, the code behind, the page class, the values, the memory, the variables are all 100% disposed of, and go out of scope!

When a page is sent to the client, the server does NOT keep a copy of the page, a copy of the code, a copy of the values in memory. As a result, any attempts to reference a page code class will fail.

So, the page life cycle (a round trip) looks like this:

You have this:

enter image description here

Note how your page class - code behind is NOT in memory on the server.

YOU DO NOT have this:

enter image description here

And you do NOT even have this:

enter image description here

Remember, this is not like desktop software. The server is ONE server for everyone, and it is the job of the web server (IIS) to process ONE posted page, and ONE paged posted by "any user" and not just you.

The server does NOT keep a copy of the page code behind in memory. The copy of the page class (code behind) ONLY exists in memory for a short period of time - and ONLY during the post back cycle when the code behind runs. Once the code behind is done, and the page is sent back to the client side, then on the server side, the code behind and page class is 100% disposed of, and tossed out of memory. Remember, the web server can only process one page at a time, and it is not "allocated" for just one user!

Note very carefully here - the web page is now ON the CLIENT computer, and that page class (code behind) now does not exist on the server side anymore.

When you click on a button, or do a post-back, then you get the start of the round trip.

This:

enter image description here

Our web page is sent up to the server. You now have this:

enter image description here

NOW an instance of the page class is created, and your code behind starts running. And hence previous variable values also start from scratch and as new.

Your code behind can modify controls (even controls to be visible or not), but the page is NOT interacting with the user - ONLY code can MODIFY the "copy of" the web page (user does not see one change, or many changes made by code at this point in time).

One change, or MANY changes to the web page can occur, but AS YOU update things like a text box etc., the user does NOT see these changes just yet. So, if you run a loop 1 to 10, and update a text box, the text box will be updated 1 to 10. However, the end user sees nothing, since that web page (and code) is running up on the server (and server is making changes to that copy of the web page). The user just sees the browser "wait" icon while this process is occurring.

Changes to web page are occurring on the server - the client-side browser does not have the web page any more!

Once ALL of your code is done running, then and ONLY then does the page make the trip back to the client-side browser.

The server-side class instance and code (and variables) are then TOSSED OUT - DOES NOT exist! Your server-side page class is disposed - removed from memory, and the web page code behind does NOT exist any more in memory.

So, the whole new modified web page travels back to the client side, is re-displayed, JavaScript is loaded, and THEN JavaScript starts running. So even the client-side page now 100% re-loads.

So, if you open 2 pages, or 5 pages (in different browser tabs, or even separate browsers), then each of these pages are static pages JUST sitting on the user's desktop. The server does not keep a copy of the 5 pages, nor does the code behind EVEN exist in memory. After all, the user might now start shopping on Amazon with that one tab, right? or the user might close the browser - the server has no idea this will have occurred, or even if the web page is still open.

You can think of this like calling a subroutine. Once the subroutine exits, then all of the variables and code for that subroutine now goes out of scope. You can think of each web page as the same idea. Each web page code behind ONLY exists during the short time the post-back cycle runs, and ONLY during the VERY short time the code behind is running. Once the code behind is finished (hopefully modifying controls on the page), then the WHOLE page is sent back to the client side, and on the server side, that code, that page class, the variables are all 100% disposed of. A web server is in effect a message processor, and it processes one web page at a time. It does not hold in memory each user's browser tabs open. The web server has to dish out web pages for many users, but it is only one computer!

This concept in web land is called "state-less" programming. And you don't have a bunch of code and separate memory for each user like you do with desktop software. In desktop land, EACH user has their own computer. In web land, you have ONE server "page" processing system called IIS. Its job is to process a posted page, and when it returns the processed page, it is now ready to process a new posted back page - a page that can be posted by ANY user, not just the one user.

You don't have multiple copies of the code behind in memory. The code behind and page class ONLY exists for the VERY short time during the "round trip" or so-called page life cycle.

Hence, your sample code that attempts to reference other page class and code? It will never work, since IIS does not hold such code or the variables in memory. It ONLY works with ONE page at a time.

So, study the above pictures and with an understanding of the page lifecycle, you will see how any code design that attempts to reference other pages simply cannot work as your code is currently designed.

You can't call page code from another page. And in many ways, if you could do this, then my code would look for and try to use a web page you have open called "my banking".

Hence, keep in mind that once a page is sent to the client side, then on the server side that page code, the page class, the variables etc. don't exist server side anymore. The web server is to be thought of a "page post processing" system, and it really only can process one page at a time.

On each page post-back, you note the values (variables) in code start from scratch each time, and as noted, the code behind page class and values only exists for a very short time - the short time being the time that the page is up on the server being processed. Once the page is processed and sent back to the client side, then the server dumps, and 100% disposes of the code behind from memory, and the web server is now ready and waiting to process any page from any user. Remember, you have ONE web server, and it can and will be processing pages from all users - not just you the one user.

Do read the above, and once you grasp the concept of "state less" programming, you see how any code design in which you attempt to reference or use another page class will not work, since they don't exist or remain in memory. About the only exception to the rule is when using a master and child page. In that case, during the short round trip, then both page classes exist in memory, but once again, the instant the code completes and sends the master + child page to the client side, then once again, the page code class goes out of scope and does not exist in memory anymore.

As a result of the above, then no concept or designs that attempt to reference other page code classes can work, since such code is no longer in memory (in scope) once such pages have been rendered. So, a desktop design approach as you have here will simply not work.

So, after code behind, then page travels back to the client side, is re-displayed, JavaScript is loaded, and THEN JavaScript starts running. So even the client side page now 100% re-loads.

Hence this:

enter image description here

Note again, the code on the server side has now been removed, dumped, and 100% disposed of. The code behind (page class) does not exist in memory once that page travels back to the client side).

Sign up to request clarification or add additional context in comments.

8 Comments

OK, I think I understand why my refresh techniques are not working. How would I accomplish this task of refreshing Main from Page 3? Main has a Databind method that pulls the data. I can call it, but the static page will not refresh. Everything I've tried that involves window.location.reload also ends the user's session.
I assume that the 3 pages you had worked previous with the older version of IE web browser. Thus, it kind of makes sense to figure out what/why the older site worked, and now the new site does not. In other words, in place of say replacing the engine on the car that not working, maybe it's just a simple battery fix/replacement? As noted, you can't really reference other page class(s) code with your current design. The 1st page can thus call a web method without a post back - that's probably the best choice here.
On the other hand, , but before one starts adding all these moving parts, polling and things like session? I would figure out why or what causing IE to work, but not Edge, as that's much less work. In other words, the original design as you noted worked, but not with Chrome or Edge - I would find out why. And I don't grasp why all these windows are being opened - trying to do this on a phone, or even a tablet going to be rather difficult, but regardless, I would find out why and how this worked originally, and fix the browser issues to work with later browsers - not try some new fangled code.
One employee claims it worked at one point, but the code in source control has not been touched since before she started. I edited my post to include a screenshot. I didn't design this. lol You can see the security screen that has to remain open for the invoices to show. Selecting a Claim and pressing the Go button should load it in the parent window while invoices remains open. The original code had RegisterStartupScript("<script type='text/javascript'>opener.location.reload();</script>, but it does not work. Maybe it used to. (???)
Hum, ok, that logon screen looks a bit strange - I wonder if it is a windows auth screen as opposed to web based authentication (and what authentication provider are you using? (best guess would be FBA (forms based authentication). And that "list" of choices? My spider sense suggests that checking items in the list, and then the "ok"/"go" button did/does a database update, and that's how the first page knows/gets the update (would have to see the code - but that's a guess on my part). So, one might want to look at what the "go" button does on that 3rd page - I thinking it does some db update
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.