Prevent Page Refresh in C# - asp.net

Duplicate of Asp.Net Button Event on refresh fires again??? GUID?
hello, ive a website and when a user click a button and the page postback, if the user refresh the Page or hit F5 the button method is called again.
any one know some method to prevent page refresh with out redirect the page to the same page again ?
something like if (page.isRefresh) or something... or if exist any javascript solution is better.
this seen to works.... but when i refresh it does not postback but show the before value in the textbox
http://www.dotnetspider.com/resources/4040-IsPageRefresh-ASP-NET.aspx
private Boolean IsPageRefresh = false;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["postids"] = System.Guid.NewGuid().ToString();
Session["postid"] = ViewState["postids"].ToString();
TextBox1.Text = "Hi";
}
else
{
if (ViewState["postids"].ToString() != Session["postid"].ToString())
{
IsPageRefresh = true;
}
Session["postid"] = System.Guid.NewGuid().ToString();
ViewState["postids"] = Session["postid"];
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (!IsPageRefresh) // check that page is not refreshed by browser.
{
TextBox2.Text = TextBox1.Text + "#";
}
}

Thanks for comments and sorry for my mistake,
I found this code in:
http://www.codeproject.com/KB/aspnet/Detecting_Refresh.aspx
And this time tested ;)
private bool _refreshState;
private bool _isRefresh;
protected override void LoadViewState(object savedState)
{
object[] AllStates = (object[])savedState;
base.LoadViewState(AllStates[0]);
_refreshState = bool.Parse(AllStates[1].ToString());
_isRefresh = _refreshState == bool.Parse(Session["__ISREFRESH"].ToString());
}
protected override object SaveViewState()
{
Session["__ISREFRESH"] = _refreshState;
object[] AllStates = new object[2];
AllStates[0] = base.SaveViewState();
AllStates[1] = !(_refreshState);
return AllStates;
}
protected void btn_Click(object sender, EventArgs e)
{
if (!_isRefresh)
Response.Write(DateTime.Now.Millisecond.ToString());
}

You can test for the Page.IsPostBack property to see if the page is responding to an initial request or if it's handling a PostBack such as your button click event. Here's a bit more information: w3schools on IsPostBack
Unfortunately that's not going to solve your problem since IsPostBack will be true when the user clicks the button as well as when they refresh the page after the button action has taken place.
If you're doing a task like performing CRUD on some data, you can Response.Redirect the user back to the same page when you're done processing and get around this problem. It has the side benefit of reloading your content (assuming you added a record to the DB it would now show in the page...) and prevents the refresh problem behavior. The only caveat is they still resubmit the form by going back in their history.
Postbacks were a bad implementation choice for the Asp.net and generally are what ruin the Webforms platform for me.

This doesn't solve the problem.
First of all, storing a token in the view state is not a good idea, since it can be disabled. Use control state instead. Although, a HttpModule is a better solution.
All in all, this will not work anyway. If you open another tab/window the session will be invalid for the previous tab/window. Therefore braking it. You must somehow store a unique value each time a page is first loaded. Use that to determine where the request came from and then check the "refresh ticket". As you may see, the object for one user might get pretty big depending on the amount of requests made, where and how long you store this information.
I haven't seen any solution to this I'm afraid, as it is pretty complex.

bool IsPageRefresh ;
if (Page.IsPostBack)
{
if (ViewState["postid"].ToString() != Session["postid"].ToString())
IsPageRefresh = true;
}
Session["postid"] = System.Guid.NewGuid().ToString();
ViewState["postid"] = Session["postid"];

I tried many ways and I ended up looking for the form data sent when the postback / refresh is triggered... I found that there is a Key for any VIEWSTATE created and you can just compare those Keys like...
I put that on my custom basepage to reuse it like an Property
public bool IsPageRefresh = false;
protected void Page_Init(object sender, EventArgs e)
{
if (IsPostBack)
{
var rForm = Request.Form;
var vw = rForm["__EVENTVALIDATION"].ToString();
var svw = Session["__EVENTVALIDATION"] ?? "";
if (vw.Equals(svw)) IsPageRefresh = true;
Session["__EVENTVALIDATION"] = vw;
}
}

Related

How to update CheckBoxes on the client side after making changes on the server side?

