admin管理员组

文章数量:1122832

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?

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?

Share Improve this question edited Nov 26, 2024 at 22:04 jp2code asked Nov 21, 2024 at 21:15 jp2codejp2code 1851 silver badge10 bronze badges 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". – Andrew Morton 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(); – jp2code 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. – Andrew Morton 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. – jp2code 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. – Richard Deeming Commented Nov 22, 2024 at 9:10
 |  Show 4 more comments

1 Answer 1

Reset to default 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:

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

YOU DO NOT have this:

And you do NOT even have this:

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 careful 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.

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

This:

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

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 occuring.

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. It's 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:

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).

本文标签: vbnetRefresh ASPNET page from another ASPNET page in Code BehindStack Overflow