検索
リンク
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Visual Studio
Azure
ASP.NET Core
ライトニングトーク
Plone
AJAX
Selenium
C#
jQuery
ADO.NET Entity Framework
SQL Server
JavaScript
LINQ
WebMatrix
EFCore
Fizz-Buzz
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 ファン
ブログジャンル
画像一覧
|
2015年 10月 24日
AngularJS を使った、クライアント側実装のとある Web アプリの話。
このようなアプリを、Visual Studio で開発、サーバー側実装を C# による ASP.NET WebAPI などで実装しつつ、AppHarbor や Azure Wb Apps、はたまた LAN 内の Windows Server といった、IIS 上に設置・稼働させるシナリオを想定してほしい。 さて、この Web アプリでは、AngularJS の ng-include ディレクティブを用いて、利用者の操作に応じて ng-include で読み込ませる "副ビュー" である HTML ファイルを差し替えるようにしてある。 実動サンプルを AppHarbor 上に、下記 URL で設置したので、実際に試してもらえる。 http://sample-aspnetstaticfilecachectrlandnginclude.apphb.com/ このアプリでは、"副ビュー" として、~/views/date-time.html と ~/views/time.html を、利用者が選択したラジオボタンアイテムに応じて、ng-include で読み込むようにしてある。 ng-include の対象が更新されない!?さてこのようなアプリを開発・動作試験中に、困った現象に遭遇した。いちどこの Web アプリを開いて ~/views/time.html を表示したあと、~/views/time.html を変更してブラウザで再読み込みしても、ブラウザ上には変更前の ~/views/time.html が表示されてしまうのだ。 この現象は IE11 および Edge で発生することを確認した。 そして、ブラウザおよびOSを再起動しても、~/views/time.html は古い内容で表示されてしまう。 Ctrl + Shift + Delete などでブラウザのキャッシュを明示的に削除してから再読み込みすると、ようやく変更後の ~/views/time.html が表示されるようになった。 ※IEのオプション設定で、終了時にキャッシュを削除するように設定されている場合は、ブラウザやOSの再起動でも、変更後の ~/views/time.html が表示される。 この振る舞いは、先に紹介した実動サンプルでも見ることができる。 この実動サンプルでは「Update 'date-time.html' and 'time.html'.」ボタンをクリックすると、サーバー側にて、~/views/date-time.html 及び ~/views/time.html に、現在日時及び時刻を書き込むようになっている。 その上でブラウザの再読み込みまで実行されるのだが、IE/Edge では、再読み込み後も、~/views/time.html の内容は前回表示された古い内容のままとなっている。 IE/Edge の開発者ツールや、Fiddler で通信のやりとりを見ていると、IE/Edge では、~/views/time.html の必要が発生しても、自身がキャッシュしてある ~/views/time.html を使うだけで、Webサーバーには何も要求送信していなかった。 同じ Windows10 上の Google Chrome および Firefox ではそのような現象は起きなかった。 ※MacOS 上の Safari や、各種モバイルデバイス上のブラウザについては未確認。 また、この現象は、~/views/time.html だけで発生し、ページ表示時に既定で読み込むようにしてある ~/views/date-time.html では発生しない。 ~/views/date-time.html については内容変更してブラウザの再読み込みをすると、ちゃんと変更後の内容が表示される。 原因は Cache-Control 応答ヘッダの不在?ブラウザとWebサーバーとの間の HTTP 通信の内容を調査してみると、サーバー側からの応答ヘッダには、Last-Modified ヘッダが含まれていて、ちゃんと ~/views/time.html ファイルの最終更新日時が記載されている。だがしかし、Cache-Control ヘッダは明示されていなかった。 どうやら、Cache-Control 応答ヘッダが明示されていないことが、この不具合の要因であるようだ。 そこで、web.config に、IIS に対する設定変更を記述し、Cache-Control 応答ヘッダを出力するようにしてみた。 Cache-Control 応答ヘッダとして "no-cache" を返すように web.config に下記構成を書き加えてみた。 <configuration>その上で改めて動作確認してみると、ブラウザからの要求の2回目からは要求ヘッダに If-Modified-Since ヘッダが加わるようになった。 これに対するサーバー側の応答も、もし If-Modified-Since 要求ヘッダ値よりファイルのタイムスタンプが新しくなっていれば HTTP ステータス 200 OK でファイルの内容を応答本体に含めて返信、もしそうでなければ HTTP ステータス 304 Not Modified (変更なし) で応答本体は空で返信するようになった。 これで Windows10 上での IE, Edge, Chrome, Frefox の各ブラウザで共通の振る舞いとなり、解決となった。 ※MacOS 上の Safari や、iOSやAndroidなどのモバイルデバイス上の各種ブラウザではどうなのかは未確認。 サンプルのソースコード以上の実動サンプルのソースコードと、web.config 修正によって不具合回避できる様子をブランチ上にコミットした git リポジトリを、GitHub に公開した。https://github.com/sample-by-jsakamoto/ASPNETStaticFileCacheCtrlAndNGInclude README.md に掲載した「Deploy to Azure」ボタンをクリックすれば、Microsoft Azure のアカウントさえお持ちであれば、ご自身で Azure Web Apps 上にこの Web アプリを設置して動作を確かめることができる (この程度のサンプルは、無料枠でじゅうぶん試せる)。 まとめCache-Control 応答ヘッダで "no-cache" を返すように web.config を構成すると、IISがサーブするあらゆる静的コンテンツにて、常にブラウザからサーバーへの要求が発生することになる。もちろん、要求には If-Modified-Since ヘッダが付いており、応答も適宜 HTTP 304 によるヘッダのみの軽量な応答にはなるものの、とにかく HTTP 通信は発生してしまう点に注意が必要であろう。 今回の一件、ng-include で古い内容が表示される不具合の解決にあたり、すべての静的コンテンツで Cache-Control 応答ヘッダに no-cache を付けて返して差支えなければ、これで一件落着である。 自分はその程度の処理性能チューニングでじゅうぶん足りる要件だったので、web.config への構成追加で対応終了とした。 もっと細やかにキャッシュ制御している場合は、単純に web.config に書いて終わりではなく、最悪(?)、ASP.NET HTTP モジュールを作成して C# 等のプログラミング言語によっていろいろ制御する必要がでてくるかもしれない。 自分はそこまでの要求はなかったので、この点については割愛。 だがしかし悪夢再び...ところで、Visual Studio で Web アプリの開発作業を行っているなら、多くの人が "BrowserLink" 機能を活用しているのではないかと想像する。※"BrowserLink" 機能が何であるかは、本稿では割愛。 通常は ASP.NET MVC のビューなど、サーバー側で HTML をレンダリングする機構で有効化・利用可能となる機能だが、いわゆる .html、すなわち静的コンテンツとしての HTML ページでも "BrowserLink" 機能を有効化することができる。 具体的には、web.config に以下の記述を書き足すとよいとされている(出典はこちら)。 <configuration>ところが、である。 この web.config の設定を施すと、再び "ng-include で古い内容が表示される" 問題が発生するのだ。 しかも IE/Edge に限らず、Chrome、Firefox でも発生する。 この不具合の詳細と対処方法については日を改めて投稿したい。 つづく [2015-10-26 追記] 続編、投稿しました。 ブラウザーリンク機能が有効だと AngularJS の ng-include で読み込む HTML がキャッシュされたまま更新されない http://devadjust.exblog.jp/22387945/
by developer-adjust
| 2015-10-24 07:29
| Web系一般
|
Comments(0)
|
ファン申請 |
||