I've been looking for this answer for a couple weeks now but many other questions/answers don't fit my project or simply don't work.
Let me explain my project. It is a simple View Page which on page load it would set the Text to different fields throughout the page. On the bottom I have a container with buttons which control which div is displayed in the container. On each click of the button, I run some code to set data sources to grid views or fill fields with text. I noticed when I click F5 to refresh the page I get that pesky "form resubmission" popup which will cause the last button click such as appending a note to a listview to be duplicated.
Here is some code to understand what I am doing
HTML(Not complete, just necessary to understand my question)
<td style="vertical-align: top;" class="Flow-Sub-Menu">
<asp:Button ID="Button_Sub_Menu_Financial" runat="server" Text="Financial Info" OnClick="Button_Sub_Menu_Financial_Click" />
<asp:Button ID="Button_Sub_Menu_Indemnitors" runat="server" Text="Indemnitors" OnClick="Button_Sub_Menu_Indemnitors_Click" />
<asp:Button ID="Button_Sub_Menu_Court" runat="server" Text="Court Info" OnClick="Button_Sub_Menu_Court_Click" />
<asp:Button ID="Button_Sub_Menu_Forfeiture" runat="server" Text="Forfeiture Info" OnClick="Button_Sub_Menu_Forfeiture_Click" />
<asp:Button ID="Button_Sub_Menu_Collaterals" runat="server" Text="Collaterals" OnClick="Button_Sub_Menu_Collaterals_Click" />
<asp:Button ID="Button_Sub_Menu_Notes" runat="server" Text="Notes" OnClick="Button_Sub_Menu_Notes_Click" />
<asp:Button ID="Button_Sub_Menu_Documents" runat="server" Text="Documents" OnClick="Button_Sub_Menu_Documents_Click" />
</td>
<div id="Div_Sub_Menu_Notes" runat="server" visible="false">
<div class="row">
<div class="col-xs-4" style="min-width: 550px;">
<div class="Flow-Box">
<div class="Flow-Box-Content" style="height: 440px; overflow-y: scroll;">
<asp:ListView ID="LV_Notes" runat="server" ItemPlaceholderID="ItemPlaceHolder" DataKeyNames="Bond_Note_ID" OnPagePropertiesChanging="LV_Notes_PagePropertiesChanging" OnItemCommand="LV_Notes_ItemCommand">
<LayoutTemplate>
<table style="width: 500px; background-color: white;">
<tr id="ItemPlaceHolder" runat="server"></tr>
<tr>
<td colspan="2">
<asp:DataPager ID="DataPager_Notes" runat="server" PagedControlID="LV_Notes" PageSize="3">
<Fields>
<asp:NextPreviousPagerField ButtonType="Link" ShowFirstPageButton="false" ShowPreviousPageButton="true"
ShowNextPageButton="false" />
<asp:NumericPagerField ButtonType="Link" />
<asp:NextPreviousPagerField ButtonType="Link" ShowNextPageButton="true" ShowLastPageButton="false" ShowPreviousPageButton="false" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td colspan="2" style="padding-left: 10px; padding-right: 10px;">
<div style="border: 2px solid grey; height: 75px; padding: 5px;">
<%# Eval("Note") %>
</div>
</td>
</tr>
<tr>
<td style="padding-left: 10px;" <%# (Eval("Document_ID").ToString() != "" ? "" : "hidden=\"hidden\"") %>>
<label>Document Attached : <%# Eval("Document_Title").ToString() %></label>
</td>
<td style="text-align: right; padding-right: 10px;" <%# (Eval("Document_ID").ToString() != "" ? "" : "hidden=\"hidden\"") %>>
<asp:Button ID="Button_View_Document" runat="server" Text="View/Download Document" CommandName="View_Document" CommandArgument='<%#Eval("Document_ID")%>' />
</td>
</tr>
<tr>
<td style="text-align: left; padding-left: 10px;">
<div>
<%# Convert.ToDateTime(Eval("Created_DateTime")).ToShortDateString() + " " + Convert.ToDateTime(Eval("Created_DateTime")).ToShortTimeString() %>
</div>
</td>
<td style="text-align: right; padding-right: 10px;">
<div>
<%# Eval("Full_Name") %>
</div>
</td>
</tr>
<tr>
<td colspan="2" style="height: 20px; border-top: 4px solid #009900;"></td>
</tr>
</ItemTemplate>
</asp:ListView>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4" style="min-width: 500px;">
<div class="Flow-Box">
<div class="Flow-Box-Label">
New Note
</div>
<div class="Flow-Box-Content">
<table class="Flow-Box-Table">
<tr>
<td>
<textarea id="TextArea_New_Note" runat="server" style="width: 400px; height: 150px;"></textarea>
</td>
</tr>
<tr>
<td>
<asp:Button ID="Button_Append_New_Note" runat="server" OnClick="Button_Append_New_Note_Click" Text="Append Note" />
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
C# Codebehind
protected void Button_Sub_Menu_Notes_Click(object sender, EventArgs e)
{
resetSubMenuButtons();
Button_Sub_Menu_Notes.BackColor = System.Drawing.Color.Orange;
Div_Sub_Menu_Notes.Visible = true;
string bondID = Request.QueryString["BondID"];
bindNotes(bondID);
}
protected void bindNotes(string bondID)
{
DataTable dt = Common_Functions.GetData("SELECT * FROM View_Bond_Notes_With_Name WHERE Bond_ID='" + bondID + "' ORDER BY Created_DateTime DESC");
LV_Notes.DataSource = dt;
LV_Notes.DataBind();
}
protected void LV_Notes_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
(LV_Notes.FindControl("DataPager_Notes") as DataPager).SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
string bondID = Request.QueryString["BondID"];
bindNotes(bondID);
}
protected void LV_Notes_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "View_Document"))
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
string documentID = e.CommandArgument.ToString();
Session["BondDocumentID"] = documentID;
Page.ClientScript.RegisterStartupScript(GetType(), "openDocument", "window.open('/FileServing/Bond_Document_Server.aspx');", true);
}
}
protected void Button_Append_New_Note_Click(object sender, EventArgs e)
{
string bondID = Request.QueryString["BondID"];
string UserID = Request.Cookies["UserID"].Value;
string newNote = TextArea_New_Note.Value;
if (String.IsNullOrWhiteSpace(newNote))
{
return;
}
cmd = new SqlCommand("INSERT INTO Bond_Notes " +
"(Bond_ID, Created_DateTime, Created_By, Note) " +
"VALUES " +
"(@Bond_ID, @Created_DateTime, @Created_By, @Note)", conn);
cmd.Parameters.AddWithValue("@Bond_ID", bondID);
cmd.Parameters.AddWithValue("@Created_DateTime", DateTime.Now);
cmd.Parameters.AddWithValue("@Created_By", UserID);
cmd.Parameters.AddWithValue("@Note", (String.IsNullOrWhiteSpace(newNote) ? (object)DBNull.Value : newNote));
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
TextArea_New_Note.Value = "";
bindNotes(bondID);
}
So when the user clicks "Button_Append_New_Note", the code will fire to run the sqlcommand and then refreshes the ListView by calling the "bindNotes(bondID)". If the user clicks F5 or hits refresh for whatever reason, they are resubmitting that form and add duplicates. I've read many solutions to redirect to the same page, this will not work in my case since the div would be hidden again and I would prefer the Notes div to stay visible so the user can see their new note in the listview. I also prefer not to have an sql check to look for a duplicate and prevent an insert since I may want the user to insert duplicates if they chose to at another time, but the user would manually type in the duplicate.
Any recommendations or suggestions on how to avoid the form resubmission?
Also please no criticizing on the code, I am looking for answers, not a lecture on why its bad to build an SQL sentence with inline string addition. I will correct and optimize these faults eventually.
If you found my solution elsewhere, please ensure it would work in my case cause I have found my same question many times, but not with my scenario.
Thanks in advance.