I have encountered an unexpected behaviour and/or bug in the .net postback system.
I have a page that uses a master page to provide common elements, with form inputs split between the child and master pages. The form submit button is located on the master page, and I am attempting to process postback on the masterpage.
Any time I attempt to submit data where the form contains any non empty values and the url contains parameters, the page fails to process correctly. This does not occur if the page is submitted under either condition by itself.
The form postback method is post.
The page fails to load and in firefox returns the no element found error.
I have checked for correct class names ect and I do have empty attributes in non form elements, but as the page loads correctly at first I don't think that is relevant. I have also checked for infinately looping code.
This is the current postback handling code:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
save_page();
}
page_render();
}
//save
private void save_page()
{
dev_text.Text = "save in progress";
}
Setting text in an HTML element on the server will only be seen on the browser when the HTML is sent to the browser. Normally this happens once the entire processing of the page has completed... so normally quite some time after the user initiated the post-back.
Instead of setting the text on the server, consider setting the text directly on the browser at the moment of submission. Something like...
function setSavingText(){
// Vanilla javascript...
document.getElementById("<%=dev_text.ClientId%>").innerHTML = "save in progress";
// JQuery...
$("#<%=dev_text.ClientId%>").text("save in progress");
}
<asp:Button runat="server" ... OnClientClick="setSavingText();" />
The above function contains both a line for vanilla (normal) javascript, and one for the jQuery library. You only need one of them.
Related
I am working on a legacy service that has 30 aspx pages with years of business logic
There is a parent aspx page which acts as a base page that the above aspx pages inherit from.
I need to add a Response header and I am having trouble finding the right place to add it to the ParentPage.aspx.cs so that it gets applied to all aspx pages.
Ideally I would want to add after PageLoad() is done for the the data to be available to add to the header.
I tried using the onPreRender() and onLoadComplete() stages to add the header. But it is not guaranteed that this would get called because the aspx pages have logic that do Response.Redirect() Because of the redirect onPreRender() and onLoadComplete() do not get called. I would not be able to change the logic on redirects
However UnLoad() does get called all the time. But response cannot be altered in the UnLoad() stage
Are there any suggestions where the header to the response could be added in the ParentPage.aspx.cs ?
Do you have a master page?
Just drop in the code to add a header in the page load event.
I mean, code can fill out text boxes, change things, and then you can toss in a new header - the order of such events don't matter.
So, if you have a master page that all pages use?
Then do this in site master:
protected void Page_Load(object sender, EventArgs e)
{
Response.AddHeader("Test", "My Test Value");
}
So, it not clear if you have a master page, but page load triggers in site master each time any navigate to any page occurs. And also the above runs each time any post-back or button click occurs on any page.
So, just add the header in the page load in master.
The above thus results in this:
So, it don't matter if you add the header at the start of code, or end of code say in a page. The other code behind can run, make changes to the "DOM" via code behind, but everything WAITS 100% until ALL of the code behind is done running, and THEN and only THEN does the WHOLE page make the trip back down to the client side, the client side re-loads the page, re-starts any JavaScript code (and re-sets, all JavaScript values and variable to fresh start), and then the page life cycle is complete, ready to start again on the next button click etc. And on the server side, the page class is disposed, and all its variables etc. also goes out of scope (hence the term state-less). So, both ends, including client side js code variables are re-set in this process.
So, in fact the "order" or what event you use to inject/add that header? it really don't matter when it runs, only as long as it runs at "some point" in time during that whole page life cycle on the server.
In fact, what I am saying, it is REALLY hard to mess this up, since just about any event can add the header - but page load looks to be as good as any event here.
Edit: The page load event
You thus should see/be able to add the event to page master like this:
I'm working with ASP.NET webforms and I'm wondering if it is possible to change/ignore the PostBackUrl so it won't change pages.
My button:
<asp:Button ID="continuebtn" OnClick="Continuebtn_Click" runat="server" PostBackUrl="~/client/profile.aspx" CssClass="btn btn-success btn-sm" Text="Continue"/>
And the OnClick function is:
protected void Continuebtn_Click(object sender, EventArgs e)
{
//some code
if(condition == false)
//change the url from PostBackUrl so it won't change pages
else
//keep the current Url
}
I've tried :
continuebtn.PostBackUrl = "";
continuebtn.Attributes["PostBackUrl"] = "return false";
continuebtn.Attributes.Remove("OnClick");
continuebtn.Attributes.Add("OnClick","return false");
continuebtn.OnClientClick = "return false;";
add return; to if
I tried to remove the PostBackUrl from the button and add it from the code behind with continuebtn.PostBackUrl = "~/client/profile.aspx" but it didn't work either.
There are two big reasons to use post-back URL in place of say using a code behind click event and say then response.Redirect("some web page").
First up, post-back url passes the previous page!!!!!
So, if you have say a text box and a button like this: (or evne a grid view)
Now you can use code behind to jump to the next page, or you can use/set/have post-back url set.
If you use post-back URL. Then you don't need to write a code behind stub, and you ALSO get use of previous page in the next page on-load event (you ONLY can pick up previous page in load - first time).
eg:
protected void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack == false)
{
TextBox tbox;
tbox = Page.PreviousPage.FindControl("TextBox1");
Debug.Print("Text box = " + tbox.Text);
TextBox1.Text = s;
}
}
}
so post-back url = a great way to pass/get at/use the previous page values with find control. Now if you not needing to do this, then you probably should not use post-back URL, since you are bulking up the payload for the next page (it will contain the current page, and you have as noted use of "previous page". However, it is a fantastic way to avoid parameters and/or cluttering up session() just to pass a bunch of values. Just use post-back URL and then like "magic" then previous page can be used. if you don't use post-back URL then previous page is null and not valid.
And if you place two buttons on the page? Can you set postback url? Sure you can set that control, text box or do anything you like - but do keep in mind that the code behind is running AFTER a post-back, and it will of course be too late to change a button that CAUSED the post back.
So, you can certainly do this in button2 click even to change button1:
protected void Button3_Click(object sender, EventArgs e)
{
Button1.PostBackUrl = "";
}
So in above, button3 click event and code behind wiped out the post-back URL of button one. Or we can of course set the url to anything we want.
Now, the code behind is done, page is rendered and THEN sent back down to the browser with the above change. If user hits button1, then no postback url exists - we blew it out with the above code.
However, in the SAME button event? no, it is too late to change or modify the post-back.
In that case, and if you need "conditional" jump? Then you need to delete and remove the post-back url, and simply put the logic you need to determine the ya, or nay jump based on the code behind for that click event.
HOWEVER - and a BIG WHOPPER however? If you JUST use a response.Redirect("some web page") in that code behind, then you DROPPIGN THE MAIN reason as to why the developer used post-back URL in the first place. That main, big, huge, large reason is that post-back URL gives the next page in line FULL USE of the previous page values with "previous page". If you do NOT use post-back URL, then you can't use previous page to pass all those values and inspect and get and grab control values from the previous page.
So what if you really did need the "abilities" that post-back URL provides (that ability of course is "previous" page in the next page load!
In that case, then you have to use Server.Transfer() in that code stub to get use of previous page in the next page that loads.
So, regardless:
You can't change post-back URL in the same button code event - it is too late.
If you are going to then put the logic in the code event? Then be VERY VERY aware that if you use a response.Redirect("some web page"), then you may VERY well be breaking the functionally of why in the first place the developer used post-back url (to have use of "previous page".
Your suggested idea to modify client side the post-back url in one button click, and then do a js "click" of that button you just changed the post-back url should also work (good idea!!!).
But, I would thing that just using a code behind stub in the click event, and then the code can choose to navagate or jump to the next page based on that code? Right?
However, if you do that, then you will break the "features" of post-back URL in pasing page prevous.
In that case? Then you need to use a server.Transfer("to next web page") in place of response.Redirect("to next web page), since a server.Transfer will give you use of "page previous" in the next page load event JUST LIKE post-back URL does!
Of course with a server.Transfer, you will note that the web page URL does not change or update - and this is a fall out of having to do this. (and may, or may not matter to you).
I have a Update Panel inside a User Control i use on 2 pages in my website
Both pages use the same MasterPage, ScriptManger is declared in the MasterPage.
Both pages call the UC the same way:
<uc:SearchCube runat="server" ID="searchCube" />
in the Update panel i have many RadioButtons that on change generate a server side event that fill dropdown in the update panel and update the panel
protected void SearchCategoryChanged(object sender, EventArgs e)
{
FillDropdowns();
SearchOptions.Update();
}
Update Panel is set like this:
<asp:UpdatePanel ID="SearchOptions" runat="server" UpdateMode="Conditional"
hildrenAsTriggers="true"/>
Each RadioButton is set like this:
<asp:RadioButton ID="RadioButton1" GroupName="SearchCategory" runat="server"
AutoPostBack="true" OnCheckedChanged="SearchCategoryChanged" Text="Text"/>
I also have an AsyncPostBackTrigger on each Radio Button Controller
The problem i have is that on one page when i call the Update() function the panel is updated and Page_Load is triggered which causes the UC to refresh and reload the default settings of the UC
I can see in DEBUG mode that on the working page Update() does not generate Page_Load.
Can anyone explain to me why this is happening?
Everytime a request goes to the server, it executes the Page_Load event.
What you need to do is make sure you have a PostBack validation on all your pages:
protectec void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
//Not a postBack: Normal page load
//Init your page here
}
else
{
//It's a PostBack (from a command).
//Do nothing or init stuff your all your commands.
}
}
If you put some breakpoints in your Page Load and your SearchCategoryChanged method, you'll be able to see what the pipeline looks like.
Fixed my problem.
the problematic page is an index page that takes a few parameters in.
I have a Response.Redirect() on the page to avoid duplication of pages.
Apparently when the PostBack() is made it calls the page without any parameters and i was forcing it to be redirected into a default view since no parameters were sent to the page.
i found a lead to my problem in a Microsoft help forum that stated:
By calling Response.Write() directly you are bypassing the normal
rendering mechanism of ASP.NET controls. The bits you write are going
straight out to the client without further processing (well,
mostly...). This means that UpdatePanel can't encode the data in its
special format.
Anyway the page was reloading every time which caused it to reload the User Control with it's default values.
I have a AjaxCall.aspx page that will be called another page by .ajax() using jquery.
At AjaxCall.aspx I had remove all the html tag and left only
<%# Page Language="C#" AutoEventWireup="true" CodeFile="AjaxCall.aspx.cs" Inherits="_AjaxCall" %>
and at the code behind it was a simple on the pageload event.
protected void Page_Load(object sender, EventArgs e)
{
Response.write("{ \"Testing\": \"Hello World!\" }");
}
I monitor the ajax request in Chrome developer tools in Network and I notice that every time I make a ajax request to AjaxCall.aspx page, it requested twice in a row. I later went into debug mode to check and discover that the pageload event fired twice.
I did some digging and found that an empty img src has something to do with this, but the problem is I have no any html tag in the AjaxCall.aspx page!
I later tried to add back the HTML body and form tag, and try to call that page again, and good news is it load once, but as soon as I add those html tag back to AjaxCall.aspx, it load twice again.
I can't have those html tag at my AjaxCall.aspx because it suppose to return a json format data when it is requested, having those html tag will cause error on whatever page that called it. At the same time I don't want it to continue load twice on every call I made. So is there anyway to overcome this problem?
If you want to deliver JSON response with application page (.aspx and code behind), you have to flush your response and close it in order to stop the process.
If you don't do that, the page .aspx will be return, may be with some HTML tag generating multiple request (like img with bad src)
Try this:
protected void Page_Load(object sender, EventArgs e)
{
Response.write("{ \"Testing\": \"Hello World!\" }");
Response.Flush();
Response.End();
}
Moreover, you can also use before your Response.write a Response.Clear in order to clear the optionnal content that could have been injected by any code, just to be sure to send only this content.
I have a text string value that I'd like to persist from one web page to another without using query strings or the session/view states. I've been trying to get the ASP http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hiddenfield.aspx">HiddenField control to pass information from one web form to a different form.
All the hiddenfield control examples that I've seen is to preserve round trips from the client to the server for the same form.
Is there way for a form to access the ASP controls (and their values) from the previously-rendered form? Or is the initial form simply disposed of in memory by the time the second form executes it's OnLoad method?
Quick answer is no. As others have noted, you can use Server.Transfer and then you can - however this is to be used with caution. It is a "server side redirect" eg.
Your user is on http://mysite.com/Page1.aspx they click a button and you perform a Server.Transfer("Page2.aspx"). Page2.aspx will be rendered in their browser, but the URL will still be Page1.aspx, this can cause confusion and mess up back/forward navigation.
Personally I would only use Server.Transfer as a last resort - in the world of the web, sharing data across pages generally means you need to use a storage mechanism; Cookie, QueryString, Session, Database - take your pick.
You can't get the previous page fields with Response.Redirect.
You can with cross page posting :
if (Page.PreviousPage != null)
{
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
}
If both pages live in the same application you can use Server.Transfer:
firstpage.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Server.Transfer("~/secondpage.aspx");
}
secondpage.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Page previousPage = (Page) HttpContext.Current.PreviousHandler;
Label previousPageControl = (Label) previousPage.FindControl("theLabel");
label.Text =previousPageControl.Text;
}
A somewhat better solution would be implementing an interface on your first page where you expose properties for the values needed by the second page.
I would presume that the Response.Redirect() sends a Location: HTTP header to do a redirect.
As HTTP is stateless, I'd also presume that these variables are inaccessible.
There are however, solutions.
Print a form with hidden fields, and use javascript to submit it
Redirect in the code internally (load up the thing it needs to get to manually)
Store the data in some temporary database table somewhere, and pass along a unique ID
However, from my experience, I can't understand why you might need to do this (other than re-submitting a form after a user authentication - which hopefully you should be able to use method 2 for
Remember, a Response.Redirect instructs the browser to issue another request to the server. So far as the server is concerned, this next request is indistinguishable from any other incoming request. It's certainly not connected to a previous form in any way.
Could you explain your aversion to storage in the session, so we can propose some viable alternatives?