質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Firefox

Mozilla Foundationによって作られた無料、オープンソース、クロスプラットフォームなウェブブラウザ

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

2回答

5462閲覧

DataPagerの挙動について

tryCSharp

総合スコア29

Firefox

Mozilla Foundationによって作られた無料、オープンソース、クロスプラットフォームなウェブブラウザ

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2019/02/27 07:59

編集2019/02/27 22:41

前提・実現したいこと

いつもお世話になっております。

DataPager付のListViewを持つWebForm1とLabelを持つWebForm2があります。
WebForm1のListViewはボタンを持ち、PostBackUrlにはWebForm2を設定しています。

WebForm1のListViewのボタンを押し、WebForm2へ遷移後、ブラウザ(Firefox)の戻るボタンを押し、WebForm1へ戻ります。
その後、WebForm1のDataPagerで任意のページを選択するとWebForm2を参照してしまいエラーが発生します。

なお、Internet ExplolerとChromeでは発生しません。また、ローカルでデバッグ時にも発生しません。

発生している問題・エラーメッセージ

'/FindControlTest' アプリケーションでサーバー エラーが発生しました。 ランタイム エラー 説明: サーバーでアプリケーション エラーが発生しました。このアプリケーションの現在のカスタム エラー設定では、セキュリティ上の理由により、アプリケーション エラーの詳細をリモート表示できません。ただし、ローカル サーバー コンピューターで実行されているブラウザーで表示することはできます。 詳細: このエラー メッセージの詳細をリモート コンピューターで表示できるようにするには、現在の Web アプリケーションのルート ディレクトリにある "web.config" 構成ファイル内に、<customErrors> タグを作成してください。その後で、この <customErrors> タグで "mode" 属性を "off" に設定してください。 <!-- Web.Config 構成ファイル --> <configuration> <system.web> <customErrors mode="Off"/> </system.web> </configuration> メモ: 現在表示されているエラー ページをカスタム エラー ページに変更するには、アプリケーションの <customErrors> 構成タグの "defaultRedirect" 属性をカスタム エラー ページ URL に置き換えます。 <!-- Web.Config 構成ファイル --> <configuration> <system.web> <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/> </system.web> </configuration>

該当のソースコード

WebForm1

aspx

1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="FindControlTest.WebForm1" %> 2 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4 5<html xmlns="http://www.w3.org/1999/xhtml"> 6<head runat="server"> 7 <title></title> 8</head> 9<body> 10 <form id="form1" runat="server"> 11 <div> 12 <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" 13 DataSourceID="SqlDataSource1"> 14 <AlternatingItemTemplate> 15 <tr style=""> 16 <td> 17 <asp:Button ID="Button1" runat="server" Text="ジャンプ" CommandName="Select" PostBackUrl="WebForm2.aspx" /> 18 <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' /> 19 </td> 20 </tr> 21 </AlternatingItemTemplate> 22 <EditItemTemplate> 23 <tr style=""> 24 <td> 25 <asp:Button ID="UpdateButton" runat="server" CommandName="Update" Text="更新" /> 26 <asp:Button ID="CancelButton" runat="server" CommandName="Cancel" 27 Text="キャンセル" /> 28 </td> 29 <td> 30 <asp:Label ID="IDLabel1" runat="server" Text='<%# Eval("ID") %>' /> 31 </td> 32 </tr> 33 </EditItemTemplate> 34 <EmptyDataTemplate> 35 <table runat="server" style=""> 36 <tr> 37 <td> 38 データは返されませんでした。</td> 39 </tr> 40 </table> 41 </EmptyDataTemplate> 42 <InsertItemTemplate> 43 <tr style=""> 44 <td> 45 <asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="挿入" /> 46 <asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="クリア" /> 47 </td> 48 <td> 49 <asp:TextBox ID="IDTextBox" runat="server" Text='<%# Bind("ID") %>' /> 50 </td> 51 </tr> 52 </InsertItemTemplate> 53 <ItemTemplate> 54 <tr style=""> 55 <td> 56 <asp:Button ID="Button1" runat="server" Text="ジャンプ" CommandName="Select" PostBackUrl="WebForm2.aspx" /> 57 <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' /> 58 </td> 59 </tr> 60 </ItemTemplate> 61 <LayoutTemplate> 62 <table runat="server"> 63 <tr runat="server"> 64 <td runat="server"> 65 <table ID="itemPlaceholderContainer" runat="server" border="0" style=""> 66 <tr runat="server" style=""> 67 <th runat="server"> 68 &nbsp;</th> 69 <th runat="server"> 70 ID</th> 71 </tr> 72 <tr ID="itemPlaceholder" runat="server"> 73 </tr> 74 </table> 75 </td> 76 </tr> 77 <tr runat="server"> 78 <td runat="server" style=""> 79 <asp:DataPager ID="DataPager1" runat="server"> 80 <Fields> 81 <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" 82 ShowNextPageButton="False" ShowPreviousPageButton="False" /> 83 <asp:NumericPagerField /> 84 <asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="True" 85 ShowNextPageButton="False" ShowPreviousPageButton="False" /> 86 </Fields> 87 </asp:DataPager> 88 </td> 89 </tr> 90 </table> 91 </LayoutTemplate> 92 <SelectedItemTemplate> 93 <tr style=""> 94 <td> 95 <asp:Button ID="Button1" runat="server" Text="ジャンプ" CommandName="Select" PostBackUrl="WebForm2.aspx" /> 96 <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' /> 97 </td> 98 </tr> 99 </SelectedItemTemplate> 100 </asp:ListView> 101 <asp:SqlDataSource ID="SqlDataSource1" runat="server" 102 ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 103 ProviderName="<%$ ConnectionStrings:ConnectionString.ProviderName %>" 104 SelectCommand="SELECT &quot;ID&quot; FROM &quot;TABLE1&quot;"> 105 </asp:SqlDataSource> 106 </div> 107 </form> 108</body> 109</html>

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Web; 5using System.Web.UI; 6using System.Web.UI.WebControls; 7 8namespace FindControlTest 9{ 10 public partial class WebForm1 : System.Web.UI.Page 11 { 12 protected void Page_Load(object sender, EventArgs e) 13 { 14 15 } 16 } 17}

