WebResource (WebResource.axd / AssemblyResourceLoader) の使い方

昨日の内容は大きく間違っていたようです、ごめんなさい。色々変だなーとは思うところがあったんですが、5分で調べられる範囲じゃなかった、反省。

WebResource.axd は、ASP.NET 2.0 で提供され、AssemblyResourceLoader を使ってアセンブリの埋め込みリソースを Web のレスポンスとして提供するハンドラです。
利用するためには、

  1. 埋め込みリソースを AssemblyResourceLoader に対して公開する
  2. アセンブリを特定できる型を用意する
  3. WebResource.axd を利用してリソースを要求する

という手順になります。

埋め込みリソースを AssemblyResourceLoader に対して公開する

埋め込みリソースは、デフォルトでは AssemblyResourceLoader を利用してアクセスできません。これを許可するためには WebResourceAttribute を使用します。
また、WebResourceAttribute では、そのリソースをアクセスした際にブラウザに返す Context-type も指定する必要があります。

// プロジェクトの root namespace の下の FolderA の下にある filename.jpg を公開
[assembly:WebResource("RootNamespace.FolderA.Filename.jpg", "image/jpg")]

当然ですが、指定した名前でリソースを埋め込んでおく必要があります。

アセンブリを特定できる型を用意する

昨日の記述とかぶりますが、リソースの指定には ResourceManager などと同様に名前空間アセンブリがリソースと一致している型を必要とします。

namespace RootNamespace
{
  public sealed class FolderA {}
}

と、とりあえず空でも良いので型を用意しておきましょう。どうせ、リソースの難読化などで必要になりますしね?*1

WebResource.axd を利用してリソースを要求する

公開されたリソースをアクセスするための URL を取得するには GetWebResourceUrl() を呼び出します。前述の例だと、

  string url = this.ClientScript.GetWebResourceUrl(typeof(FolderA), "Filename.jpg");

として取り出せます。この URL に対して GET 要求を行うと filename.jpg が image/jpg という context-type で手に入ります。

公開されたリソースをアクセスするもう1つ手段は RegisterClientScriptResource() を呼び出すことです。たとえば、郵便番号入力コントロールのクライアントスクリプト

this.ClientScript.RegisterClientScriptResource(typeof(FolderA), "ZipCodeValidator.js");

という具合に登録します。この呼び出しは、次の記述と等価です。

this.Response.WriteLine("<SCRIPT SRC="{0}"></SCRIPT>",
  this.ClientScript.GetWebResourceUrl(typeof(FolderA), "ZipCodeValidator.js");

ただし、郵便番号入力コントロールは、Web Form 上に複数個配置される可能性があります。郵便番号入力コントロールが、下側のコードを記述していた場合、郵便番号入力コントロールを2つ配置すると、生成されたレスポンスには SCRIPT タグが2回出現してしまいます。
RegisterClientScriptResource() の場合、二重呼び出しのチェックが存在しますので、郵便番号入力コントロールを2つ配置しても、SCRIPT タグは1つしかレスポンスに書き出されないという利点があります。

*1:sgen を使って強い型付きクラスを生成しておくのも手ですし、そのほうがコードから利用できて便利になると思います。