WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

Firefox と PostBackUrl

by WebSurfer 9. March 2019 15:51

ASP.NET Web Forms アプリで、クロスページポストバックにより別のページに遷移し、その後ブラウザの戻るボタンで元のページに戻った場合、ブラウザによってはページングなどの機能が働かなくなる(ページングしたいのにクロスページポストバックされてしまう)という話を書きます。元の話は Teratail のスレッド「DataPagerの挙動について」のものです。

form 要素の action 属性

ASP.NET Web Forms アプリでは form 要素の action 属性に自身のページの url が設定されますので、ボタンクリックなどの操作で form が submit されると自身のページに POST されます。それが ASP.NET での既定の動きで「ポストバック」と呼ばれています。

クロスページポストバックとは、自身のページではなく、他のページに POST することです。それには、Button などに用意されている PostBackUrl プロパティにポスト先のページの url を設定します。それにより、Button が html の input 要素に変換された時、その onclick 属性にクロスページポストバックを行うためのクライアントスクリプトが設定されます。

その Button をクリックすると、まず onclick 要素に設定されたクライアントスクリプトが動いて form 要素の action 属性が PostBackUrl プロパティに設定された url に書き換えられ、その後 form が submit されます。結果、クロスページポストバックが行われるという仕組みになっています。(詳しい説明は上に紹介した Teratail のスレッドにありますのでそちらを見れください)

予期せぬ動きと言うのは何かと言うと、ブラウザによっては、クロスページポストバックで別ページに遷移後、戻るボタンをクリックして元のページを表示した場合、PostBackUrl が設定されてないボタンをクリックしてもクロスページポストバックされてしまうことです。

上に紹介した Teratail のスレッドの話はページャーの話でしたが、ページャーに限らす、ポストバックすることにより動くソート、編集などのボタンクリックでも同様にクロスページポストバックされてしまいます。

この記事を書いた時点で自分が試した限りですが、Firefox 65.0.2 と Safari 5.1.7 がそういう動きをするブラウザでした。IE11, Edge 44.17763.1.0, Chrome 72.0.3626.121, Opera 58.0.3135.90 は期待通り自身のページにポストバックされました。

何故ブラウザによってそういう予期せぬ動きになるかと言うと、ページをキャッシュに保存するタイミングの違いです。

ASP.NET Web Forms アプリのデフォルトのキャッシュコントロール設定では、ブラウザは別のページに遷移する前に元のページをキャッシュに保存します。遷移後、ブラウザの戻るボタンをクリックすると、ブラウザは元のページをキャッシュから取得します。そこのところは Firefox に限らず IE でも Chrome でも同じです。

Firefox, Safari はクロスページポストバックを行うためのクライアントスクリプトが動いて form 要素の action 属性が別ページの url に書き換えられた後キャッシュに保存するのに対し、IE, Edge, Chrome, Opera は書き換える前(即ち、action 属性が自身のページの url の時)にキャッシュするという違いがあります。(ブラウザとしてどちらが正解かはいろいろ議論があるところと思いますが、その話はちょっと置いときます)

この記事の上の画像は Firefox でクロスページポストバックで別ページに遷移後、戻るボタンで元のページを表示し、開発ツールで html ソースの form 要素を表示したものです。action 属性の url は別ページに書き換えられています。

この状態では、PostBackUrl の設定有無にかかわらず、form を submit する操作をすれば、action 属性に設定されたページにクロスページポストバックされてしまうという訳です。

先の記事「PostBackUrl と Page.PreviousPage」にも書きましたが、PostBackUrl(クロスページポストバック)はいろいろ問題が多く、どうしても必要というケースもなさそうですので、使わないようにすべきと思っています。

Tags: ,

ASP.NET

ModalPopup と Firefox の問題

by WebSurfer 6. November 2014 16:46

Ajax Control Toolkit の ModalPopup を Firefox で表示した場合、一旦表示して消した ModalPopup が、別ページに遷移する前に一瞬表示されてしまう問題とその対処方法の紹介です。

遷移前に一瞬表示された ModalPopup

