フォームを送信して更新すると、asp.netでデータが再送信されますか? C# で、ページの読み込み時にページの更新イベントをトラップする方法はありますか??
5 に答える
ASP.NET は、それを直接行う方法を提供していません。
一方、重複提出を避けるためのテクニックがいくつかあります。
送信後にリダイレクトします。これは最悪です。重複送信を回避できたとしても、ユーザーの観点からは、最新の Web アプリケーションでは受け入れられません。
フォームごと、セッションごとに送信を追跡します。ユーザーが初めてフォームを送信するときは、セッションでこれを覚えておいてください。別の送信が発生した場合は、破棄する必要があるかどうかを判断してください (場合によっては、破棄してはなりません。たとえば、StackOverflow で回答を 1 回編集すると、必要に応じて 2 回編集できます)。
最初の送信後、JavaScript での送信を無効にします。これにより、場合によっては、ユーザーが送信ボタンをダブルクリックしたり、最初にクリックしたりして、フォームが送信されなかったと考えて待機し、2 回目のクリックを行うという状況が回避されます。もちろん、これに頼らないでください。JavaScript が無効になっている可能性があります。ダブルクリックでは機能しますが、F5 の更新では機能しません。すべての場合、この手法は完全に信頼できるわけではありません。
例として、2 番目のものを実装してみましょう。
this.textBoxComment
ユーザーがブログのページに新しいコメントを追加できるコメント ボックスがあるとします。提出は次のように行われます。
private void Page_Load(object sender, System.EventArgs e)
{
if (this.IsPostBack)
{
string comment = this.ValidateCommentInput(this.textBoxComment.Text);
if (comment != null)
{
this.databaseContext.AddComment(comment);
}
}
}
ユーザーが 2 回クリックすると、コメントが 2 回投稿されます。
それでは、いくつかのセッション トラッキングを追加しましょう。
private void Page_Load(object sender, System.EventArgs e)
{
if (this.IsPostBack)
{
if (this.Session["commentAdded"] == null)
{
string comment = this.ValidateCommentInput(this.textBoxComment.Text);
if (comment != null)
{
this.databaseContext.AddComment(comment);
this.Session.Add("commentAdded", true);
}
}
else
{
// TODO: Inform the user that the comment cannot be submitted
// several times.
}
}
}
この場合、ユーザーはコメントを 1 回だけ送信できます。他のすべてのコメントは自動的に破棄されます。
問題は、ユーザーがいくつかのブログ投稿にコメントを追加したい場合があることです。それを可能にする方法は 2 つあります。簡単な方法は、ポストバック以外のリクエストごとにセッション変数をリセットすることですが、これにより、ユーザーは最初のページで更新を押すよりも、あるページで投稿を送信し、別のページをロードできるようになります。 2 ページ目にコメントを追加できるようになりました。
private void Page_Load(object sender, System.EventArgs e)
{
if (this.IsPostBack)
{
if (this.Session["commentAdded"] == null)
{
string comment = this.ValidateCommentInput(this.textBoxComment.Text);
if (comment != null)
{
this.databaseContext.AddComment(comment);
this.Session.Add("commentAdded", true);
}
}
else
{
// TODO: Inform the user that the comment cannot be submitted
// several times.
}
}
else
{
this.Session.Remove("commentAdded");
}
}
より高度な方法は、コメントが送信されたページのリストをセッションで追跡することです。
private void Page_Load(object sender, System.EventArgs e)
{
List<string> commentsTrack = this.Session["commentAdded"] as List<string>;
string blogPostId = this.ValidatePostId(this.Request.QueryString["id"]);
if (blogPostId != null)
{
if (this.IsPostBack)
{
this.AddComment(commentsTrack);
}
else
{
if (commentsTrack != null && commentsTrack.Contains(blogPostId))
{
commentsTrack.Remove(blogPostId);
}
}
}
}
private void AddComment(List<string> commentsTrack)
{
if (commentsTrack == null || !commentsTrack.Contains(blogPostId))
{
string comment = this.ValidateCommentInput(this.textBoxComment.Text);
if (comment != null)
{
this.databaseContext.AddComment(comment);
if (commentsTrack == null)
{
commentsTrack = new List<string>();
}
commentsTrack.Add(blogPostId);
this.Session["commentAdded"] = commentsTrack;
}
}
else
{
// TODO: Inform the user that the comment cannot be submitted
// several times.
}
}
同じ問題が発生していたので、セッション トレースで解決しました。そして、この問題を解決するのは簡単で時間のかからない方法だと思います。
たとえば、「ボタン」をクリックすると、システムはイベント「button_click」をキャッチします。ページを更新すると、システムは同じイベントを再実行します。この問題が発生しないようにするには、イベントに : をイベントに挿入します
private void button_click(object sender, System.EventArgs e)
{
button.Enabled =false;
button.Enabled =true;
}
とはどういう意味ですか?