ASP.NET Redirect and End Page - c#

So I read up a lot about how to properly use Response.Redirect without causing some errors.
Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();
Situation: A user logs in the site and visits a page that lists forms. The user sits on that page for an hour doing nothing (which would log them out). The user clicks a button to edit a title (which requires a postback). This results in the user object being null since it logged him out of the session.
What I have done: In the page load, check if the user object is null and if it is, redirect to the login page. That is what should happen right?
Problem: The button event is STILL firing. Is it because I have the following line of code?
Context.ApplicationInstance.CompleteRequest();
How can I stop the event from being firing when I simply want to redirect to the login page?
I know I can provide true in the redirect code, but that will cause an error too right?
Response.Redirect(url, true);
What I currently do (which is not the best way I know): In the button event, I again check to see if the user object is null. If it is not null, proceed with the code to edit the title (recording who edited it). This is a bad way of handling this.
What I have seen: Wrap all events with Response.IsRequestBeingRedirected. But if I have several pages and lots of button events, this can get a bit annoying. Is this the only way to handle this situation?
Example:
protected void Page_Load(object sender, EventArgs e)
{
Account account = Session["Account"] as Account;
if (account == null)
{
Response.Redirect("WebForm1.aspx?NewSession=true", false);
Context.ApplicationInstance.CompleteRequest();
return;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Account account = Session["Account"] as Account;
Label1.Text = account.userID.ToString();
}
Again, if I am already on the page, and the session expired, and I click Button1, the Button1_Click method is still being called. What I provided will give me a "NullReferenceException". Page_Load IS being called, and it is making the redirect. However, Button1_Click is still being called even with the return statement in Page_Load.
Thanks!

You are correct about Response.Redirect(url, true). It is kind of expensive because it throws ThreadAbortException causing the current thread to terminate which is not what you want most of the times.
There is even a KB exists on this topic KB312629.
And yes, with your code it is not possible to prevent events from firing for the current IHttpHandler (which Page class implements) using built-in classes/methods.
So I would suggest to create base page class and add a bool field indicating about request completion request plus method that will call ApplicationInstance.CompleteRequest and will set the flag to true. Also you'll need to override RaisePostBackevent method to take control over controls (not Page) events invocation on page.
public abstract class BasePage : Page
{
private bool shouldNotRaiseEvents;
protected void CompleteRequest()
{
shouldNotRaiseEvents = true;
Context.ApplicationInstance.CompleteRequest();
}
protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
if (shouldNotRaiseEvents)
{
return;
}
base.RaisePostBackEvent(sourceControl, eventArgument);
}
}
Your updated code would be:
Response.Redirect(url, false);
CompleteRequest();
Also please note that if you have something inside LoadComplete, PreRender, SaveViewState, Render, Unload event handlers and you don't want this code to execute after redirect call you'll need to override that methods also.

Related

Invoking a method from the parent page after user control has been loaded?

May I know if there is any way to invoke a method from the child page(.aspx) after the page load of the user control is finished?
Right now I have an issue of being unable to retrieve the value from the child page because the variables from the user control has not been assigned the value yet.
To put it simply
FROM MY .ASPX FILE
Page_Load(object sender, EventArgs e)
{
x = getValueFromUserControl();
}
FROM MY USER CONTROL
Page_Load(object sender, EventArgs e)
{
int x = getvalueFromDatabase();
}
getValueFromuserControl()
{
return x;
}
Since the ASP.NET Life Cycle goes from the child page(.aspx) page_load -> user control page_load, I am unable to retrieve the value of x.
That said, ideally I would not like to put the function in the child page and call it from the user control as the user control is being used in other pages.
In short, I would like to invoke a method from my .aspx page after the page_load in my user control ends, Thank you!
Get the value at a later page event:
protected override void OnLoadComplete(EventArgs e) {
x = getValueFromUserControl();
}
Unless, of course, there is a specific reason why you must get the value on Page_Load. There are other, probably more appropriate ways to handle this, but without knowing what x is and what you need to do with it, it is hard to give any other advice. For example, maybe the UserControl should fire an event that is handled by the page.

Postback collapsing fields

I've got a login button with he following code.
protected void prv_Click(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
if (!HttpContext.Current.Request.IsSecureConnection)
{
string postbackUrl = HttpContext.Current.Request.Url.AbsoluteUri.Replace("http", "https");
Response.Redirect(postbackUrl);
}
}
login_box.Visible = true;
}
The problem is, if the user is browsing using http and clicks on login link which fires off the prv_Click, the site redirects you to https which is correct, but the login_box which is standard div set to visible false and run at server never gets set to true. The user has to click on the login link again which then expands it.
Any help would be appreciated.
Don't set the visibility on the button click, set it on page load. Something like this should work:
login_box.Visible = HttpContext.Current.Request.IsSecureConnection;
Note that it shouldn't be in an IsPostBack. This will always ensure that it's only visible when you have a secure connection. If it needs to be hidden for any other reasons, then you'll need to modify the expression accordingly.

How to globally cancel post-back events for specific business logic?