上の画像は、[Show ModalPopup]ボタンをクリック ⇒ ModalPopup が表示される ⇒ ModalPopup 上の[Cancel]ボタンクリック ⇒ ModalPopup が非表示になる ⇒[ブログのページへ]のハイパーリンクをクリックした時、遷移先のページからの応答を待っている時のものです。応答を待っている間、本来表示されてはいけない ModalPopup が表示されてしまっています。

この問題は、ブラウザが Firefox の場合で(現時点での最新バージョン 33.0.2 で確認)、かつ、ModalPopup の DropShadow プロパティが true に設定された場合に発生します。

そのメカニズムは以下の通りです。

DropShadow="true" となっていると、ModalPopup の PopupControlID プロパティに設定した Panel の外側が div 要素で囲われ、その style 属性に "display: none;" が追加 / 削除さることによって ModalPopup の非表示 / 表示が切り替えられます。

たとえ Panel の Style プロパティに "display: none;" を設定しておいても、一旦 ModalPopup を表示するとその設定は削除され、その後 ModalPopup を非表示にしても Panel の "display: none;" は復活しません。(その外側の div 要素に動的に追加される "display: none;" によって非表示になる)

Firefox の場合、ハイパーリンクがクリックされて、遷移先のページを要求に行くとき、Panel の外側の div 要素そのものがなくなるか、その div 要素に設定されている "display: none;" の効果がなくなり、要求を出してから応答が帰ってくるまで Panel が表示されてしまうという感じです。(推測です。実際にどうなっているのかは不明)

ハイパーリンクでなくリダイレクトで遷移しても同じで、GET 要求を出してから応答が戻ってくるまで Panel は表示されてしまいます。

なお、この問題は DropShadow="false" になっていると起こりません。なぜなら、その場合は Panel は div 要素で囲われることはなく、Panel に直接 "display: none;" が追加 / 削除され ModalPopup の非表示 / 表示が切り替えられるからです。

対症療法的ですが、ハイパーリンクの onclick イベントで、ModalPopup (Panel) の style 属性に "display:none;" を設定することでこの問題を回避できます。

そのサンプルコードを以下に書いておきます。また、実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。

<%@ Page Language="C#" %>

<%@ Register Assembly="AjaxControlToolkit" 
    Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>ModalPopup と Firefox</title>
  <style type="text/css">       
    .modalBackground {
      background-color: Gray;
      filter: alpha(opacity=70);
      opacity: 0.7;
    }

    .modalPopup {
      height: 100px;
      width: 250px;
      background-color: White;
      border: solid 2px black;
    }
  </style>
  <script type="text/javascript">
  //<![CDATA[
    function setDisplayNone() {
      var ele = document.getElementById('<%=Panel1.ClientID%>');
      ele.setAttribute('style', 'display: none;');
    }
  //]]>
  </script>
</head>
<body>
  <form id="form1" runat="server">
  <asp:ToolkitScriptManager ID="ToolkitScriptManager1" 
    runat="server">
  </asp:ToolkitScriptManager>

  <h1>ModalPopup と Firefox</h1>

  <asp:Button ID="Button1" 
    runat="server" 
    Text="Show ModalPopup"/>    
  <br />
  <asp:HyperLink ID="HyperLink1" 
    runat="server" 
    NavigateUrl="~/Default.aspx">
    ブログのページへ
  </asp:HyperLink>
  <br />
  <asp:HyperLink ID="HyperLink2" 
    runat="server" 
    NavigateUrl="~/Default.aspx"
    onclick="setDisplayNone();">
    ブログのページへ(display:none 設定)
  </asp:HyperLink>

  <asp:ModalPopupExtender ID="ModalPopupExtender1" 
    runat="server"
    TargetControlID="Button1" 
    PopupControlID="Panel1"        
    BackgroundCssClass="modalBackground" 
    DropShadow="True"
    CancelControlID="CancelButton">
  </asp:ModalPopupExtender>

  <asp:Panel ID="Panel1" 
    runat="server"  
    Style="display: none" 
    CssClass="modalPopup">        
    <p style="text-align: center;">ModalPopup</p>
    <p style="text-align: center;">
      <asp:Button ID="CancelButton" 
        runat="server" Text="Cancel" />
    </p>
  </asp:Panel>
  </form>
</body>
</html>

Tags: , ,

AJAX

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  November 2019  >>
MoTuWeThFrSaSu
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

View posts in large calendar