WebForm2

aspx

1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="FindControlTest.WebForm2" %> 2 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4 5<html xmlns="http://www.w3.org/1999/xhtml"> 6<head runat="server"> 7 <title></title> 8</head> 9<body> 10 <form id="form1" runat="server"> 11 <div> 12 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> 13 </div> 14 </form> 15</body> 16</html>

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Web; 5using System.Web.UI; 6using System.Web.UI.WebControls; 7 8namespace FindControlTest 9{ 10 public partial class WebForm2 : System.Web.UI.Page 11 { 12 protected void Page_Load(object sender, EventArgs e) 13 { 14 if (!IsPostBack) 15 { 16 if (Page.PreviousPage != null) 17 { 18 ListView listview = (ListView)Page.PreviousPage.FindControl("ListView1"); 19 Label1.Text = listview.SelectedDataKey[0].ToString(); 20 } 21 } 22 } 23 } 24}

試したこと

Internet Exploler、Chromeでは発生しませんでした。

補足情報(FW/ツールのバージョンなど)

Oracle: Oracle 11g
サーバーOS:Windows Server 2012
クライアントOS:Windows7
.NET:4.0
サーバーIIS:8.0
クライアントIIS:10.0 Express
Visual Studio:2015 Express for Web

追記(Web.config編集後のエラー)

'/FindControlTest' アプリケーションでサーバー エラーが発生しました。 オブジェクト参照がオブジェクト インスタンスに設定されていません。 説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。 例外の詳細: System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。 ソース エラー: 現在の Web 要求の実行中にハンドルされていない例外が生成されました。障害の原因および発生場所に関する情報については、下の例外スタック トレースを使って確認できます。 スタック トレース: [NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。] FindControlTest.WebForm2.Page_Load(Object sender, EventArgs e) +165 System.Web.UI.Control.LoadRecursive() +70 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3177 バージョン情報: Microsoft .NET Framework バージョン:4.0.30319; ASP.NET バージョン:4.0.30319.17929

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/02/27 09:12

エラーメッセージにあるとおり「現在の Web アプリケーションのルート ディレクトリにある "web.config" 構成ファイル内に、<customErrors> タグを作成してください。その後で、この <customErrors> タグで "mode" 属性を "off" に設定してください。」として、詳細エラーメッセージを取得してアップしてください。
退会済みユーザー

