There are two scenarios for an ASP.net webforms page which I would like to differentiate between: "Normal postback" and when a page is created because the next page has called PreviousPage.
A normal posback occured for page 1
IsPostback is true
IsCrossPagePostBack is false
and
There was a Server.Transfer("page2.aspx") to page 2, and page 2 uses PreviousPage so page 1 is created virtually. For page 1:
IsPostback is true
IsCrossPagePostBack is false
You can see that IsPostBack and IsCrossPagePostBack do not help because they are the same in both cases.
The reason why I am asking this:
I have page 1 which sends data to page 2 via cross-page postback (PostBackUrl="page2.aspx" set in page 1). For all users who have javascript enabled, this works fine.
But I wanted also a fallback for the users who have javascript disabled. For them, a click on the submit button on page 1 does not lead to page 2 but to a postback to page 1. Page 1 could now detect this and do a Server.Transfer("page2.aspx") to page 2. The problem is: When page 2 uses PreviousPage then page 1 is created again and would do a Server.Transfer() again and again and again ...
My workaround for this is to do the Server.Transfer not in the Page_Load event but only in the Page_PreRender event because this event does only occur when it is a normal postback and not when the page is created as PreviousPage.
This workaround works but it is very dirty. If I could differentiate between the two scenarios already in the Page_Load event, it would be much better.
Is this possible?
When you do the HttpServerUtility.Transfer from Page 1 to Page 2, the HttpContext is then shared between Page 1 and Page 2. So normally, one request means one request handler (usually a page) and one request context. But in this case there's two handlers and one (shared) context. You can use the context to share information about the request between the two handlers.
So one solution may be that Page 1 puts all the data that page 2 needs in the HttpContext.Items. Then Page 2 first checks for this data. If present, Page 2 knows that control was transferred by way of Server.Transfer and that it should not call on Page 1 through PreviousPage. Instead it should now get its data from the context.
Page1.aspx
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack && HttpContext.Items.Contains("CrossPagePostBack") == false)
{
// Cross page postback did not succeed (JavaScript disabled)
string name = NameTextBox.Text;
HttpContext.Items.Add("Name", name);
HttpContext.Items.Add("Transfer", true);
Server.Transfer("Page2.aspx");
}
}
Page2.aspx
protected void Page_Load()
{
if(IsPostBack)
{
string name;
if(CrossPagePostBack)
{
// Cross page postback succeeded (JavaScript was enabled)
HttpContext.Items.Add("CrossPagePostBack", true);
name = PreviousPage.NameTextBox.Text;
}
else if (HttpContext.Items.Contains("Transfer"))
{
// We got transferred to from Page1.aspx
name = (string)HttpContext.Items["Name"];
}
// Do something with Page 1's form value(s)
}
}
Or you can turn this around and let Page 2 add a mark ("Page 2 was here") to the HttpContext.Items, and then Page 1 checks that mark. If it's present it doesn't need to transfer again (break the loop). I'm not 100% sure if a call to PreviousPage also results in a shared request context.
Page1.aspx
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack && HttpContext.Items.Contains("CrossPagePostBack") == false)
{
// Cross page postback did not succeed (JavaScript disabled)
if(HttpContext.Items.Contains("Transfer"))
{
// We did not yet transfer to Page 2
HttpContext.Items.Add("Transfer", true);
Server.Transfer("Page2.aspx");
}
}
}
Page2.aspx
protected void Page_Load()
{
if(IsPostBack)
{
if(CrossPagePostback)
{
// Cross page postback succeeded (JavaScript enabled)
HttpContext.Items.Add("CrossPagePostBack", true);
}
string name = PreviousPage.NameTextBox.Text;
// Do something with Page 1's form value(s)
}
}
The second method is simpler in implementation, especially if the form on Page 1 is complex. You'd have only one place where you read Page 1's form, and you only add a simple boolean to the HttpContext.Items.
Related
I have two simple pages. Page 1 postbacks to page 2. I have two buttons that can cause a postback, Confirm and Delete. On page 2 there are two buttons; one saves the passed data, and the other deletes the passed data. What I need to do is have the unneeded button on page 2 set to visible = false. How can I set up different actions based on which button caused the postback?
you could use Query string to indicate the page to show the appropriate button in your second page
ex : http:\localhost\page1.aspx?show=delete
at the other hand, in your page2 "page_load" function you could manage the code to show the button based on query string requested along with the request url
the code will be something like this on your Page_Load:
string showButton = Request.QueryString["show"];
if(showButton == "delete")
{
// write the code to show the delete button here
}
Here a button that does a postback
<asp:LinkButton runat="server" ID="btnBestPrice" OnClick="btnSearchBestPrice_Click">Search Best Price</asp:LinkButton>
Assume that this button is clicked on page
http://localhost:47207/Default?ClusterId=131
Now after the postback is completed, the page is still
http://localhost:47207/Default?ClusterId=131
However, after the postback, i want to make URL to be
http://localhost:47207/Default
Is that possible?
If i make a redirect, the postback event would be loss. I still want to process the postback event perfectly fine. So if somehow i can set the postback url to be raw url of the page on the client side or?
asp.net 4.5 web forms c#
I assume your postback is displaying some information to user, but have to change the URL without interrupt the process.
First of all you have to understand that if you changed the URL in the server side, the browser will treat it as a new page and make a new request. Response.Redirect is basically telling the browser it is time to move onto another page. So you cannot change the URL while remaining in the same request. (while Server.Transfer is remaining at the same URL but different page which is not what you want)
So I have 2 solutions for you, the following one make sense to me but there is still redirecting the page:
protected void Page_Load(object sender, EventArgs e) {
if (Session["ClusterId"] != null) {
try {
int ClusterId = int.Parse(Session["ClusterId"]);
// Code here
} catch { }
Session.Remove("ClusterId");
return;
}
}
protected void btnSearchBestPrice_Click(object sender, EventArgs e) {
int ClusterId = int.Parse(Request["ClusterId"]);
Session.Add("ClusterId", ClusterId.ToString());
Response.Redirect("~/Default");
}
Here is another solution that does all the actions in your btnSearchBestPrice_Click event without Redirect and Session, and bind a JavaScript page ready event, call history.pushState and also wipe out the unnecessary parameters in the action attribute of your form element.
A button on html page redirect to aspx page with window.open() command.
There are certain data on the html page which i want on server-side of the aspx page before page_load executes.
following is my code on the html page which redirects to the aspx page
var win = window.open('mypage.aspx','_self');
win.args=this.Args;
following is my code on aspx page which tries to catch the data passed from the html page
<script type='text/javascript'>
var readyStateCheckInterval = setInterval(function () {
if (document.readyState === "loading") {
$('#hdnArgs').val(window.args);
clearInterval(readyStateCheckInterval);
}
}, 100);
</script>
<input type='hidden' id='hdnArgs' runat='server'/>
Following is the code on the aspx.cs file which tries to read the hidden variable's value which has been set from the data of the html page
protected void Page_Load(object sender, eventargs e)
{
string data = hdnArgs.value; //this is always null
}
But what I get is always 'null'.
The readyStateCheckInterval sets the hidden variable value after the page_load event is completed.
I want the value of hidden variable before page_load.
How can I get that?
Its not possible to set value of any control before page life cycle finish.
let me explain you..
You try to set value on hdnArgs but In Page lifecycle control only generate and send it to browser only after finish Page_init,Page_Load,Page_Load_Complete
All those methods..
So,When you try set args value to hdnArgs using $('#hdnArgs').val(window.args); Page_load event already completed..
Solution
I think you need to pass value as a QueryString to get Value in Page_load
var win = window.open('mypage.aspx?Args='+this.Args,'_self');
and In ASPX page
protected void Page_Load(object sender, eventargs e)
{
string data = Request.QueryString["Args"];
}
Also you can send data using Page Postback if you have large data.
To confirm:
hdnArgs is on the starting page
starting page opens a new page in a window
when that page is opening (but not complete, which will hopefully happen when you happen to look at it at 100ms intervals... it won't if it's quicker than that), input#hdnArgs is updated to the a value from the opened page
The Page_Load is on the starting page
You want the start page Page_Load to get a value from the popup
You'll need to review the lifecycle of asp.net pages, eg: https://msdn.microsoft.com/en-gb/library/ms178472%28v=vs.100%29.aspx
By the time the start page even thinks about processing any javascript, the Page_Load of the startup page is long gone.
Perhaps, in the Page_Load, you could load the new page directly eg with
var content = new System.Net.WebClient().DownloadString(contentUrl);
and parsing it for the #hvnArgs
Here is the sequence in which events occur when a master page is merged with a content page:
http://msdn.microsoft.com/en-us/library/dct97kc3.aspx
So, my problem is:
I have one login page (not use master page), one master page, and hundreds of content page.
I check login session Session["loggedInUser"] in master page (if not logged in, redirect to login page)
So, when I don't log in, if I type the address of one content page, it must check login session in master page and redirect to login page, right? But it has two cases here:
If in content page, I don't use anything related to Session["loggedInUser"], it will redirect to login page, so, it's OK here!
The second case: if I use Session["loggedInUser"] to display Username in content page for example:
UserInfo loggedInUser = (UserInfo)Session["loggedInUser"];
it will return null object here, because the page_load in content page is fired before page_load in master page, so it thows null object instead of redirecting to login page.
I also tried Page_PreInit in master page but no help
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["loggedInUser"] == null)
{
Response.Redirect("~/Login.aspx");
}
}
Any suggestion?
Presumably, when you say you are using the Session["loggedInUser"] value, you are then calling .ToString() method or similar to display it?
In which case, you will need to check for a null object before using it. It would be best practice to check for the existance of the object before using any methods on it in any case, so:
if (Session["loggedInUser"] != null)
{ ... }
Only if you are certain that the code will never be executed without the Session object being instantiated can you use methods without checking for a null reference.
http://msdn.microsoft.com/en-us/library/03sekbw5.aspx
Finally I've come up with a solution:
I create a class BasePage like this:
public class BasePage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
if (Session["loggedInUser"] == null)
{
Response.Redirect("~/Login.aspx");
}
base.OnLoad(e);
}
}
And in the content page, instead of inheriting from Page, I change to BasePage and it works perfectly
Thanks for all of your support
Nice day ;)
You could check for Session["loggedInUser"] in the content Page's Page_PreRender() rather than Page_Load()or alternatively, do the master page check in the Page_Init() rather than Page_Load(). We had the same problem and went with the Master page Page_Init() option, so that we could still use Page_Load() in all the Content pages.
Edit: It's Page_Init() not PreInit().
I have 2 masterpages(1 for prelogin,2nd for afterlogin),home page is independent,logout page inherits postlogin page) in all postloginpage session chck if sessionnull(xyz)else(redirect loginpage) all this in Page_Init event of afterlogin.master................Successfull
I have 2 aspx pages, in a postback event from page 1, i add data to the current context, then do a server.transfer to page 2. this all works as expected, however due to the server.transfer, the address bar still shows the url for page 1.
the weirdness comes when i click a button on page 2.
in IE (7 or 8) when i click a button on page 2, the page posts to page 2 as expected.
in Firefox when i click a button on page 2, the page posts to page 1.
Has anyone else experienced this?
Am i doing something wrong?
Is there a workaround?
this is essentially the code in page 1
Context.Items["x"] = x.Checked;
Context.Items["y"] = y.Checked;
Context.Items["z"] = z.Checked;
Server.Transfer( "page2.aspx", false );
Do a cross-page postback instead?
MSDN: Cross-Page Posting in ASP.NET
If you're not using PreviousPage, you could use Response.Redirect("~/Page2.aspx"); instead. This will inform the user's browser of the page change.
Alternatively, if you are using PreviousPage use a cross-page post back by setting the PostBackUrl attribute on the desired Button. This will allow your Server.Transfer logic to be properly handled. To get access to the CheckBox's value you will need to make public properties on Page1 that will be accessible through the PreviousPage.
So Page1 will contain these properties in the code behind:
public bool xChecked { get x.Checked; }
public bool yChecked { get y.Checked; }
public bool zChecked { get z.Checked; }
Page2 will use PreviousPage:
protected void Page_Load()
{
if(PreviousPage != null && PreviousPage is Page1)
{
if(((Page1)PreviousPage).xChecked)
{
//use xChecked like this
}
}
}
You could try setting the form.action to the specific page you want to post to.
page 2's Form Load Event:
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Form.Action = "page2.aspx"
End Sub
This should guaranty posting to the correct page.