[SSRS] Response.Redirect でページ遷移すると画像が見えなくなる(deleteAfterServicing パラメーター)

横井 羽衣子(よこい ういこ)
SQL Developer Support Engineer

皆様ごきげんよう。今日は、Chart コントロールの再表示の問題と、簡単な切り分け方法についてご案内いたします。

【今日のお題】 ASP.NET Web アプリケーションで、chart コントロールを利用し、レポートからデータを取得している。 chart 表示ページから別のページに遷移し、Response.Redirect で遷移元のページに移動すると、複数ある chart の画像のうち、いくつかがランダムに表示されない状態 [x] になることがある。 image← こんな感じ ただし、例外は発生しておらず、イベント ハンドラに渡されたパスも NULL ではなく、データがあるように見える。 なお、静的リンクや、Server.Transfer などを使うと問題なく表示される。また F5 を押し、リフレッシュなどすると表示される。なぜこうした状況になるか。

   

1. 対処 : deleteAfterServicing パラメーターを明示的に False にする

Chart コントロールを追加すると、Web.config ファイルに "ChartImageHandler" として自動的に ChartHttpHandler が登録されます。対処としては、このChartHttpHandler のvalue 属性で deleteAfterServicing パラメーターを false にしてあげることになります。

例) <add key="ChartImageHandler" value="storage=file;timeout=20;url=~/Files/;deleteAfterServicing=false" />

このパラメーターを明示的に指定しない場合は既定値 True となりますが、この値が有効な状態においては、Chart などのイメージはダウンロードされた後に削除されることになります
そのため、表示されない状態が発生します。

この問題のポイントは、Response.Redirect で遷移を行うという点です。

Server.Transfer や、静的リンクで遷移すると表示されるのは、リクエストの再要求を行わず、前のページの情報をそのまま使うためですが、Response.Redirect では、以下のような動きになります。

1. Chart を描画する(ページ描画中にイメージが生成され、Web サーバのディスクに保存される。保存されたイメージはクライアントにダウンロードされる)
2. 別ページに一度遷移する
3. Response.Redirect で 1. の Chart を使用しているページに遷移する(ページ描画中に再度イメージのダウンロードを試みる)

この動作において、deleteAfterServicing が既定値 True であると、上記のフェーズ 1 ではすでに Chart の実際のイメージのダウンロードが完了していますので、Web サーバのディスク上に保存されたイメージはファイルの参照元から削除されることになります。
そのため、フェーズ 3. で再度同じ Chart イメージをダウンロードしようとした場合、Chart の実イメージが存在することは保証されません。F5 を押すと描画されるのは、実イメージが再生成されるためです。(よーくみると、画像の URL が変わります)
deleteAfterServicing を False にすると、再度リクエスト要求があってもイメージを残しておくことが可能になります。

2. deleteAfterServicing = false の場合画像競合しないか

製品上ファイル上書きなどの競合、セキュリティも保護されるよう設計されています。

イメージ ファイルの管理 https://msdn.microsoft.com/ja-jp/library/dd456629.aspx 既定では、ImageStorageMode プロパティは UseHttpHandler に設定されます。この設定では、表示されたグラフ イメージの管理に、Web.config ファイルに登録されている ChartHttpHandler が使用されます。 次の場合にグラフ HTTP ハンドラーを利用できます。 • サーバー クラスターまたは複数プロセス サイトで、ファイル上書きの競合を防ぎます。 • 他のユーザーが表示しているグラフ イメージをダウンロードしないように、表示されたグラフ イメージのセキュリティを保護します。 • メモリや他のストレージ オプション (Microsoft SQL Server など) にイメージ ファイルを保存することで、ディスク操作を減らします。    

  

3. 参考ドキュメント

