none
asp.net&ajaxで開発中でresponse.write()でエラー RRS feed

  • 質問

  • になるのですが、具体的には、UpdatePanelないのtextboxが空欄でボタンを押した時にポップアップを出そうとしています。以下です。

    button_click(object sender, eventargs e)

    {

         string script = "<script type='text/javascript>";

         script += "alert('enter name')";

         script += "</script>";

         Response.Write(script);

    }

    とすると、エラーメッセージが以下の様になります。

    Sys.WebForms.PageRequestManagerParserErrorException

    試しに、UpdatePanelの外で試すと正常に表示されます。そこで、このエラーをキーワードに調べますと、USのフォーラムで自分の状況に近い事は載っていましたが、Response.Writeを使うとおかしくなるような事が書いてあったのですが、詳細を知っている方がいたら教えてください。

    ajaxをいじってまもないので、基本的な事を勉強中です。

    2007年6月18日 1:04

すべての返信

  • 調べられた通りです。簡単に言えば、Ajaxは裏で非同期に特別なフォーマットでサーバーとクライアント間で通信していますが、Response.Writeをすることにより、その特別なフォーマットにゴミが入るためです。以下が詳しいです。

     

    Sys.WebForms.PageRequestManagerParserErrorException - what it is and how to avoid it

    http://weblogs.asp.net/leftslipper/archive/2007/02/26/sys-webforms-pagerequestmanagerparsererrorexception-what-it-is-and-how-to-avoid-it.aspx

    2007年6月18日 1:34
    モデレータ
  • なるほど。リンクしていただいたサイトでもこれに関して熱いディスカッションがなされていましたね。ありがとうございます。という事は、この状況でtextboxが空欄のメッセージは素直にlabelか、あるいはvalidationあたりを使ってエラーメッセージを表示させる方法しかないのでしょうか?つまり、メッセージボックスは表示する事が出来ないということでしょうか。
    2007年6月18日 2:13
  • このような場合は、クライアントスクリプトで PageRequestManager を使って非同期ポストバックのクライアントイベントハンドラで処理します。

     

    ●Default.aspx

    Code Snippet
    <body>
      <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server" >
          <Scripts>
            <asp:ScriptReference Path="Script.js" />
          </Scripts>
        </asp:ScriptManager>
        <div>
          <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
              <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
              <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
              <br />
              <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            </ContentTemplate>
          </asp:UpdatePanel>
        </div>
      </form>
    </body>

     

    ●Script.js

    Code Snippet

    // Sys.Application イベントの追加

    Sys.Application.add_init(AppInit);

     

     

    // Sys.Application.init イベントハンドラ

    function AppInit(sender)

    {

      // PageRequestManagerインスタンスの取得

      var prm = Sys.WebForms.PageRequestManager.getInstance();

     

      if (!prm.get_isInAsyncPostBack())

      {

        // 非同期ポストバックの各イベントハンドラの設定

        prm.add_initializeRequest(InitializeRequest);

      }

    }

     

    // 非同期ポストバックの初期化(initializeRequest)イベントハンドラ

    function InitializeRequest(sender, args)

    {

      var prm = Sys.WebForms.PageRequestManager.getInstance();

      if (!prm.get_isInAsyncPostBack() &&

          args.get_postBackElement().id == "Button1" &&

          $get("TextBox1").value == "")

      {

        args.set_cancel(true);

        alert("テキストを入力してください");

      }

    }

     

     

    これで、お望みの動作になるかと。

     

    あとは、RequiredFieldValidator を使うか、もしくは AJAX Control Toolkit の

    ValidatorCallout エクステンダ

    http://ajax.asp.net/ajaxtoolkit/ValidatorCallout/ValidatorCallout.aspx

    などを使う方法もあります。



     

    2007年6月18日 5:19
  •  chack - Akira Inoue さんからの引用

    このような場合は、クライアントスクリプトで PageRequestManager を使って非同期ポストバックのクライアントイベントハンドラで処理します。

    これで、お望みの動作になるかと。

     

    ~(中略)~

     

    あとは、RequiredFieldValidator を使うか、もしくは AJAX Control Toolkit の

    ValidatorCallout エクステンダ

    http://ajax.asp.net/ajaxtoolkit/ValidatorCallout/ValidatorCallout.aspx

    などを使う方法もあります。

     

    なるほど。大変勉強になります。あと、動作確認が取れている方法として以下がありますが、こういうことをやってもいいのか今のところ確信が持てていません。どうなんでしょう?

     

      ScriptManager.RegisterClientScriptBlock(this.UpdatePanel1, this.GetType(), "enterName", "alert('enter name');", true);

    2007年6月18日 6:02
    モデレータ
  • つまりは、こんな感じでサーバ側で処理させるわけですよね。

     

    Code Snippet

    protected void Button1_Click(object sender, EventArgs e)

    {

      if (string.IsNullOrEmpty(TextBox1.Text))

        ScriptManager.RegisterClientScriptBlock(this.UpdatePanel1, this.GetType(),

                                       "enterName", "alert('enter name');", true);

      else

        Label1.Text = TextBox1.Text;

    }

     

    メリットとしては、サーバ側で TextBox1 の内容によって、例えば DB と照合したり、他の Web サービスと連携したりすることもできて、その結果によってスクリプトの内容を柔軟に変えることもできますから、状況によってはこの方法も使えると思いますよ。

     

    ただ、非同期ポストバックによって必ずサーバ側との通信が発生するわけですから、サーバの負荷などを考慮すると、クライアントサイドで済ませられることは、クライアントで処理したほうが良い訳です。

    (特に AJAX アプリケーションでは、うまく設計しないとサーバ負荷やトラフィックが大きくなりがちですし・・・)

     

    今回の場合は、TextBox1 の値が Empty かどうか?の条件ですから、出来ればクライアントスクリプトで PageRequestManager を使った方法をお勧めします。

     

    その他の場合は、検証内容やサーバ負荷、トラフィックなどを考慮して使い分けるのがベストかと。

    2007年6月18日 6:57
  •  chack - Akira Inoue さんからの引用

    つまりは、こんな感じでサーバ側で処理させるわけですよね。

     

    その通りです。

     

     chack - Akira Inoue さんからの引用

    メリットとしては、サーバ側で TextBox1 の内容によって、例えば DB と照合したり、他の Web サービスと連携したりすることもできて、その結果によってスクリプトの内容を柔軟に変えることもできますから、状況によってはこの方法も使えると思いますよ。

     

    ありがとうございます。Ajaxはまだ本格的に取り組んだことがないので、どうもこのあたりのレンダリングの関係が今一歩不安なんです。やっていいことと悪いことが今一歩整理できていません。下期には本格的にAjaxを扱おうと思っていますので、少しずつですが知識を仕入れているところです。

     

     chack - Akira Inoue さんからの引用

    ただ、非同期ポストバックによって必ずサーバ側との通信が発生するわけですから、サーバの負荷などを考慮すると、クライアントサイドで済ませられることは、クライアントで処理したほうが良い訳です。

    (特に AJAX アプリケーションでは、うまく設計しないとサーバ負荷やトラフィックが大きくなりがちですし・・・)

     

    なるほど。言われてみれば確かにそうですね。Ajaxなのでクライアント処理が基本ということをまず頭に置いて、そこから応用していくのがいいわけですね。Ajaxなので下手にサーバー側でレンダリングを弄ってしまうと、おかしくなるんじゃないかというのが気になっていたので、少し方向性が見えてきた気がします。ありががとうございました。

    2007年6月18日 12:23
    モデレータ