WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

URL Rewrite Module の Outbound Rules

by WebSurfer 2017年3月20日 16:56

gzip 圧縮済みのコンテンツを応答としてブラウザに返す場合、下の画像のように応答ヘッダに Content-Encoding: gzip を設定する必要があります。

応答ヘッダ

HTTP ハンドラを使って自分でダウンロードするコードを書く場合は自由に応答ヘッダを追加できますが、IIS の静的ハンドラを使う場合(例えば、img 要素の src 属性に .svgz 画像のパスを設定したような場合)はどうすればいいでしょう?

URL Rewrite Module 2.0 の Outbound Rules を利用すると応答ヘッダに Content-Encoding: gzip を設定できます。.svgz 画像の場合を例にとって以下にその方法を書きます。(注: Content-Type: image/svg+xml も必要ですが applicationHost.config の MIME Map で設定済みであれば何もする必要はありません。IIS Manager で調べてください)

URL Rewrite Module の Outbound Rules

IIS Manager を起動して、上の画像のように Add Rule(s) ダイアログで Outbound Rules の Blank rules を選択し、OK ボタンをクリックすると Edit Outbound Rule という編集画面が開くので、そこでまず Precondition を定義します。

Precondition の定義

上の画像は Precondition の名前を IsSVGZ とし(任意)、Server Variable の URL(クエリ文字列等を含まないベースの部分)が正規表現の \.svgz$ にマッチする(.svgz で終わる)という条件になっています。URL の代わりに PATH_INFO を使っている記事がありますが、 ASP.NET の場合はどちらも同じ結果になりますので、分かりやすいと思われる URL を使用しました。

Precondition 設定後 Edit Outbound Rule 編集画面に戻って、Rule 名(任意)と Match 条件を設定します。下の画像の赤枠で囲った部分を見てください。

Name と Match の設定

Server Variable 名の RESPONSE_CONTENT_ENCODING と言うのは、Microsoft の公式文書には見つかりませんでしたが、応答ヘッダの Content-Encoding になるようです。正規表現の .* は 0 個以上の任意の文字という意味です。

ちなみに、RESPONSE_ が頭に付いている Server Variables には、RESPONSE_CONTENT_ENCODING 以外に、以下の画像の項目があるようです。未検証未確認ですが、それらは全て URL Rewrite Module で書き換え可能かもしれません。

Action の設定

次に Edit Outbound Rule 編集画面の下の方にある Action の設定を行います。下の画像の赤枠で囲った部分を見てください。

Action の設定

上記の操作の結果、当該サイトの web.config に以下のコードが生成されます。(逆に言えば、IIS Manager を操作しなくても、web.config を編集して以下のコードを追加しても同じ結果が得られます)

 
<system.webServer>
  <rewrite>
    <outboundRules>
      <rule name="Rewrite SVGZ header" 
        preCondition="IsSVGZ" stopProcessing="true">
        <match serverVariable="RESPONSE_CONTENT_ENCODING" 
          pattern=".*" />
        <action type="Rewrite" value="gzip" />
      </rule>
      <preConditions>
        <preCondition name="IsSVGZ">
          <add input="{URL}" pattern="\.svgz$" />
        </preCondition>
      </preConditions>
    </outboundRules>
  </rewrite>
</system.webServer>

上の web.config の設定により、Server Variable の URL が .svgz で終わっている要求に対しては、応答ヘッダの Content-Encoding を gzip に書き換える(無ければ追加する)という操作が URL Rewrite Module によって行われ、一番上の画像で示したように Content-Encoding: gzip が付与されます。

<注意>

URL Rewrite Module は自分でダウンロードしてインストールする必要があります。インストールしてないと web.config を書き換えても効果はありません。

Microsoft URL Rewrite Module 2.0 for IIS 7 (x64)

Microsoft URL Rewrite Module 2.0 for IIS 7 (x86)

Windows 10 にはインストールできない(レジストリの設定変更が必要)という話がありますが、その場合は、英語版しか見つかりませんが、以下のページからダウンロードしたものがレジストリの設定変更なしでインストールできます。

Microsoft URL Rewrite Module 2.0 for IIS (x64)

自分は英語版を使ったので、IIS Manager の Url Write の部分のみ英語になってしまいました。上の画像の表示は日本語版とは異なると思います。

Tags: , ,

Windows Server

ブラウザーリンク

by WebSurfer 2017年2月25日 15:44

先日買った Windows 10 Pro 64-bit のノート PC に OS が Vista の旧マシンでは使えなかった Visual Studio 2015 Communuty をインストールして使い始めました。

手始めに、テンプレートを使ってインターネット上でフォーム認証を使う Web サイトプロジェクトを作って、Fiddler で要求 / 応答をキャプチャしてみると、以下の画像のように localhost との正体不明な通信が行われています。(驚)

Fiddler によるキャプチャ

(ちなみに、vortex.data.microsoft.com, urs.smartscreen.microsoft.com の正体は分かっています。Tunnel to とは Fiddler が HTTP CONNECT 要求を受けてブラウザとサーバー間で直接通信するようにトンネルを開けたということだそうです)

一体これは何なんだと驚いて、URL にある browserLink をキーワードにググって調べてみると、MSDN Blog の記事に「クロスブラウザのテストに Visual Studio 2013 のブラウザーリンクをどうぞ」というのが見つかりました。