退会済みユーザー

2019/02/27 09:20 編集

PostBackUrl(クロスページポストバック)はいろいろ問題が多く、絶対に使わないようにすべきと思いますが、どうしても使わなければならない理由があるのですか? その使用を避ける方向で検討するのをまず第一にすべきと思います。そもそも、ブラウザの「戻る」ボタンを使われても破綻しないようにするのはかなり難しいのですが、クロスページポストバックとか使われたら何が何だか・・・と言う感じです。IE, Chrome で問題なかったのは運が良かっただけという気がします。
tryCSharp

2019/02/27 10:12

コメントありがとうございます。 1つ目のコメントに対する対応は明日させてください。 でもPostBackUrlは使わないようにすべきとのことで他の方法を検討しようと思います。
tryCSharp

2019/02/27 22:42

Web.config編集後のエラーを追記しました。
退会済みユーザー

退会済みユーザー

2019/02/27 23:58

運用環境(すなわち IIS で実行)で、ブラウザが Firefox の場合に(IE, Chrome は OK)そういうサーバーエラーが出るのですよね・・・ 自分的には奇々怪々としか言いようがないです。自分の環境で調べてみます。少し時間をください。
guest

回答2

0

ベストアンサー

自分の PC の Windows 10 Pro 64-bit の IIS10 で動く .NET 4.6.1 の ASP.NET Web Forms アプリで試してみましたが、自分の環境にある Firefox 65.0.1 で質問者さんと同じ問題が再現できました。IE11、Chrome 72.0.3626.119 では問題ありません。

原因は、Firefox の戻るボタンで WebForm2 から WebForm1 に戻った後、ページャーのボタンをクリックすると何故か WebForm2 へクロスページポストバックがかかってしまい、その場合は WebForm2 のコードビハインドの中にある listview.SelectedDataKey が null になるからでした。

WebForm1 のページャのボタンは、以下のように NumericPagerField が a 要素、NextPreviousPagerField が input type="submit" となっています。これは Firefox, IE, Chrome いずれも同じです。

<a href="javascript:__doPostBack('ListView1$DataPager1$ctl01$ctl02','')">3</a> <input type="submit" name="ListView1$DataPager1$ctl02$ctl00" value="最後">

なので、クリックすれば普通のブラウザの動きとしては WebForm1 にポストバックするはずです。

しかしながら、Firefox の戻るボタンで WebForm2 から WebForm1 に戻った後は、ページャークリックで何故か WebForm2 にクロスページポストバックがかかってしまいます。(IE, Chrome は期待通り WebForm1 にポストバックがかかるので問題なしです)

そのクロスページポストバックの時は WebForm2 のコードビハインドの中の listview.SelectedDataKey が null になるので NullReferenceException がスローされます。

なぜ Firefox だけそういう訳の分からない奇々怪々なことになるのかは調べる気力がわいてこないので分かりません。

上の質問に対するコメントにも書きましたが、PostBackUrl(クロスページポストバック)はいろいろ問題が多く、個人的には絶対に使わないようにすべきと思っています。

解決策はクロスページポストバックの使用を避ける方向で検討すべきと思います。たとえば、WebForm1 のボタンクリックのイベントハンドラで WebForm2 へリダイレクトする。ID は Session またはクエリ文字列で渡すというように。

【追記】

evin101 さんの回答に対する 2019/03/01 10:34 の私のコメントで「調べた画像を私の回答欄に貼っておきます」と書きましたが、その画像を貼って若干の説明を追記しておきます。

:画像のページの名前は WebForm1 ⇒ 0065-PostBackUrlFormA、WebForm2 ⇒ 0065-PostBackUrlFormB に変えてますので注意してください。

ブラウザの「戻る」ボタンで目的のページをキャッシュから取得するのは、ASP.NET Web Forms アプリのデフォルトの設定では、IE も Chrome も Firefox も同じです。

下の画像は Firefox 65.0.1 と IE11 で、(1) 質問で言う WebForm1 を表示、(2)[ジャンプ]ボタンクリックで WebForm2 へクロスページポストバック、(3) ブラウザの[戻る]ボタンで WebForm1 に戻すという操作の要求・応答を Fiddler で見たものです。

イメージ説明

