I have a form to edit employee information. If the user wishes to enter a new e-mail address for the selected employee, there is a textbox and a button that says "Add Email Address." Very simple, you enter the e-mail address, click Add Email Address. It postsback and that button's event handler executes the INSERT to the database.
The problem:
If you press F5 to refresh the page after that postback, it causes the same postback to occur, even if the textbox is blank. In other words, for every time you hit F5, the actions in the event handler for that Add Email Address button occur again. If I hit F5 ten times, the same e-mail address shows up in the database ten times.
One suggestion I found said, "just re-direct to the same page after you apply your changes." The reason this is not ideal in our case is that it's a rather lengthy form of employee data --- if the user makes a bunch of changes to the overall form (such as FirstName, LastName, etc.), then makes an e-mail addition before applying the changes elsewhere, those changes elsewhere would be lost if we re-directed to the same page.
The very long winded solution I can think of is, capture all of the data in ViewState, carry it across the re-direct to the same page, then use a query string in the URL to determine if we want to fill in the data from ViewState. Before I embark on that path, I'm hoping that instead of that, there is some method I just don't know that says like, PostbackButDontRetainPostbackData() (wishful thinking, I know).
In the handler for that Add Email Address button check if the email already exists in the database. If it does, do not add the email again and display an appropriate message to the user. Usually forms have a reserved area like a hidden div for this purpose so in case anything goes wrong the div will be populated with error messages and displayed to the user.
Also, it would help to display a confirmation message to the user when their data is successfully received and processed.
UPDATE
If you don't like to show any messages to the user, simply do nothing after you find out that the email already exists in the database. e.g.:
public void AddEmailToDB(string email)
{
// first find out if the email already exists in the database
bool isDuplicate = ...;
// if it does, simply return and do nothing
if(isDuplicate) return;
// if control reaches here then the email is not
// a duplicate and you can do your normal processing
}
UPDATE II
If you don't want the browsers to show a messagebox everytime a user presses F5 after a postback, you can do a partial postback using AJAX by wrapping your email textbox and add button in an UpdatePanel, it's very easy to use.
Related
I am using the PasswordRecovery Control in my ASP.NET WebForms Application (C#), now the thing is, When we are using PasswordRecovery Control, we are forced to use Wizard Control, which means, if the user enters username correctly, it will then hide textbox and display success message (or whatever you put in SuccessTemplate).
Now, the issue is by this way, when Unauthorized user, tries to access the application, they can try this control to get the actual username from the application (security risk). So, if they try the wrong username, they will get the "UserNameFailureText" and if they will enter the proper username, they will see the next template (SuccessTemplate) which will show a success message (By this way, they can get that the entered username is available in the system or not), so I want to remove the wizard structure, in all scenario, the textbox with a username will stay on the screen, and no matter what user enters, he will see a generic message "if you have entered the correct username, you will receive an email" Like that.
If anyone has any idea whether it's possible in PasswordRecovery control, or should I have to build a custom Page?
PS: I have tried removing SuccessTemplate from the page, it will automatically take the default success template.
I don't see why you can't just create a page from scratch? All that text box will do is check if the user exists, send them the email, and display your message. There not a whole lot of reasons thus to use the built-in template.
So, a simple button re-set password can run some code behind, send the re-set email, and set a label or text box, or even some "div" as visible = true to display your message. You don't mention or note that authentication provider you are using - but given the built in templates - then that suggests FBA, and thus the tables that drive the site and hold user + passwords should be fully available to your code behind.
On the other hand, you might have to add some kind of password re-set table, and say include a GUID generated ID, and the datetime. That way, the link you send in the email is specific to the one user - and has a limited time before that link expires.
Or I suppose the link in the email just directs them to the new password page - but I tend to toss in a GUID that is checked against that new re-set table. With the guid, then when they click on their email link, you can display their name, and only prompt for the new password. The email link simply includes that GUID as a parameter, and you pull that one row from the re-set table to get who is about to re-set their password.
Currently I'm in say Page A. The URL is http://localhost:22507/PageA.aspx. From there select a dropdown value. Now the same page shows some extra data and an edit button along with the dropdown. Page URL is still http://localhost:22507/PageA.aspx. When I click the Edit button its redirected to another page Page B. And the present URL is http://localhost:22507/PageB.aspx?qstr=6EysKHDt1+a/m8SQcruQOCVgWF+9+PCfmydyeX5wbKU=
While clicking the Back button in the Page B, it directly goes to the first state. ie, I've to again select the drop down, click edit etc.
How can I go back to the just previous state(Page A with data and Edit button) after clicking Back button?
Now I use Response.Redirect("PageA.aspx", false); for redirecting
When changing the selected list item, use pushState to update the browser address bar and history to record the change of state. E.g instead of the address bar still displaying /PageA.aspx, it could instead show /PageA.aspx?selected=1.
If you then use the back button from PageB.aspx?qstr=6EysKHDt1+a/m8SQcruQOCVgWF+9+PCfmydyeX5wbKU=, pressing back will return you to PageA.aspx?selected=1. You can then parse the query string to determine the correct state to display.
Mozilla provides documentation on pushState here: https://developer.mozilla.org/en-US/docs/Web/API/History_API.
Note that for older browsers there are some compatibility issues. A clunky old method that would work would be to reload the page with a query string when the dropdown is changed, allowing the back button to work in much the same way. An alternative that avoids reloading the page may be to update a cookie with a flag indicating the state. On loading the page, check for the cookie and flag. However, then you would need to consider expiry of the cookie (ie what if they didn't press back but instead navigated to pageA again through some other means, would loading the saved state still be acceptable?).
I've created a form to send message for admin, and when I click on send button all things are fine and data are sent and saved to the database and I print success message. But if I refresh the page -by pressing F5- the message is sent again to the server and database!. How can I fix this problem ?
I just want to send message to the server once when I click on send button, not on refresh page.
my code is
<asp:Button ID="btnsenddata" runat="server" OnClientClick="return validate()" OnClick="btnsenddata_Click" Text="SendData" />
protected void btnsenddata_Click(object sender, EventArgs e)
{
//this place i connect to DB
}
This is a commond issue. The behavior is by design: The information of the
button that was pressed is actually re-sent to the server (along with all
other information of the controls) when the page is being refreshed.
A nice way of workaround i found, while surfing the net, is (this way is on the server side) to use HashTable:
//Class member
HashTable ht = new HashTable();
btnMyButton_Click(object sender, EventArgs e)
{
ht =(Hashtable)Application["UserOKHashtable"]
if ((ht.ContainsKey(Session["UserSessionKey"]))
{
// double - clicked or user pressed refresh
return;
}
else
{
(ht.Add(Session["UserSessionKey"],UserName);
// your code here
// and finally
((Hashtable)Application["UserOKHashtable"])
.Remove(Session["UserSessionKey"]);
}
}
Remember to remove the user's session key from the hashtable at the end
of the procedure, otherwise the user will only be able to click the
button once during the whole session.
If you search for "prevent double post", you will find more information and possible workaround for it.
hope it'll help :)
I would put a OnClick handler on the button. So, in your .asp file <asp:Button id="btnMyButton" runat="server" OnClick="btnMyButton_Click"
Then on the aspx.cs side you add method 'btnMyButton_Click' and put your code in there
btnMyButton_Click(object sender, EventArgs e)
{
//your code to update database goes here
}
You will have to come up with some method, probably in the database, to ensure that repeated messages are not sent within a certain period of time. You can't easily get around the F5 issue because all that does is tell the browser to repeat exactly what it did the last time. This means the same data is sent to the user. That is the trick, any check you put in must store the data within the server since the client will just replay the last action.
You could hold a session variable to let you know when the user sent this form last (just ensure you check for Session["sentform"] != null when checking for the session variable)
Also, you could create a simple log in the database to say what user clicked (if you have logged in users), the time it was last sent, and something that will let you identify which page, message requestor was fired. Then you can ask the database if this user has sent message for page/process X within the last couple minutes and return true or false.
I have registration form, suppose there are 5 fields, and all are required i.e. mandatory.
My problem is that when user login & fill 2 fields of that registration form & click browser back button, then I want to restrict user to same form & Show requiredField Validator messages of incomplete fields. So How can I fire Validation on browser back button & restrict user on same form.
You cannot affect browser behavior when the user clicks the Back button.
The correct solution is to check right after user have been login, if he has complete the registration entries on database, and if not you redirect him to fill that data.
From your comments, to alert them a solution is to capture the onbeforeunload and check there if they have fill out everything or not, show your message.
Simple example, you just need here to place your conditions.
window.onbeforeunload = function() {
return 'You have unsaved changes!';
}
You can't disable the back button (see the other answers and their comments).
What you can do is check on every page whether the user is logged in. If not, redirect him to your login page. This way the user can't access the site without logging in, which I guess is what your client is really after.
I have an asp.net web page (C# 2008) where the user would enter an EmployeeID, and when they tab out of the textbox (the page executes a validation code block in the codebehind), they get a messagebox prompting them to select one of two values from a dropdown listbox.
The code for the message prompt in the codebehind is :
Response.Write("<script>window.alert('Please select Alpha or Beta')</script>");
After the prompt is displayed, and the user clicks "ok" and returns to the page, the text on the page appears distorted (the text in labels are a size larger, the labels get wrapped to another line etc)
I tried putting a Response.Redirect("UserProfileMaint.aspx"); after the messagebox in the codebehind, but now, the messagebox does not appear;
So this is my squence:
User enters EmployeeID
If user has NOT selected Alpha or
Beta, then show messagebox
If user HAS selected Alpha or Beta,
then don't show messagebox
I want to display the messagebox validation, and ensure the appearance of the text on the page is not distorted. How can I do this?
Response.Write writes directly to the output stream, placing it before <html> which the browser gets very confused by (causing your text issues). What you want to do instead is this:
ClientScript.RegisterStartupScript(GetType(), "alert",
"alert('Please select Alpha or Beta');", true);
ClientScript.RegisterStartupScript includes the script in the page to be run on load rather than put in the response too early. The last argument: true is telling it to wrap that alert in <script> tags, keeping your code-behind cleaner.
The best way to handle this would be to use Javascript and do Client side validation. If you really want to do server side validation then instead of showing a alert by using Response.Write you should use RegisterStartupScript or better show the message using a Label at the top.
HTH
When you call Response.Redirect, that occurs on the server side, whereas you want the redirect to occur on the client side after a choice is made.
To do that, when you write your script with Response.Write (btw, there are much better ways to do this), you would have logic that determined what the user selected, and then based on the selection, either requery them for data, or set the location property of the inherent document object to the url you want to redirect to.