[ ASP.NET ] Windows アプリのようなメッセージボックス制御

Pocket

ここでは ASP.NET の Web アプリケーションで Windows フォームアプリケーションのようなメッセージボックス制御を行うサンプルを掲載しています。

ここで説明するメッセージボックスの制御には、Javascript を使用してポストバックを行っています。Javascript からフォームに対してサブミット ( ポストバック ) しているだけですので技術的に難しいことはありません。

今回は、以下のような一般的(?)な状況を例に考えることとします。

  1. 複数の入力項目を持つWebフォームで登録ボタンクリックでデータベースへ登録する
  2.  入力された情報がデータベース上に存在しない場合はそのまま登録する
  3.  入力された情報が既にデータベース上に存在すれば確認ダイアログを表示する
  4.  OKボタンがクリックされた場合にのみ、その情報を上書きし、キャンセルボタンの場合は何もしない

Windows アプリケーションでは容易ですが、ASP.NET のような Web アプリではサーバとブラウザでそれぞれ実行順序を制御する必要があるので、悩むことも多いです。

[ ポイント ]

  • データベースへの問い合わせはWebサーバで行う
  • 確認ダイアログはブラウザ上で出力させる
  • JavaScript からポストバックを行う

メッセージボックス制御サンプル(枠組のみ)

メッセージボックス制御のサンプルコードになります。なお、データベースへの登録処理などは本題ではありませんので記述していません。詳細はサンプルコード中のコメントを参照ください。

ASPX

    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Button" />
    </div>
    </form>

VB.NET

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If IsPostBack Then

            'Javascriptからのsubmitはポストバックとして認識される

            ' 上書きする(OK)ボタンがクリックされた場合
            Dim update As String = Page.Request.QueryString.Get("update")
            If (update = "true") Then

                '----------------------------------------------
                ' TODO:ここで、データを上書きする処理を行う
                '----------------------------------------------

                '(後始末)
                ' 次のポストバックでこのルートを通らないようにするために
                ' アップデートのために追加したGET パラメータ(update)をaction属性から除去する
                Dim formid As String = Me.Form.ClientID
                Dim cScript As String = formid + ".action = ""Default.aspx"";"

                'JavaScriptの埋め込み(画面表示前に実行させる)
                ClientScript.RegisterClientScriptBlock(Me.GetType(), "clientscript", cScript, True)

            End If

        End If

    End Sub

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click

        Dim confirm As Boolean

        '--------------------------------------------------------
        ' TODO:ここにデータベースに存在するか確認する処理を記述する
        '--------------------------------------------------------

        If (True) Then
            ' 確認ダイアログを出力させる
            confirm = True
        Else
            '確認ダイアログを出力させない
            confirm = False
        End If

        'マスターページを使っている場合、formタグのidがaspnetFormとなるので、
        '確実に取得するためには、Form.ClientIDプロパティからIDを取得する
        Dim formid As String = Me.Form.ClientID

        If (confirm) Then
            ' 確認ダイアログを出力するスクリプト
            ' POST先は自分自身(Default.aspx)
            Dim sScript As String = "if(confirm(""上書きしますか?"")){ " + _
                                        formid + ".method = ""post"";" + _
                                        formid + ".action = ""Default.aspx?update=true"";" + _
                                        formid + ".submit();" + _
                                    "}"
            'JavaScriptの埋め込み
            ClientScript.RegisterStartupScript(Me.GetType(), "startup", sScript, True)

            ' ClientScript.RegisterStartupScriptメソッドで登録した場合、ブラウザでの描画完了後に
            ' 登録したJavaScriptが実行される
            '
            ' ここでは、OKボタンが押されたことをGETパラメーター(update)で通知する

        Else

            '--------------------------------------------------------
            ' TODO:ここに、データを登録する処理を記述する
            '--------------------------------------------------------

        End If

    End Sub

C#

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            // Javascriptからのsubmitはポストバックとして認識される

            // ここで、GETパラメーター(update)がTrueの場合には、フォーム上のデータを
            // データベース上に上書きする処理を記述する

            // 上書きする(OK)ボタンがクリックされた場合
            string update = Page.Request.QueryString.Get("update");
            if (update == "true") {
            
               //-------------------------------------------------
               // TODO:ここで、データを上書きする処理を行う
               //-------------------------------------------------
 
                //(後始末)
                // 次のポストバックでこのルートを通らないようにするために
                // アップデートのために追加したGET パラメータ(update)をaction属性から除去する
                string formid = this.Form.ClientID;
                string cScript = formid + ".action = \"Default.aspx\";";

                // JavaScriptの埋め込み(画面表示前に実行させる)
                ClientScript.RegisterClientScriptBlock(this.GetType(), "clientscript", cScript, true);
            }

        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Boolean confirm;

        //-------------------------------------------------
        // TODO:ここにデータベースに存在するか確認する処理を記述する
        //-------------------------------------------------

        if (true) {
            // 確認ダイアログを出力させる
            confirm = true;
        } else {
            // 確認ダイアログを出力させない
            confirm = false;
        }

        // マスターページを使っている場合、formタグのidがaspnetFormとなるので、
        // 確実に取得するためには、Form.ClientIDプロパティからIDを取得する
        string formid = this.Form.ClientID;

        if (confirm) {
            // 確認ダイアログを出力するスクリプト
            string sScript = "if(confirm(\"上書きしますか?\")){ " + 
                                     formid + ".method = \"post\";" + 
                                     formid + ".action = \"Default.aspx?update=true\";" + 
                                     formid + ".submit();" + 
                                 "}else{" + 
                                     "" + 
                                 "}";

            // JavaScriptの埋め込み
            ClientScript.RegisterStartupScript(this.GetType(), "startup", sScript, true);

            // ClientScript.RegisterStartupScriptメソッドで登録した場合、ブラウザでの描画完了後に
            // 登録したJavaScriptが実行される
            //
            // OKがクリックされるとGETパラメーター(update)を付けて、ポストバックする

        } else {
        
            //-------------------------------------------------
            // TODO:ここに、データを登録する処理を記述する
            //-------------------------------------------------
        }
    }

F5 などで再表示を行った場合の問題点

今回のサンプルでは上書きするかの判断を GET パラメータ ( update ) で行っていますが、 Page_Load イベントで上書き処理を行った状態で再表示 ( F5 ) を行うと、再度上書き処理が行われてしまいます ( GET パラメーターも再度送られる )。

対応方法は色々あると思いますが、解決手段の1つとして、Page_Load イベントで更新登録したあとでClientScript.RegisterClientScriptBlock で スクリプトを埋め込む代わりに、Response.Redirect ( URL には Get パラメーターをつけない ) で自分自身にリダイレクトさせる方法があります。クライアントとブラウザ間でやり取りの回数が増えますが、簡単な対処方法です。

ポストバックにしたくないとき

今回は Javascript からポストバックするようにしましたが、” キャンセル ” が選択されたときに、単にページ遷移する場合には form.submit ではなく、location.href を使用できます。

location.href = “Default.aspx”;

ASP.NET とは関係なく、Javascript の話です


おすすめコンテンツはこちら

Pocket

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>