検索
リンク
タグ
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月 26日
前回の投稿、「IIS 環境で、AngularJS の ng-include で読み込む HTML がキャッシュされたまま更新されない」の続編。
Visual Studio の "ブラウザー リンク" 機能Visual Studio で Web アプリ開発をする際、便利な機能のひとつが "ブラウザーリンク (Browser Link)" 機能である。これは何かというと、Webアプリ開発中の Visual Studio と、開発中のWebアプリコンテンツを開いているブラウザーとの間で通信を実現することで提供される便利機能の基盤である。 と言っても何のことだかわかりにくいが、Browser Link によって実現される便利なWebアプリ開発機能として代表的なものを挙げると、CSS の "ライブリロード" だろうか。 Visual Studio で Web アプリのプロジェクトを開いて実行し、ブラウザで開発サーバーの URL を開いたのちに、おもむろにその Visual Studio で .css ファイルを書き換え始めると、ほぼほぼリアルタイムで、.css の変更内容がブラウザに反映されていく、といった機能だ。 ![]() ※このケースだと、技術的には保存された .css を "再読み込み (リロード)" しているわけではないため、厳密には "ライブリロード" という言い方は正確ではない気もするが、まぁ、そんな細かいことはいいだろう。 昨今では、grunt やら gulp やらの自動タスク実行環境によっても容易にライブリロード環境を構築できるので、珍しい話ではない。 しかし、Gruntfile.js とかをゴリゴリ書いたり自分でコンテンツにライブリロード用の JavaScript コードを書き加えたりしなくても、Visual Studio さえあれば設定要らずですぐに有効化されているのが楽といえば楽である。 なお、Browser Link は「Visual Studio とブラウザとが通信する」というのがキモなのであり、CSS のライブリロードだけでなく、他にも色々と有用かつ強力な開発支援機能がある。しかし本投稿は Browser Link の全機能を説明するのは主旨ではないため、以降は割愛。 Browser Link の仕組みと制約仕組みとしては、ASP.NET の HTTP 要求処理パイプラインの仕組みを利用して、Web アプリサーバーが HTML コンテンツをブラウザに返す直前に Visual Studio が介入し、Visual Studio との通信を行う JavaScript コードをコンテンツに書き加えてから応答返信することで実現されている。参考情報: しばやん雑記 - Visual Studio 2013 の新機能、ブラウザーリンクの仕組みを調べてみた http://blog.shibayan.jp/entry/20130629/1372502532 ところで、静的な HTML ファイル、いわゆる .html なファイルは、ASP.NET の HTTP 要求処理パイプラインを通らずに、直接 Web サーバーである IIS ( このシナリオだと普通は IIS Express ) によって取り扱われ、ブラウザに応答返信される。 このような仕組みであるため、静的 HTML ファイルについては先述の "介入" のチャンスがない。 すなわち、静的 HTML ファイルに Visual Studio との通信を行う JavaScript コードを書き加えることができないため、Browser Link 機能が働かない。 Browser Link 機能の静的 HTML ファイルでの有効化しかしいっぽうで、ブラウザで開くコンテンツは静的 HTML ファイルで開発するスタイルも普通にあるわけで (とくに Single Page Application, 略して SPA と呼ばれるような実装形態とか)、そういう場合は、静的 HTML ファイルでも Browser Link 機能を利用したいという需要はある。ということで、静的 HTML ファイルについても Browser Link 機能を有効化する手立てはちゃんとある。 静的 HTML ファイルへの HTTP 要求が発生したら、IIS に任せてしまうのではなく、ASP.NET の要求ハンドラで処理するように構成すればよいのだ。 そうすれば ASP.NET の HTTP 要求処理パイプラインの中で、通信用 JavaScript コードの注入が実現し、静的 HTML ファイルであっても Browser Link 機能が有効になる。 具体的には、拡張子 .html に対する HTTP 要求を、ASP.NET に標準で備え付けの、その名もずばり "StaticFileHandler" という名前のクラスに任せるよう、web.config に設定を書き加えればよい。 設定内容は下記である。(出典はこちら) <configuration> ng-include のキャッシュされたまま問題再燃!?だがしかし、ここでひとつの罠があった。上記設定を書き加えて、静的 HTML ファイルでも Browser Link 機能が有効になったと喜んでいると、前回投稿の、「ng-include で読み込む HTML ファイルが古い内容が表示される」問題が再発したのだ。 しかも発生するブラウザは、自分が試したのは Windows10 上の IE11, Edge, Google Chrome, Firefox だけだが、いずれのブラウザでも問題発生したのだ。 これはいったいどういうことか。 各ブラウザの開発者ツールや Fiddler で HTTP 通信の内容を確認してみた。 すると、サーバー側からの応答ヘッダに、Cache-Control として "public" が指定されているのに加え、Expires 応答ヘッダに現在日時 + 1日の日時が設定されていたのである。 これでは XHR 要求において、どのブラウザでも一向にキャッシュ破棄されない わけだ。(いや、正確には1日経てば破棄されるのだが) 調べてみたところ、どうやら StaticFileHandler クラスは、これら応答ヘッダは固定で出力しているようなのだ。 つまり、例えば web.config を書き換えることで応答ヘッダの内容を制御する、といったことはできないようなのである。 これは困った。 回避策は?Browser Link 機能は諦めて、HTML ファイルを StaticFileHandler に処理させるのをやめるか、あるいは、自作の ASP.NET HTTP モジュールを作って (ひどくは工数かからないけど) 応答ヘッダをさらに書き換えるようにわざわざ実装するしかないのか...。だがよくよく考えると、静的コンテンツの処理に ASP.NET の HTTP 要求パイプラインをくぐらせる方法がほかにもあった。 web.config の system.webServer 構成セクションには、modules ノードがあり、ここには runAllManagedModulesForAllRequests という true 又は false を設定する属性がある。 "Run All Managed Modules for All Requests"、すなわち「すべての要求に対し、すべてのマネージドモジュールを実行する」である。 この文脈で「マネージドモジュール」といえば、それは ASP.NET でいうところの HTTP モジュールと同義である。 となれば、この属性に true を設定すれば、静的 HTML ファイルに対する要求を含む、すべての要求処理が ASP.NET の HTTP 要求処理パイプラインを通ることを意味するのではないか? そうであれば、Browser Link 機能のための JavaScript 注入も行われるはずである。 ということで試してみた。 まずは先に追加した system.webServer - handlers への追加行を削除して元に戻しておく。 次に、system.webServer 構成セクションに、下記のノードを追記する。 <modules runAllManagedModulesForAllRequests="true"> この状態で、再び問題の Web アプリを動作確認してみた。 すると、期待どおり Browser Link 機能が有効になりつつ、AngularJS の ng-include におけるキャッシュ問題も前回投稿の処置によって解消された状況に落ち着くことができた。 サンプルのソースコード前回投稿に引き続き、GitHub に公開したサンプルコードのリポジトリに、今回のシナリオの問題再現とその対応の様子を別々のブランチ上にコミットした。https://github.com/sample-by-jsakamoto/ASPNETStaticFileCacheCtrlAndNGInclude 前回同様、README.md に掲載した「Deploy to Azure」ボタンをクリックすれば、Microsoft Azure のアカウントさえお持ちであれば、ご自身で Azure Web Apps 上にこの Web アプリを設置して動作を確かめることができる (この程度のサンプルは、無料枠でじゅうぶん試せる)。 まとめ静的 HTML ファイルでも Visual Studio の Browser Link 機能を利用しようとして、静的 HTML ファイルへの HTTP 要求をASP.NET 標準備え付けの StaticFileHandler で処理するよう web.config を構成すると、固定で現在日時プラス1日のキャッシュ破棄指定が応答ヘッダに出力されてしまう。このことと、AngularJS の ng-inclued ( というか、ブラウザの XHR 機構 ) の仕様の兼ね合いで、ng-include 対象の静的 HTML ファイルが強くキャッシュされてしまう問題が発生する。 Browser Link 機能は有効にしつつこの問題を回避するには、静的ファイルへの HTTP 要求を StaticFileHandler で処理するのではなく、既定どおり IIS に任せるとして、代わりにすべての HTTP 要求を ASP.NET HTTP 要求処理パイプラインをくぐらせるようにすればよい。 具体的には、web.config の system.webServer 構成セクション、modules ノードを追加し、 runAllManagedModulesForAllRequests 属性に true を指定すればよい。 こうすることで、静的ファイルへの要求処理時に Browser Link 用の JavaScript を注入する機会が生じ、これで問題を回避可能だ。 補足なお、"静的ファイルへの要求を含めたすべての要求がマネージドモジュールをくぐる (ASP.NET HTTP 要求処理パイプラインを通過する) ようにする" ということは、もちろん、微々たるものとはいえ、処理速度上は不利である。開発中はともかくも、運用時には runAllManagedModulesForAllRequests は true のままにはしたくない、という場合は、「発行時の構成ファイル変換」によって runAllManagedModulesForAllRequests の設定を削除する (か、 false を設定する) ことで対処できるだろう。 その他の想定されるシナリオとしては、Browser Link に関係なく他の何かしらの事情のために、.html ファイルを StaticFileHandler で処理する必要が別途あるケースが考えられる。 この場合は、残念ながら今回投稿の方法では「ng-include でキャッシュされたまま問題」が発生して回避できない。 このようなケースでは、ASP.NET HTTP モジュールを自作することで回避可能だが、詳しくは割愛する。 (必要であれば @jsakamoto までメンションください)
by developer-adjust
| 2015-10-26 21:21
| .NET
|
Comments(0)
|
ファン申請 |
||