上の画像の #22 が Firefox での (1)、#27 が (2) です。画像の #59 が IE での (1)、#64 が (2) です。(3) の操作では Firefox も IE も要求は出ていません。画面は WebForm1 に戻るのでキャッシュから取得しています。

Firefox で (3) の操作の後にキャッシュから取得して表示された html ソースを見ると、以下の画像のように form 要素の action 属性が (2) でクロスページポストバックを行った先に(質問者さんの場合 WebForm2、私の場合は 0065-PostBackUrlFormB)に書き換えられてます。

イメージ説明

これが Firefox を使った場合に起こる問題の原因です。IE, Chrome の場合は書き換えられるようなことはありません。

なぜ Firefox でこんなことになるのかは調べてないので分かりません。WebFrom1 の初期画面からのポスト先が WebForm2 だったから書き換えてやろうという「小さな親切大きなお世話」ってやつかもしれませんね。

クロスページポストバックを使わないで、普通に WebForm1 のボタンクリックのイベントハンドラで WebForm2 へリダイレクトし、ID は Session またはクエリ文字列で渡すというようにした場合はどうなんでしょう? たぶん問題ないと思いますが、未確認です。

【追記2】

くどいようですが、原因についてさらに調べましたのでその結果を追記しておきます。興味がありましたら見ていただけると幸いです。

自分が調べた限りですが、要するに、IE, Chrome と Firefox ではキャッシュするタイミングに違いがあって、IE, Chrome は初期画面の、Firefox はユーザーが操作して JavaScript が動いた後の html ソースをキャッシュするという違いが今回の問題の原因になっているようです。

詳しくは以下の通りです。

クロスページポストバックを行うために Button に PostBackUrl="WebForm2.aspx" と設定すると、その Button からレンダリングされる input 要素は以下のようになります。type 属性が submit であることと onclick 属性に設定されたスクリプトに注意してください。

<input name="ListView1$ctrl0$Button1" id="ListView1_Button1_0" onclick='javascript:WebForm_DoPostBackWithOptions( new WebForm_PostBackOptions("ListView1$ctrl0$Button1", "", false, "", "WebForm2.aspx", false, false))' type="submit" value="ジャンプ">

onclick 属性に設定されている WebForm_DoPostBackWithOptions メソッドとその引数の WebForm_PostBackOptions は、HTTP ハンドラ WebResource.axd を使って埋め込みリソースから取得される js ファイルに含まれていて、以下の通りです。

function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit) { this.eventTarget = eventTarget; this.eventArgument = eventArgument; this.validation = validation; this.validationGroup = validationGroup; this.actionUrl = actionUrl; this.trackFocus = trackFocus; this.clientSubmit = clientSubmit; } function WebForm_DoPostBackWithOptions(options) { var validationResult = true; if (options.validation) { if (typeof(Page_ClientValidate) == 'function') { validationResult = Page_ClientValidate(options.validationGroup); } } if (validationResult) { if ((typeof(options.actionUrl) != "undefined") && (options.actionUrl != null) && (options.actionUrl.length > 0)) { theForm.action = options.actionUrl; } if (options.trackFocus) { var lastFocus = theForm.elements["__LASTFOCUS"]; if ((typeof(lastFocus) != "undefined") && (lastFocus != null)) { if (typeof(document.activeElement) == "undefined") { lastFocus.value = options.eventTarget; } else { var active = document.activeElement; if ((typeof(active) != "undefined") && (active != null)) { if ((typeof(active.id) != "undefined") && (active.id != null) && (active.id.length > 0)) { lastFocus.value = active.id; } else if (typeof(active.name) != "undefined") { lastFocus.value = active.name; } } } } } } if (options.clientSubmit) { __doPostBack(options.eventTarget, options.eventArgument); } }

validation, trackFocus, clientSubmit は、上のボタンの onclick 属性に設定されたスクリプトで false に設定されるので、結局 theForm.action = options.actionUrl; だけの動作とななります。(即ち、form 要素の action 属性が WebForm2.aspx に書き換えられるだけ。theForm はインラインスクリプトとして定義されます)

ボタンは input type="submit" なので、その後 form が WebForm2.aspx に submit されます。

