I have a problem with a webform.
My Goal: Intially when a page is loading, it has to load every textbox empty. After filling the info and click submit, it has to get submitted(UpdatePaymentInfo())
Problem: Here, When the user fills the info and clicks Submit,it calls onload function even before the submit button and makes all text box empty.
Here is the code:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string QueryStringupdatecreditcard1 = Request.QueryString.ToString();
if (String.Equals(QueryStringupdatecreditcard1, "tabID=B"))
{
divTitle.Visible = false;
trmain.Visible = false;
tdOrderSummary.Visible = false;
trCCandBilling.Visible = true;
trtest2.Visible = false;
divUpdatecreditcard.Visible = true;
trusecompaddress.Visible = false;
txtFirstName.Text = "";
txtLastName.Text = "";
txtAddress1.Text = "";
txtAddress2.Text = "";
txtCity.Text = "";
txtZip.Text = "";
txtCardNo.Text = "";
txtVccNumber.Text = "";
trAmountCharged.Visible = false;
}
}
protected void imgbtnSubmit_Click(object sender, ImageClickEventArgs e)
{
try
{
UpdatePaymentInfo();
}
}
Wrap the current contents of your OnLoad method in:
if (!Page.IsPostBack)
{
// Code in here will only be executed when the page is *not* being loaded by a postback
}
This is because, as per the ASP.NET Page Life Cyle, the things that you care about in this instance happen in this order:
Load - During load, if the current request is a postback, control
properties are loaded with information
recovered from view state and control
state.
Postback event handling - If the request is a postback, control event
handlers are called. After that, the
Validate method of all validator
controls is called, which sets the
IsValid property of individual
validator controls and of the page.
So what happens is (somewhat simplified):
You click the image button, triggering the postback.
The data from your form is loaded into your controls.
Your OnLoad method overwrites the values in the controls to clear them.
Your click handler is run, but because of step 3 it sees empty values.
As others have sort-of mentioned, it wouldn't necessarily be a bad thing to refactor your OnLoad method whilst you're doing this. At the moment you seem to have it doing two distinct things:
Clearing the text fields
Setting the visibility of fields
It might be worth separating this into one or two (depending on if the visibility setting and field clearing will be done independently) separate methods and adjusting your OnLoad method so it looks like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsInPostBack)
{
SetFieldVisibility();
ClearFields();
}
}
Page_Load always occurs.
See the documentation on the Page Lifecycle
What you need to do is check to see if the Page_Load is being triggered by a Postback.
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
///do stuff in here that you want to occur only on the first lad.
}
else
}
// code that you want to execute only if this IS a postback here.
{
}
// do stuff you want to do on Page_Load regardless of postback here.
}
You can use the IsPostBack property of the Page as follows:
protected override void OnLoad(EventArgs e) {
if (!Page.IsPostBack) {
EmptyTextBoxes();
}
}
Have you tried wrapping the form reset code in a check to see if the page is a postback?
if(!Page.IsPostback) {
// Do form reset here
}
You thought about using the IsPostBack page variable?
protected override void OnLoad(EventArgs e)
{
if(!IsPostBack){
//all your logic here.
}
}
if it's the case, you might use a databound control and set it to insert mode
Related
I am trying to add a basic switch to my site in order to switch between static and responsive layouts.
I have two linkbuttons at the bottom of my page:
<div id="toggleView">
<asp:linkbutton ID="lbtnMobile" runat="server" Visible="false">Switch to Mobile site</asp:linkbutton>
<asp:linkbutton ID="lbtnFull" runat="server" >Switch to Full site</asp:linkbutton>
</div>
They both have a very similar OnClick event.
protected void lbtnFull_Click(object sender, EventArgs e)
{
c.ViewChange = true;
Session["Customer"] = c;
}
protected void lbtnMobile_Click(object sender, EventArgs e)
{
c.ViewChange = false;
Session["Customer"] = c;
}
The events should set a boolean in a class file (User.vb) between true or false and then save the session, on postback the Page_Load event is supposed to read this boolean and use it to adjust the Viewport meta tag:
protected void Page_Load(object sender, System.EventArgs e)
{
//Other Stuff in here, irrelevant to current question
HtmlMeta view = new HtmlMeta();
view.Name = "viewport";
if (c.ViewChange = false)
{
view.Content = "width=device-width, initial-scale=1";
lbtnFull.Visible = true;
lbtnMobile.Visible = false;
}
else
{
view.Content = "width=1040px, initial-scale=1";
lbtnFull.Visible = false;
lbtnMobile.Visible = true;
}
MetaPlaceHolder.Controls.Add(view);
}
However, when I click on the "Switch to Full Site" linkbutton, the page will postback but nothing will have changed. Does the postback get triggered too early somehow?
The page load event will happen BEFORE your click event. Reference this here.
This means your check for the ViewChange will happen before you set it in the OnClick handler.
You should change
if (c.ViewChange = false)
to
if (c.ViewChange == false)
for something to happen. But I think it won't be what you expect. Because page_load is executed before click event. You may move some code from page_load to click event handlers.
When ever you postback the Page_Load always get called. So, the code mentioned inside Page_Load would always get executed.
protected void Page_Load(object sender, System.EventArgs e)
{
... All your mentioned code will be executed.
}
Therefore, you won't find any change in your HTML page currently viewed in a browser because at postback initial content also got executed. You need to wrap your content inside !IsPostBack to make it work properly.
Thus, modify you code in following way.
protected void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostback)
{
... All your mentioned code will be executed during normal load.
}
}
Also, you need to add some extra code in LinkButton click event i.e. what to show and what to hide.
Firstly your implementation in the Page_Load isn't very clear.
Nevertheless this is what I recommend, from what I've understod:
As the page load will get executed before the post-back event like the buton or link click, you need persist the value of the class object
Make a protected property of type of your class (where you store/manage the ViewChange atribute)
The property should internally (in the get & set), hold/persist the value in session/viewstate (similar to what you've written)
The setting and reading should only be by referring the property directly (and not how you've done the click-event)
On clicking of the button and post setting the new value, you will have to redirect to the same page, as only then the Page_Load event will get the new boolean value that you've just changed in the click-event; (Page_Load occurs befoer the any other post-back event)
An alternative to the fresh redirection is that, you could make a function that has the view changing logic (as depicted in your Page_Load code), and this function should be called on your button/link click event (post boolean value change) and also in the Page_Load event, but within the "!IsPostBack" block
Hope this helps you.
Having just added a new button in my web application, I get an error when clicking on it, and I'm wondering if this is related to misplaced code. I will describe what/where I did, briefly. Thanks very much.
In ascx file:
<asp:Button ID="btn_rezerv" runat="server" Text="Reserve film" OnClick="btn_rezerv_Click"/>
In the ascx.cs file:
namespace CinProj.UserControls
{
public partial class FilmsList : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
PopulateControls();
}
private void PopulateControls()
{
string categId = Request.QueryString["CategID"];
string filmId = Request.QueryString["FilmID"];
....
if (categId != null)
{
.....
}
if (filmId != null)
{
......
Button btn_rezerv = (Button)item.FindControl("btn_rezerv");
}
}
protected void btn_rezerv_Click(object sender, EventArgs e)
{
string fid = Request.QueryString["FilmID"];
ShoppingCartAccess.AddItem(fid);
}
}
}
"Server Error in '/' Application.
Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation. "
Another problem could be because your PopulateControls method should probably only be called when during the Page Load when it's not a PostBack. I can't tell from above, but to me it looks like it only needs done on Load. Try wrapping that call with this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
PopulateControls();
}
}
It's likely the result of making some sort of client change that the server doesn't know about. Many times this is the result of changing values in a dropdown in JavaScript, for example.
To fix, you could:
Do away with using JavaScript for said modification
Use an UpdatePanel and add your control to it. If the client needs to make a change, trigger the UpdatePanel's update in order for the control's viewstate to update.
I have a System.Web.UI.UserControl in my application which is to be used to display messages to the user, however after these messages are displayed to the user once I want them to clear (conditionally).
The simplified code I have now that I am trying to get to work is the following:
protected override void OnUnload(EventArgs e) {
if (_resetOnUnload) {
divMessageBlock.InnerHtml = "";
_resetOnUnload = false;
}
base.OnUnload(e);
}
However any changes to the view in the OnUnload event do not get transferred over on the next page load (form submit).
My question is how would I setup this user control to clear itself either before any messages can be added elsewhere or after the page has been rendered for the user and have stay that way?
Try this. Set the viewstate to save _resetOnUnload and then load it. OnLoad can stay the same, testing whether or not to clear.
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
if (_resetOnUnload) {
divMessageBlock.InnerHtml = "";
_resetOnUnload = false;
}
}
protected override void LoadViewState(object savedState) {
if (savedState != null) {
object[] myState = (object[])savedState;
_resetOnUnload = (bool)myState[0];
}
}
protected override object SaveViewState() {
object[] allStates = new object[]{ _resetOnUnload };
return allStates;
}
How about just outputting your message to a control with ViewState turned off? That way, your message will be displayed, and any subsequent Postback will clear the message.
I guess the OnPreRender event is the last one, where you can change what the control's output should be. After that, the control has been rendered, and your changes will have no effect.
How do I increment a step value to be processed when the page loads? For example, in the code below the viewstate variable is not incremented until after Page_Load, due to the ASP.NET page lifecycle.
protected void Page_Load(object sender, EventArgs e)
{
switch ((int)ViewState["step"])
{
//do something different for each step
}
}
protected void btnIncrementStep_Click(object sender, EventArgs e)
{
//when the button is clicked, this does not fire
//until after page_load finishes
ViewState["step"] = (int)ViewState["step"] + 1;
}
Just move the switch statement into an event that happens later. E.g. LoadComplete() or PreRender(). PreRender is probably a bit late, depending on what you want to do.
There's no way around this. Page_Load event will always happen before any control events get fired. If you need to do something after the control event, use Page_PreRender.
ASP.Net Page Lifecycle Image
Increment during the LoadComplete event or even during OnLoad.
You have all the information needed to make the decision whether to increment from the form data. You don't need to wait for the onClick() event. Check the form to see if the item will be clicked.
Look in the request.params("__EVENTARGS")
This identifies the control that caused the postback.
If you need to increment and check the value during Page_Load, then an option would be to store the value in the session instead of ViewState, e.g:
private int Step
{
get { return (int)Session["step"]; }
set { Session["step"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
Step = 0; // init
else
Step ++; // increment
switch (Step)
{
//do something different for each step
}
}
So I have a weird situation here... I have an System.Web.UI.WebControls.WebParts.EditorPart class. It renders a "Search" button, when you click this button, it's clickHandler method does a DB search, and dynamically creates a LinkButton for each row it returns, sets the CommandName and CommandArgument properties and adds a CommandEventHandler method, then adds the LinkButton control to the page.
The problem is, when you click a LinkButton, its CommandEventHandler method is never called, it looks like the page just posts back to where it was before the ORIGINAL "Search" button was pressed.
I have seen postings saying that you need to add the event handlers in OnLoad() or some other early method, but my LinkButtons haven't even been created until the user tells us what to search for and hits the "Search" button... Any ideas on how to deal with this?
Thanks!
This is my favorite trick :)
Our scenario is to first render a control. Then using some input from the user, render further controls and have them respond to events.
The key here is state - you need to know the state of the control when it arrives at PostBack - so we use ViewState. The issue becomes then a chicken-and-egg problem; ViewState isn't available until after the LoadViewState() call, but you must create the controls before that call to have the events fired correctly.
The trick is to override LoadViewState() and SaveViewState() so we can control things.
(note that the code below is rough, from memory and probably has issues)
private string searchQuery = null;
private void SearchButton(object sender, EventArgs e)
{
searchQuery = searchBox.Text;
var results = DataLayer.PerformSearch(searchQuery);
CreateLinkButtonControls(results);
}
// We save both the base state object, plus our query string. Everything here must be serializable.
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
return new object[] { baseState, searchQuery };
}
// The parameter to this method is the exact object we returned from SaveViewState().
protected override void LoadViewState(object savedState)
{
object[] stateArray = (object[])savedState;
searchQuery = stateArray[1] as string;
// Re-run the query
var results = DataLayer.PerformSearch(searchQuery);
// Re-create the exact same control tree as at the point of SaveViewState above. It must be the same otherwise things will break.
CreateLinkButtonControls(results);
// Very important - load the rest of the ViewState, including our controls above.
base.LoadViewState(stateArray[0]);
}
You need to re-add the dynamically created controls, in the onload, so that they can be in the page hierarchy and fire their event.
LinkButton link= new LinkButton();
link.Command +=new CommandEventHandler(LinkButton1_Command);
protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
try
{
System.Threading.Thread.Sleep(300);
if (e.CommandName == "link")
{
//////////
}
}
catch
{
}
}
A dirty hack I just came up with, is to create dummy LinkButtons with the same IDs as the real buttons.
So let's say you are going to create a LinkButton "foo" at Pre_Render (which is too late), then also create a dummy foo at Page_Load:
var link = new LinkButton();
link.ID = "foo";
link.Click += fooEventHandler;
dummyButtons.Controls.Add(link);
(Where "dummyButtons" is just a PlaceHolder on the page with Visibility set to false.)
It's ugly, but it works.