グラフ イメージの表示 https://msdn.microsoft.com/ja-jp/library/dd456682.aspx 既定で、ASP.NET のグラフ コントロールでは、この方法を使用してグラフ イメージを表示します。 これは最も単純な表示方法です。 表示されたグラフ イメージはメモリまたは一時ファイルにキャッシュされます。 そのため、頻繁にアクセスされる静的なデータおよび外観を持つグラフの場合、パフォーマンスが改善されます。 使用法 RenderType プロパティを ImageTag に設定します。 表示されたイメージを管理する方法を指定できます。 詳細については、「イメージ ファイルの管理」を参照してください。    
イメージ ファイルの管理 https://msdn.microsoft.com/ja-jp/library/dd456629.aspx deleteAfterServicing クライアントからのダウンロードを正常終了した後に、イメージを削除するかどうか。 既定値は true です。    

     

4. おまけ : 切り分けをしてみよう!

画像が表示されないなどの場合、HTTP ステータスが何であったかによって対処が変わります。 例えば良くある 404 = Not Found の場合は、対象のファイルが無いということを調査の端緒にします。しかし、実際には別のステータスのこともあります。それによって、例えば認証を疑ってみるなど、アプローチ方法が変わることもあります。 ご自身で切り分けをされる際は、Fiddler や HTTPREPLAY ツールなどをご利用いただくことも良いかと思います。 例えば、今回この問題を弊社で調査した流れは、以下のような形でした。

1. 動作の把握
2. クライアント、レポートのいずれに問題があるかの確認
3. MSDN ライブラリにおける関連情報の確認
4. サンプルの動作に基づく事例調査
5. 有効性の評価

まず、画像のロードに失敗し [x] が表示される状態になったときの要因を探るため、クライアント (Web ブラウザ)、レポートのいずれに問題があるのかについて切り分けるため、画像が表示されない状況が HTTP 通信としてどのような状況であるのかを HTTP 通信を確認することができる "Fiddler2" ツールを用いて把握しました。

Fiddler2 は、以下よりご入手いただけます。
https://www.fiddler2.com/fiddler2/

image

Fiddler2 を起動させた状態にして、Internet Explorer を起動し、再現試験を実施します。現象の発生するページ中の [x] になっている Chart イメージを右クリックし、アドレスを表示させます。すると、以下のように表示されていることがわかります。

例 : 
https://localhost/MychartTest/ChartImg.axd?i=chart_0_14.png&g=8408b888301548928040242f5ea09832

たとえば、この問題の場合、このタイミングで Fiddler の左ペインの Web Sessions を見ていくと、赤い三角に ! マークのアイコンとともに、404 が発生していることがわかります。

image

URL を見ると、そのうち、IE の画像のプロパティの URL で確認したものと同一のものが確認できます。
(Web Sessions を右クリックし、[Copy] – [Full Summary] で以下のようにコピー可能です)

# Result Protocol Host URL Body Caching Content-Type Process Comments Custom
36 404 HTTP (略)/ChartImg.axd?i=chart_0_19.png&g=a6f70d78a90947c2b3f91922f2087762 1,289 private text/html iexplore:7076 [#22] 

image

図 : IE 上の [X] 状態の画像 (上) と Fiddler 上の表示 (下)

image

これにより、今回の画像の問題は、404 = Not Found であることがわかりますので、参照先が何らかの状況により見つからない状態である、あるいはそうした判断に準ずる状況になっていると判断することができることになります。
ChartImageHandler と 404 関連でライブラリなど参考情報を確認しましたところ、deleteAfterServicing の項にて、クライアントからのダウンロードを正常終了した後に、イメージを削除するという動作であることをみとめました。
この MSDN ライブラリの動作の説明の内容と、HTTP ステータス 404 であったことを検討し、同プロパティの影響の可能性が高いと判断することになりました。

補足 : 
Fiddler2 を用いる場合、HTTPS 通信が使われる場合は、詳しくリクエストの状況を確認するには設定が必要です。

1. Fiddler2 の [Tools...] - [Fiddler Options] を開きます。
2. HTTPS タブを開きます。
3. "Capture HTTPS CONNECTS" チェックボックスと、"Decrypt HTTPS traffic" チェックボックス双方にチェックし、[OK] ボタンを押します。

image

これで、HTTPS の通信も見ることができます。

image

それでは皆様ごきげんよう。