ASP.NET Web Forms アプリで jQuery Ajax を使ってポストバックの際にサーバー側で行われる処理が可能かどうかを事前に調べ、可能と分かったら JavaScript で Button クリックしてポストバックする、可能ではないと分かった場合はポストバックせずメッセージを表示してユーザーに知らせるという話です。

元の話は Teratail のスレッド「asp:button 押下前にサーバサイドが応答しているか確認したいためPingのようなことを行いたい」のものです。実際のそのような検証が必要なケースはあまりなさそうですが、せっかく考えた話ですし jQuery Ajax の timeout の使い方が今後の参考になるかもしれないと思ったので備忘録として書いておくことにしました。
Button クリックでポストバックしてサーバー側でユーザーが送信したデータを受けて、データベースサーバーにクエリを投げる等の処理をすることはよくあると思います。
その際、Button クリックでいきなりポストバックするのではなく、その前に jQuery Ajax を使って事前にサーバー側での処理が可能かどうかを調べるというストーリーです。
(いきなりポストバックしても結果をきちんとユーザーに知らせることはできるし、やりすぎるとサーバーに無駄な負荷を増やすし軽くすると検証の意味が薄れるということで、そのような検証の必要性は低いとは思いますがそこは置いときます)
jQuery Ajax で呼び出してサーバー側で事前検証を行う HTTP ジェネリックハンドラを作ります。以下のコードがそのサンプルです。
HTTP ジェネリックハンドラ Handler1.ashx
using System.Web;
namespace WebForms1
{
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Button クリックでポストバックされた時にサーバー
// で行われる処理が可能か事前に検証する。処理に最
// 長 3 秒かかるとして、ここでは単純に 3 待つ
System.Threading.Thread.Sleep(3000);
// 検証に成功したら "検証成功" という文字列を返す
var validationResult = "検証成功";
context.Response.ContentType = "text/plain";
context.Response.Write(validationResult);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
上の Handler1.ashx を jQuery Ajax を使って呼び出します。Handler1.ashx は検証に成功すると "検証成功" という文字列を返すので、それを受けたら JavaScript で Button をクリックしてポストバックします。その結果がこの記事の一番上にある画像です。
Handler1.ashx を呼び出す JavaScript を含む Web Form ページのサンプルコードは以下の通りです。
WebForm1.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebForms1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script src="Scripts/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("#btnSec").on("click", function () {
$.ajax({
type: "get",
url: "Handler1.ashx",
timeout: 5000
}).done(function (data) {
// 呼び出し先 Handler1.ashx で検証が成功すると "検証成功"
// という文字列が返ってきて引数 data に代入される
if (data == "検証成功") {
var hiddenbutton = document.getElementById("Button1");
// Button をクリック
hiddenbutton.click();
} else {
$("#Label1").text("処理できません - 検証結果 NG");
}
}).fail(function (jqXHR, textStatus, errorThrown) {
$("#Label1").text("処理できません - " + textStatus);
});
});
});
</script>
<style type="text/css">
.style1
{
display: none;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>WebForm1 - jQuery.Ajax を使っての事前検証</h2>
<input id="btnSec" type="button" value="反映" />
<%--ポストバックを行う Button コントロール。上の style1 で
隠しボタンに設定。クリックは JavaScript で行う。クリ
ックされるとポストバックが発生し、サーバー側のイベント
ハンドラ ClickBtnSection で必要な処理が行われる--%>
<asp:Button ID="Button1" runat="server"
OnClick="ClickBtnSection" CssClass="style1" />
<asp:Label ID="Label1" runat="server">
Label1 初期値
</asp:Label>
</div>
</form>
</body>
</html>
WebForm1.aspx.cs
using System;
namespace WebForms1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void ClickBtnSection(object sender, EventArgs e)
{
// サーバー側での必要な処理
Label1.Text = "Button1 がクリックされました";
}
}
}
Handler1.ashx を呼び出して、そこでの処理中にサーバーエラーが発生した場合は以下のようになります。

Handler1.ashx を呼び出した後、jQuery Ajax の timeout オプションに設定した時間(上のコード例では 5 秒)待っても応答が返ってこない場合は以下のようになります。

Handler1.ashx から帰ってきた文字列が "検証成功" 以外の場合は(実際にそういうケースはないかもしれませんが)以下のようになります。