I have a DropDownList and a CheckBox on my web form. After the DropDownList is clicked and this event is posted back to the server. DropDownList_SelectedIndexChanged event is called on the server side. Inside that event handler, I have CheckBox.Checked = true, But I couldn't make the page on the client side to reflect this change (CheckBox.Checked = true). How do I achieve this? Or am I in the wrong direction to use the DropDownList's event handler to update the CheckBox because the page firstly reloads and then DropDownList_SelectedIndexChanged is called?
Page load method:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.DropDownList1.Items.Clear();
AddItemsToDropDownList();
}
}
DropDownList selected index changed event handler:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
var selected = this.DropDownList1.SelectedItem.Text;
CheckBox checkBox = GetCheckBoxToBeSetByText(selected);
checkBox.Checked = true;
}
OK. Found the issue. Actually there is nothing wrong with the code in my original post. But to make a smallest sample when I posted, I removed some "extra" code. The below is the "complete" code (OK, fine, I still removed some code). As you can see, I put the CheckBox into a static Dictionary. Each time the SelectedIndexChanged event handler is called, it's modifying the CheckBox in that static Dictionary, which means it's modifying the CheckBox object created from the last session? (still not clear here) Looks like each time when a postback message is received, a new set of CheckBox objects are created. Bear with me if this is known to everybody here already because I only have two days of experience on this web development thing up to today.
private static Dictionary<Environment, CheckBox> EnvironmentsCheckBoxes;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
EnvironmentsCheckBoxes = new Dictionary<Environment,CheckBox>();
EnvironmentsCheckBoxes.Add(Environment.Dev1, this.Dev1_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.Dev2, this.Dev2_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.QA, this.QA_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.QA2, this.QA2_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.Demo, this.Demo_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.Prod, this.Prod_CheckBox);
EnvironmentsCheckBoxes.Add(Environment.UAT, this.UAT_CheckBox);
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
var selected = this.DropDownList1.SelectedItem.Text;
if (selected == "Dev1")
{
EnvironmentsCheckBoxes[Environment.Dev1].Checked = true;
}
else if (selected == "Dev2")
{
...
}
...
}

.net using and reaching public value

I wrote this code in .NET. When I want to change ‘s’ by clicking button2, it doesn’t change. I mean after clicking button2 and then I click Button1 to see the changes but nothing changes. How can I change and access the value of ‘s’ properly. What am I doing wrong?
public string s;
public void Button1_Click(object sender, EventArgs e)
{
Label1.Text = s;
}
public void Button2_Click(object sender, EventArgs e)
{
s = TextBox1.Text;
}
You need to understand how web applications work.
In each post back an instance of the class that handles the page is loaded, so when you click on button 1, the page does a post back and loads again, so this way the variable s isn't loaded with your content.
To make this code work, you need to save the S values on the page viewstate.
try replacing "public string s;" with this:
public string s
{
get { return (string)ViewState["myValue"]; }
set [ ViewState["myValue"] = value };
}
More Information about Page Life Cycle at: http://msdn.microsoft.com/en-us/library/ms178472(v=vs.100).aspx

Make an asp .net web app offline

Basically a web app that we distribute to clients, one of whom will be trialling it so I need to be able to switch it off at a certain point. Don't want to put the end date in the web.config in case they work out they can change it, I was thinking of putting something in the global.asax with a hard coded date, but then I'm not sure how I can 'turn off' the app. I was thinking of checking the date in the Authenticate Request part and simply redirecting to a page that says your trial is finished (or something similar), but is there a better way?
You can do that on global.asax as:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if(DateTime.UtcNow > cTheTimeLimitDate)
{
HttpContext.Current.Response.TrySkipIisCustomErrors = true;
HttpContext.Current.Response.Write("...message to show...");
HttpContext.Current.Response.StatusCode = 403;
HttpContext.Current.Response.End();
return ;
}
}
this is safer than place it on web.config, but nothing is safe enough. Its even better there to redirect them to a page, or not show them a message, or what ever you think.
For make redirect to a page you also need to check if the call if for a page, and the code will be as:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
string cTheFile = HttpContext.Current.Request.Path;
string sExtentionOfThisFile = System.IO.Path.GetExtension(cTheFile);
if (sExtentionOfThisFile.Equals(".aspx", StringComparison.InvariantCultureIgnoreCase))
{
// and here is the time limit.
if(DateTime.UtcNow > cTheTimeLimitDate)
{
// make here the redirect
HttpContext.Current.Response.End();
return ;
}
}
}
To makes it even harder, you can make a custom BasePage that all page come from it (and not from System.Web.UI.Page) and you place there the limit on the render of the page - or show a message on top of every page render, that the time is ends.
public abstract class BasePage : System.Web.UI.Page
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if(DateTime.UtcNow > cTheTimeLimitDate)
{
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
// render page inside the buffer
base.Render(htmlWriter);
string html = stringWriter.ToString();
writer.Write("<h1>This evaluation is expired</h1><br><br>" + html);
}
else
{
base.Render(writer);
}
}
}
Just add the app_offline.htm and you can even create a nice message for your users. Also it's very easy to put the site back online, just remove or rename the app_offline.htm.
http://weblogs.asp.net/dotnetstories/archive/2011/09/24/take-an-asp-net-application-offline.aspx

