Why does Page_Load get fired when clicking on a button? - c#

I have something like
protected void Page_Load(object sender, EventArgs e){
country.Text = "USA";
}
protected void Button_Click(object sender, EventArgs e){
Console.Write(country.Text);
}
and when the user clicks on the button, it always prints "USA", even if they wrote something else in the country TextBox, it means that Page_Load() gets fired each time a button (or any other event, I guess) is clicked.
I know how to fix this, by looking at this question, but why does that happen?

The web page is sitting on the client side web browser. When you click a button, the whole page is sent up to the server. Now you code behind can not only run, but modify controls, and does whatever you want. Once all that code is run, then the browser page is sent back down to the client.
I have often suggested that a FirstPage load event would have helped mountains here. However, over time, I think the page load having to fire each time is fine, and that the setup actually helps and promotes the fact that it runs every time. However, in desktop development - from VB6, .net, heck even delphi and C++ desktop forms? The page load even ONLY ever fires one time. So yes, it is surprise to many that web forms don't work this way. The bottom line is that page load fires every time, and the simple matter is a WHOLE NEW fresh page is sent up to the sever EVERY TIME. So, while there could have been two events, often quite a bit of page load code has to run in both cases. So then having two seperate events would cause just as much trouble.
So for code that runs first time (such as setting up the text box value)? Well, if you need that code to run each time (and you might!!!), then you place it outside of the if/then block that checks for the IsPostback. So for code to setup things such as defaults - yes, you need that code inside your IsPostBack = false block.
Web pages are what we call state-less. They are sitting on the users desktop. There is NO LIVE connection to the server. The user can close that web browser or turn off their computer. And when the user closes the browser - no information or talking is sent to the server. So you can have 2 or 2000 users typeing or editing in their brwoser - the web server does not care, see or even know that users are doing things. And the web server considers them NOT CONNECTED. They are just a web page - that page can be closed - the server does not even know the user closed the web site (there is no web page close event like desktop software). So the whole design of web pages are sate-less - and disconnneced. The web server does not know if that web page is still open, being used, or been closed. The ONLY time the web server can do ANYTHING is if you send the page back up to the server. At that point EVERYTHING in that web page starts over from scratch every post back (hence the term state-less). However, thankfully things like a text box have what is called a "view state" and they DO survive those round trips. If a control does not have a view state, then they also would lose their values on each post back. One VERY nice feature of webforms is most controls have the ability to keep their viewstate (that just means the value(s) of such controls can survive a round trip.
So when you click a button, then a whole page postback has to occur, since any code running behind would not be able to look at/ see / change the value of controls on the form. In fact, we often seen someone say run a ajax web method (in the same page) and then wonder why their code behind (in that web method) can't change controls. In fact you can write code to change controls, but it only changing the server side copy, and the copy sitting on the user's desktop is not changed. In fact, when they do (eventually) a post back, anything the code behind changed is lost.
So when you click on a button, the page load event will run FIRST and then your button code. This is how it works.
So 99% of the time, when I start typing and writing code in page load?
You do this: (say to load up a datagrid with a data table).
if IsPostBack = False then
GridView1.Datasource = myrst("SELECT * from tblhotels")
GridView1.Databind()
End if
So, you have to "assume" and "write" code that means the page load event fires every time. However, in above, we only want the first time setup code (to load up a gridview) to run one time - the first time the page loads. So now, you might have 5-6 buttons on the page, and the above code in the page load will not run since we check/test if this is a post back.
So the whole web page has to travel up to the server, else your code behind can't modify any controls or values on the web page. Once that code runs, then the page travels back down to the client side and is again just sitting on the users desktop. So clicking a button HAS to send the whole web page back to the server, else the values of controls on the web page could not be modified, and worse the results of that code would never be displayed back in the browser. So code behind can't JUST modify one control. it needs a whole copy fo the web page first, and then you can change a control (or several) and then the whole page makes the trip back to the browser. So you can't write code to JUST change one control without first having a WHOLE copy of the web page with everything. However, you can use what is called a update panel. This will allow you to run code that updates JUST part of the page. However, even in that case, the page post back event does run first - this is often called a partial page post back. So you can drop in a update panel, and have buttons and code in that update panel - they can only modify things inside of that update panel, but you note that the whole page does not replot or re-fresh. You can also hand code JavaScript ajax calls, and they can client side modify some controls (and even call routines server side). But you still have to assume that code behind can NOT see + use those controls until such time the web page travels up to the server. This applies even when using a up-date panel (the code behind can only modify controls in the update panel). Update panels are very nice in that you don't have to wire up and hand code a whole bunch of ajax and JavaScript to allow partial updates of the web page and not have to cause a full page post back. But as noted, even when using a up-date panel, the page load event does fire. So for the most part, you in general write the page load and setup code inside of that postback=false code block.

This is what the ASP.Net Button class tells us about the Button class:
By default, a Button control is a Submit button. A Submit button does
not have a command name (specified by the CommandName property)
associated with the button and simply posts the Web page back to the
server.You can provide an event handler for the Click event to
programmatically control the actions performed when the Submit button
is clicked.

Related

Lifecycle .NET ASPX page on postback

Apologies if this is vague or too general, I know we are supposed to ask specific programming questions, but this is to try and understand how postbacks work in ASP.NET when something is rendered on page initially, and not touched on postback, yet still appears on screen after these postbacks.
Detail: I have an ASPX page - on initial page load it sets up all the labels and controls and a repeater with thumbnails in it.
I can follow the code through as it sets up all components, which will then be rendered.
On postback, if a value has been changes (status for example), the page makes updates to database, and then re initializes the screen (calls the init method with postback set to false), setting up everything again (I think the aim was to set up certain controls like radio buttons for the status), including the image repeater again (which I think is a waste of time).
I have tested skipping the code that sets up the image repeater etc. on a status update (postback), and the image repeater displays fine in the browser - however I am not sure why - ASP.NET is stateless, so on a postback, if the page does not render all the components on the page everytime how can they persist between postbacks?
I know there is a reason out there, just can't frame my question well enough in google to find it. Does the server send back and update which the browser merges with the existing displayed page? Leaving all unchanges components as is?
The reason I need to know this, is I have a screen with a lot of images on it, and I do not want to be setting them every time unless I have to.
This link - provided by Steve (thank you very much) - was what I was looking for goes into depth on ViewState - vaguely remember reading about that when I first stated doing .NET - have completely forgotten about it, but this explains it perfectly!
Understanding ASP.NET ViewState
https://msdn.microsoft.com/en-us/library/ms972976.aspx

Can you force a Page Render after it's loaded

Problem:
I am loading one of several user controls based on a selected tab within RadTabstrip Control which is on the parent page. I've captured the Selected Tab and assigned it to a Session variable within the OnTabClick event to use in each User Control to determine if that particular control needs to be rendered.
The reason for this is because each User Control queries a database to render different charts and I don't want unneccesary processing occuring on every post back to the server. I'd like to add that each User Control has several Labels in their Markup that only gets the Text values assigned during runtime based on the content retrieved from the database.
When I load the main page, the selected tab variable is checked by each User Control and everything works fine from that scope. (The first tab at index 0 has no Charts)
Problem is when I select a Tab which has a User Control, the appropriate code to acquire the data from the database and build the chart works fine but the TEXT value of the Label controls in the Markup don't show up on the Page, although the TEXT values are being set in the Code-Behind at the same time the data is being retreived.
If I perform a Post Back of the same page, the TEXT values of the Label controls appear.
I believe this is because the 1st stages of the Page Life Cycle which include the rendering of the Markup aren't firing on the initial loading of the User Control, but get fired on subsequent Reloads or Refreshes of the Page.
Is there a way to work around this? I am figuring a call to the Render event after hitting the database would work but I may be way off base on my thoughts.
Can anybody provide some advice or a potential solution???
Thanks
I was never able to resolve the late binding issue which prevented the text of the labels from appearing until after a manual refresh of my page so I approached the issue from a different angle. I still retained the logic that only allowed the data of each User Control to get populated if their corresponding Tabs were selected by the user, but I moved the in-line code which was embedded in my Markup to my Code-Behind file.
I was not 100% certain as to the order that the mark-up vs. the code-behind got processed, so I researched and found that anything done declaratively in the aspx page is processed first, and the objects are created before being accessed or updated in the code behind.
So with this information I totally separated the two and was able to get the Text to render on the labels without any issue.
I still would haved liked to have known the appropriate way to force a page to call the Render event to simulate or mimick a manual Postback after the initial Page_Load, but going with the flow of the Page Cycle is the much easier and probably a more preferable way to do things.
One way to approach your problem is to consider use of the "Update Panel". It will allow you to render the entire page and then on an event only refresh the area of the update panel.
Generally I would love this feature for performance reasons but there is a catch. Some browsers (e.g. versions of Safari and Opera) do not render these correctly. Is your application a web application intended for general use by consumers? If so you may need to consider a full page refresh on the same page and pass the user data (unless Opera / other browsers have fixed this shortcoming - I have not tested in in 4 months).

How to implement PRG pattern properly in asp.net webforms

I have a simple three page asp.net webforms site and having an issue with the back browser button that throws the popup "...Firefox must send any information that will repeat any action.." when hitting back on the step3.aspx.
The flow is: user lands on step1.aspx, session starts, and a user quotes on a product and gets redirected to step2.aspx. On step2.aspx, you confirm the purchase by clicking an asp:Button. The OnClick event handler, btnPurchase_Click, handles the logic for purchase and redirects, Response.Redirect("step3.aspx"), to step3.aspx. Step3.aspx simply displays the confirmation page (receipt details). The session is destroyed on step3 and when the user hits the back browser button, they are prompted with the resubmit post popup. Ideally, I want the user to hit step1 on hitting back without the resubmit prompt. Each page is set to no-cache and redirects to step1 if session is invalid.
Does anyone have a suggestion for a better flow?
This site will eventually be migrated to asp.net mvc/ajax which will most likely make the PRG workflow easier to implement but for now, looking for a relatively simple way.
A simple solution is to never allow a page to render on postback, but instead accept/store whatever information it was posted, and then redirect to the next page (or itself).
That way if a user hits the back button, it is going back to a GET, not a POST, and avoids the popup.
I give this question a try. The flow you mention will obstruct the pages normal function, which you of course already have in mind. Though, i would say it can be dangerous (against the function you expect) and contraproductive. Based on what I can see from your question, I would definitively remove Page2 and Page3 and keep all logic in same and single page.
I would also be happy to hear what you are trying to avoid, with this? Is it double posts? Like a double-post of a content in a shopping cart? Partial / uncomplete inserts of data input? With the described way to affect back-buttons, you may come around one problem but rise another. A big range of browsers that can act completely different on such work-arounds.
I see two good options,
UserControl,
Create three UserControls which every each of them have each page specific logic. You can programmatically load them into the page. I.e. on bnButton_Click Event. Usercontrols are loaded with LoadControl("PathToAscxFileOnDisk.ascx").
Panels,
I would also think about three <asp:PlaceHolder></asp:PlaceHolder> or perhaps better <asp:Panel></asp:Panel> to put all logic into.
In this case you are completely free from the postback issues and can focus on moving your functions into business logic and have use the Code-File to control the flow on show/hide and populate the controls in/out from the panels/usercontrols. You can probably also control the postback / click-URL & push-enter-key.
And you mentioned Ajax,
Ajax is absolutely there to make your page stateless (which means you can work without cache, sessions, viewstate and so on. Though, the problem lies in the users possibility to navigate between pages. I would think even Ajax is of less help, while you keep the three-pages-solution.
I would personally say it is a simple task to move the aspx files into each ascx and create a aspx as a master-container. With that option you even avoid duplicate namings (like if you copy / paste the code into panels) and trouble with Page_Load flow/logic.
If I understand correctly you're not yet using the PRG.
On step 2, temporarily store the information and redirect to show it. How you do so depends a lot on your application: session, database, cookies, etc are all options with different caracteristics.
Then redirect to show that information.
Same goes on step 3.
If you hit back on step 3, you'll go to step 2. But given you're going back to a GET request, there won't be a warning. Like you said, your application destroys the session data on 3, so according to what you said the user would go to step3.
Maybe I'm missing something on what you said.

Chrome back button skips page

I've run into a very annoying problem that I'm having an impossible time solving. The problem is that for an unknown reason, Chrome is not registering a page in it's history and so when the user clicks the back button, it goes back 2 pages instead of 1.
The page progression is as follows:
Search-form.aspx -> searching.aspx -> search-results.aspx -> result.aspx
More specifically, when I get to the result.aspx page in chrome and hit back, it skips search-results.aspx and jumps all the way back to searching.aspx.
Thoughts?
Your page_load on searching.aspx is sending the browser immediately to another page. The only thing it ever presents the user with is a loading graphic. No links are clicked to get to the next page and Chrome is considering searching.aspx to be the last most relevant step.
Consider using javascript (I prefer jQuery) to present the loading info and cut out searching.aspx entirely. On search-results.aspx use javascript to do an asynchronous (AJAX) call back to the server for the results. While the results are being returned, you can display a nice little graphic telling them to be patient while their results load.
If javascript is not an option, then consider letting the browser's loading functions be enough. I have tried to use an intermediate page in the past for similar things and it's just a mess. Don't get tangled in that web. Either do some asynchronous loading or let the browser handle telling them their page is loading. Most people will be used to, after clicking a search button, waiting for the page to load slightly longer.
EDIT If you want a quick and simple solution, put a button on searching.aspx. Make the button do the page redirect. This way an actual form submission occurs and chrome should register the next page in its history. You could just make searching.aspx be a quick message with an OK button. They click OK and off you go.

Change the url in browser from c# codebehind (NOT seo routing or URL rewriting)

I have a website where there is a lengthy list of items to display so I am using Pagination to make the load on server easier.
However, I am doing the pagination via Ajax so when the user clicks on Next Page or Previous Page linkbutton, the data repeater is refreshed with ajax.
This was working fine until, people started to click on the item and then click back, it takes them to the first page.
suppose you scan about 10 pages, by clicking on the "Next Page" button. The data changes, but the URL in the browser doesnt. And you think you found what you want so you click on it, the browser loads different page, and when you click back, the browser takes you to previous page but since the url did not change, you are back to page 1.
Currently, I have removed ajax so the url changes everytime, but I have seen several website re-write the url in browser when ajax even happens, and I was wondering if I could do the same.
Google search for url re-write digs up only seo routing stuff, nothing on what I actually want (i am sure i am not using the right words)
I was interested to know this problem, any clues or leads on this one?
thanks!
ps: several questions here were kind of close, but was either too complicated or too deviated. sorry if its a duplicate.
The only part of an URL that you can change in js, client-side, without forcing browser to reload whole page is an anchor part (http://domain/page#anchor - the part after # sign). This part is used by many js application (e.g. Google Picassa), also by silverlight to provide browser history support. You'd have to set an anchor part when navigating to another page of your data. When the page is loaded, just check the anchor part and load appropriate page. Also, you'd have to periodically check for changes - this will happen when user uses back/forward feature in his/her browser. (There could be an event that is fired when that happens, I just haven't found it)

Categories

Resources