I would like to be able to display a page, but with all controls disabled. The idea is for a user to view a standard page, but not actually interact with the page. Disabling all UI-controls server side is simple enough, but my main concern is an "inventive" user attempting to manually post the form back with fake information. My question is two fold:
Will built in event validation catch the devious activities?
If event validation doesn't catch it, is there a way to globally throw away the postback event (e.g. the button click, not the full life cycle)
No, you can't stop the normal Postback process.
How are you determining if the page should be disabled? Upon Postback use that same check in your button handler. If it's true, then don't save any information.
public void button1_Click(object sender, EventArgs e)
{
if(Page is disabled)
{
return
}
//Do normal save routine
}
Addressing one of your two questions:
If event validation doesn't catch it, is there a way to globally throw away the postback event (e.g. the button click, not the full life cycle)?
One option may be to add a value to the ViewState, and if that value exists on a postback, redirect the user to an error page. A user tampering with the viewstate should be caught. This doesn't meet your wish to throw away only the postback event, but maybe redirecting to an error page after receiving a postback from a page you thought no postbacks were possible from is ok.
if (ViewState["PageSetToReadOnly"] != null)
{
// Redirect to error page.
}
Another option would be to check if it is a postback in the page's PreInit event, and if so, unwire event handlers:
if (Page.IsPostBack)
{
this.Button1.Click -= new EventHandler(Button1_Click);
}
The best way I think to globally cancel the postback is to override this Page method. You can perform whatever logic you need to set the DoNotProcessPostBack during the OnLoad event :
Protected Overrides Sub RaisePostBackEvent(sourceControl As IPostBackEventHandler, eventArgument As String)
If DoNotProcessPostBack = False Then
MyBase.RaisePostBackEvent(sourceControl, eventArgument)
End If
End Sub
sourceControl is the control performing the postback and skipping over the MyBase.RaisePostBackEvent basically nullifies raising the event for it.

How to detect if Refresh button(F5) is pressed

I have the below code
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//do something
}
else
{
// do something else
}
}
protected void Button1_Click(object sender, EventArgs e)
{
//do something
}
}
The point is that a post back happens if I press F5/refresh button or a button click. How will I prevent the code from doing any action if F5/refresh button is clicked?
I have checked Detect F5 being pressed and Refresh but the solution of mine will be different as I need to do this in C# code.
Thanks
You are trying to capture something on the client - so it must be client side script (as discussed in the link).
It's not a postback in ASP.Net terms - your page is simply being requested again (GET). You cannot stop this - its just like going to some other page on your web site and clicking back through some navigation.
If you are saying you want to prevent some type of server side code you have from being run (more than x times) then you can think about sessions or cookies and read them in before you run whatever process. A simplistic sample:
visit page 1 - set session or cookie that identifies page 1 process was run
visit page 2 - set session or cookie that identifies page 2 process was run
return to page 1 - check for existence of session or cookie variable, and if exists, don't run page 1 process.
Another option, if viable is to use ASP.Net caching.

c# updatepanel with timer page_load

I'm experimenting with some AJAX now. I have a custom control which appears on my masterpage in which there is an update panel and a timer. The timer fires and the panel updates and everything is dandy. Except that there are some operations that I don't want it to perform on every refresh. It seems like the entire page lifecycle happens with each refresh. There are variables I want to set, and keep their value on the refresh. Is there a way to make it perform ONLY what's in the timer_tick call?
You could take a look at Request["__EVENTTARGET"] in the page load event to see what control caused the postback. If it's the timer control, jump out of the function.
Assuming your timer is called "refreshtimer":
protected void Page_Load(object sender, EventArgs e)
{
if (Request["__EVENTTARGET"] == "refreshtimer")
{
return;
}
// etc
Not sure what what an AJAX.Net post back looks like to, But I usually protect my other controls and content by checking for post back;
protected void Page_Load(object sender, EventArgs e)
{
// if its a post back then my controls should already be setup...
if (!Page.IsPostBack)
{
InitControlData();
}
}
and then it should fall thru to your event handling?
protected void timer_tick(object sender, EventArgs e)
{
// Do my Ajaxy work~
}
UpdatePanels always force the entire page to refresh. If you want only a certain portion of the page to be processed (and it's a fixed size) then you could try using an iframe.
Alternatively, if you want to save the variables you can either put them in ViewState or SessionState so that they are persisted between postbacks
This is not possible with UpdatePanels... the entire page will go through the entire lifecycle. As others mentioned, you can limit the processing that happens by using IsPostBack or ScriptManager's IsInAsyncPostBack, but ultimately this is not going to be a great solution for complex pages.
However, you can use Page Methods to execute just one static method in your page, but you'll have to make the Javascript call yourself and update the UI. Here are some examples:
http://www.singingeels.com/Articles/Using_Page_Methods_in_ASPNET_AJAX.aspx
http://encosia.com/2009/07/21/simplify-calling-asp-net-ajax-services-from-jquery/
http://weblogs.asp.net/craigshoemaker/archive/2008/09/29/using-jquery-to-call-asp-net-ajax-page-methods.aspx

Categories