ブラウザーリンクというのは、Visual Studio 2013 から搭載された新機能で、IE, Forefox, Chrome などの複数のブラウザを同時に立ち上げて表示させたり、Visual Studio 上でのコードの修正を複数のブラウザに同時に反映させたりする機能だそうです。

そのために、Visual Studio が HTML ソースにスクリプトを追加し、そのスクリプトによって Visual Studio と各ブラウザが通信を行っているそうです。その結果が、上の画像にある localhost との正体不明な通信だったようです。

MSDN Blog の記事にも書いてありますが、ブラウザーリンクは Visual Studio の設定で無効にできます。

具体的には、上の画像の ▼ 印をクリックすると表示されるドロップダウンメニューで[Browser link を有効にする]のチェックを外します。

早速チェックを外して試してみると、HTML ソースへのスクリプトの追加はなくなり、localhost との正体不明な通信も行われなくなったのが確認できました。

Visual Studio 2010 から 2015、ASP.NET 4 から 4.5 とそれほど長くはない間に、ブラウザーリンク以外にも、いろいろな進化があったようです。

その進化に完全に取り残されていると感じる今日この頃です。(汗)

Tags:

DevelopmentTools

Control.ClientID と Html.IdFor

by WebSurfer 2017年2月19日 14:13

ASP.NET Web Forms アプリの場合、サーバーコントロールが HTML 要素としてレンダリングされた際、その要素の id 属性の値を取得するのに ClientID プロパティを利用できます。

なので、<%=TextBox1.ClientID%> というようにコード表示ブロックを使って、インラインのスクリプトに TextBox1 が HTML 要素に変換された時の id を埋め込むことができます。

例えば Datepicker を使いたい場合、$('#<%=TextBox1.ClientID%>') として TextBox1 の jQuery オブジェクトを取得し、それに datepicker() メソッドを適用することで可能になります。

jQuery UI Datepicker

ASP.NET MVC アプリではそれと同様なことはできないと思っていたのですが、MVC4 以降には Html ヘルパーに IdFor メソッドが用意されていて、それを使えば可能なことが分かりました。今さらながらですが(汗)、その具体例を書いておきます。

以下のような View のコードからは、

for (int i = 0; i < Model.Children.Count; i++)
{
  @Html.LabelFor(m => m.Children[i].Name)
  @Html.EditorFor(m => m.Children[i].Name)
  @Html.ValidationMessageFor(m => m.Children[i].Name)
        
  @Html.LabelFor(m => m.Children[i].DateOfBirth)
  @Html.EditorFor(m => m.Children[i].DateOfBirth)
  @Html.ValidationMessageFor(m => m.Children[i].DateOfBirth)
}

以下のような html ソースがレンダリングされます。(i = 0 のもの)

<label for="Children_0__Name">Name</label>
<input class="text-box single-line" 
  id="Children_0__Name" name="Children[0].Name" 
  type="text" value="" />
<span class="field-validation-valid" 
  data-valmsg-for="Children[0].Name" 
  data-valmsg-replace="true">
</span>
<label for="Children_0__DateOfBirth">DateOfBirth</label>
<input class="text-box single-line" data-val="true" 
  data-val-date="DateOfBirth は日付である必要があります。" 
  data-val-required="DateOfBirth フィールドが必要です。" 
  id="Children_0__DateOfBirth" name="Children[0].DateOfBirth" 
  type="datetime" value="0001/01/01 0:00:00" />
<span class="field-validation-valid" 
  data-valmsg-for="Children[0].DateOfBirth" 
  data-valmsg-replace="true">
</span>

上記の通り HTML 要素の id は予測不能ではないものの、それをスクリプトにハードコーディングするのはやめた方がよさそうです。(命名規則が変わるかもしれないので。そのあたりの事情は ASP.NET Web Forms アプリでも同じです)

Html.IdFor メソッドを使えば HTML 要素の id を取得できます。なので、例えばテキストボックスに Datepiker を適用したい場合は、以下の for 文のようにします。(MVC4 のテンプレートでアプリを作った場合です。for 文の上の 3 行はクライアント側での検証用スクリプト、jQuery UI 用のスクリプトと CSS です)

@section Scripts {
  @Scripts.Render("~/bundles/jqueryval")
  @Scripts.Render("~/bundles/jqueryui")
  @Styles.Render("~/Content/themes/base/css")

  @for (int i = 0; i < Model.Children.Count; i++) {
  <script type="text/javascript">
  //<![CDATA[
    $("#@Html.IdFor(m => m.Children[i].DateOfBirth)").
        datepicker();
  //]]>
  </script>
  }
}

すると、上記 for 文のコードによって以下のようなスクリプトが生成されます。(script タグは一つにしたかったのですが、その方法が見つかりませんでした。(汗) 方法が分かったら追記します)

<script type="text/javascript">
//<![CDATA[
  $("#Children_0__DateOfBirth").datepicker();
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
  $("#Children_1__DateOfBirth").datepicker();
//]]>
</script>

その結果をブラウザに表示したのが上の画像です。

(name 属性の値を取得したいというケースもあるかもしれませんが、そのための Html ヘルパー NameFor も用意されているそうです。ご参考まで)

Tags: ,

MVC

About this blog

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

Calendar

<<  2017年11月  >>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

View posts in large calendar