Store and transfer values in a ascx control

I have a problem that I have been struggling with for some time, and it is regarding transfering values from one control to another.
Basically I have two .ascx controls. On control1: I have an email textbox called txtEmail. The txtEmail is used to save the email in the SQL table, and on update button click, I load Control2 that has a email textbox as well. I need the emailtext box from control1 to be available on email textbox on control2.
I have tried all kinds of different ways but to no avail. I even tried using delegates and events but I can't make it work.
Does anyone know how I can do this.
Regards
Please find below the code:
public event EventHandler Notify;
public string Email
{
get { return txtEmail.Text; }
set {Email= value ; }
}
//button that will handle the update
protected void btnUpdateDB_Click(object sender, EventArgs e)
{
var email = txtEmail.Text.ToString();
public BaseClass.BAL.MBAL m = new BaseClass.BAL.MBAL();
var s = new BaseClass.Controllers.m();
s.email=email;
if(m.save(s)!=0) txtMsave.Text="Saved....";
}
//second control
public void notifyEmailChange(object sender,EventArgs e)
{
txtUsername.Text = member1.Email;
}
protected void Page_Load(object sender, EventArgs e)
{
if(Page.IsPostBack)
{
member1.Notify += new EventHandler(notifyEmailChange);
}
}
public string email {
set { txtUsers.Text = value; }}
Maybe I am trivializing the problem, but if you are wanting to be able to read/write to the text box on each of the custom controls, just make a public property that reads and writes to the textbox on each of the two controls.
public string EmailAddress {
get {
return txtEmailAddress.Text;
}
set {
txtEmailAddress.Text = value;
}
}
Now the page that contains the two controls can read the email address from the first control and write it into the email address text box in the second control.
If I am misunderstanding the problem, let me know.
The way that I have done this in the past is to have
UserControl1 have a custom event called (for instance) Notify.
The containing control wires Notify to an EventHandler
When notify fires (on the update) the consuming event handler fires and this event handler updates the email on UserControl2
Might seem overengineered but because UserControl2 can't "see" UserControl1 I think this is the way to go
Example
In UserControl1
public event EventHandler Notify;
and within the update button click event handler
if(Notify != null)
{
Notify(this, new EventArgs());
}
In parent control
in Page_Load
ucUserControl2.Notify += new EventHandler(NotifyUserControl);
and to set the message
protected void NotifyUserControl(object sender, EventArgs args)
{
ucUserControl2.Email = ucUserControl1.Email;
}
You obviously need public properties in UserControls to expose the Email text

ASP.net passing data between pages

I have a .aspx web page, with a html form within it, this also has two input boxes.
Whats the best way to take the input box data and pass it to a new .aspx page where it is dealt with by the request method.
Assuming that the data is not sensitive then the best method to pass it to your new page using Response.Redirect and the querystring using:
protected void MyFormSubmitButton_Click(Object sender, EventArgs e)
{
string value1 = txtValue1.Text;
string value2 = txtValue2.Text;
// create a querystring
string queryString = "x=" + value1 + "&y=" + value2;
// redirect to the encoded querystring
Response.Redirect("NewPage.aspx?" + Server.URLEncode(queryString));
}
This web page has a lot of information which you can use for passing the values from page to page.
http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx#Y1100
Try Server.Transfer:
Terminates execution of the current
page and starts execution of a new
page by using the specified URL path
of the page. Specifies whether to
clear the QueryString and Form
collections.
If you set the preserveForm parameter
to true, the target page will be able
to access the view state of the
previous page by using the
PreviousPage property.
Your main page:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
// ThreadAbortException occurs here.
// See http://support.microsoft.com/kb/312629 for more details.
Server.Transfer("AnotherPage.aspx", true);
}
}
"AnotherPage.aspx":
protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null)
{
// Accessing previous page's controls
}
}

Resources