Firefox ではその時点での WebForm1.aspx の html ソースがキャッシュされるようで、それが、evin101 さんの言われる「JavaScript オブジェクト状態の保存」ということでしょうか・・・

投稿2019/02/28 02:53

編集2019/03/02 03:27
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tryCSharp

2019/02/28 03:19 編集

ご回答ありがとうございます。 検証までしていただき申し訳ございません。 PostBackUrlは使わない方向で考えてみます。
tryCSharp

2019/03/02 09:41

色々調べていただいてありがとうございます。 技術不足でお調べいただいた事になんのコメントも出来ませんが拝見させて頂いております。
guest

0

すでにベストアンサーがついていますが、原因に心当たりがあったので検証してみました。

原因はおそらくbfcacheという機能が関わっています。
~~この機能は「戻る」「進む」ボタンを使用した場合に、メモリ内にキャッシュされたページを表示する機能です。
~~
bfcache について覚えて帰ってもらいます。(転載) - oogatta のブログ

上記のブログによると、戻るボタンを使用した場合に、bfcacheにより以下のような挙動をします。

  • onload ハンドラのスキップ
  • JavaScript オブジェクト状態の保存

一方で、PostBackUrlを使用したクロスページポストバックを行った場合、以下のような動作をします。

  1. ボタンクリック等のクライアントイベント時、WebResouce.axdにより提供されるメソッドを呼び出す。
  2. 上記メソッドにより、form要素のaction属性をポストバック先のページに書き換える。
  3. 2.のページにPOSTする。

クロスページポストバックを行って「戻る」ボタンで戻った場合、上記2.の処理の結果がbfcacheの **「JavaScript オブジェクト状態の保存」**によって残ったままになるため、通常のポストバックであるにもかかわらず別のページにポストバックしてしまうということになります。

回避策としてbfcacheを無効化やbfcacheの使用を検出して対策するといった方法が上記ブログにもありますが、私もSurferOnWwwさんの意見と同様でクロスページポストバックを避ける方向が良いのではないかと考えます。

投稿2019/02/28 13:57

編集2019/03/01 01:58
evin101

総合スコア92

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tryCSharp

2019/02/28 15:26

ご回答ありがとうございます。 bfcacheという機能があるのですね。 勉強になります。
退会済みユーザー

退会済みユーザー

2019/03/01 01:34

ブラウザの「戻る」ボタンで目的のページをキャッシュから取得するのは、ASP.NET Web Forms アプリのデフォルトの設定では、IE も Chrome も Firefox も同じです。 ちょっと調べてみましたが、Firefox の場合「戻る」ボタンで取得するページの form 要素の action 属性が WebForm2 に書き換えられてしまうのが諸悪の根源(?)でした。 調べた画像を私の回答欄に貼っておきます。
evin101

2019/03/01 01:59

>ブラウザの「戻る」ボタンで目的のページをキャッシュから取得するのは、ASP.NET Web Forms アプリのデフォルトの設定では、IE も Chrome も Firefox も同じです。 https://developer.mozilla.org/ja/docs/Using_Firefox_1.5_caching 上記のページにある「メモリ内にキャッシュ」という表現を使って他のブラウザとちょっと違うということを言いたかったのですが、ちょっと紛らわしかったので回答を修正しました。
退会済みユーザー

退会済みユーザー

2019/03/01 02:24

回答の 1. 2. 3. の説明あたりもちょっと違うような気がします。私の回答欄に詳細を追記しますので、それを見ていただければと思います。
退会済みユーザー

退会済みユーザー

2019/03/02 03:26 編集

上のコメントで、 > 回答の 1. 2. 3. の説明あたりもちょっと違うような気がします。 と書きましたが 1. ~ 3. はその通りでした。すみません。 もう少し調べてみましたが、IE, Chrome, Firefox いずれも 1. ~ 3. の動きをします。問題は IE, Chrome は初期画面の状態でキャッシュするのに対し、Forefox は 2. の状態、即ち form 要素の action 属性が WebForm2 に書き換えられた状態でキャッシュするということのようです。 要するに Firefox がキャッシュするタイミングが今回の問題の原因になっているのですが、それが、evin101 さんの言われる「JavaScript オブジェクト状態の保存」ということなのでしょうか・・・ くどいようですが、自分の回答欄に調べた結果を追記しておきますので、興味がありましたら見てください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問