Azure Functions V4 が リリースされて .NET 6 が使えるようになった。それと同時に Proxy が廃止されたので、しばやんさんが、いい感じの代替えソリューションをリリースしてくれました。
この仕組みは、Site Extensions という仕組みの上で作成されているのですが、私は、Site Extensions の仕組みを知らないので調査をしてみることにしました。
概要
Site Extensions は、AppSerivce や、Functions で使える仕組み。Kudu を使った仕組みで、開発者がIISのバックエンドになりうるアプリケーションを書いて kudu に配置することができ、設定ファイルによって、IIS の applicationHost.config
を書き換えることが出来る仕組みです。kudu の中で動作するので、セキュリティで守られた環境にあるため、Adminツールを作るのにも向いています。
チュートリアル
この仕組みが作られたのが古いためか、最新のドキュメントは見つかりませんでした。2014 年ベースのものがここで見つかりました。
Writing a Site Extension for Azure Websites
今回は折角ですので、.NET 6 ベースのアプリケーションで同じことをやってみました。チュートリアルでは、ASP.NET MVC を使っていますので、同じように .NET 6 ベースのものを使ってみます。チュートリアルでは FileCounter
というプロジェクトを作りますので、同じ名前にしてみます。デフォルトで、テンプレートが作成されます。
元のチュートリアルでは、Server.MapPath("/")
というメソッドを使うのですが、今のバージョンには存在しません。代替えソリューションとしては、DI で、IWebHostEnvironment
をインジェクションして、そのオブジェクトが所有している WebRootPath
を使うようにします。元のサンプルでは、このインターフェイスを使っていなかったので、Azure でもローカルでも実行できるように、if ステートメントで分岐していましたが、不要なので削除しました。
私のサンプルでは、コードを変えてファイルをリストするように変えています。
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private IWebHostEnvironment _environment;
public HomeController(IWebHostEnvironment environment, ILogger<HomeController> logger)
{
this._environment = environment;
_logger = logger;
}
public IActionResult Index()
{
string siteFolder = _environment.WebRootPath;
var files = Directory.GetFiles(siteFolder,
"*.*",
SearchOption.AllDirectories);
var fileNames = string.Join(", ", files);
return View(model: fileNames);
}
Index.cshtml
は、ファイルのリストを model として渡しているので、次のように変えました。
@model string
@{
ViewData["Title"] = "File Listing MVC";
}
<div class="text-center">
<h1 class="display-4">Your site following files</h1>
@Model
</div>
F5
を押して実行してローカルで動作したら、プロジェクトに、applicationHost.xdlt
をプロジェクトのルートに置いておきます。VS の場合、Copy to Output Directory
の設定をCopy if newer
などにしておくのが重要です。
ApplicationHost.xdlt
これが、IIS の ApplicationHost.configを変更するための設定ファイルです。この設定の場合、scm サイトの方に/filecounterMVC
というサブディレクトリにアクセスしたときのこのアプリケーションが動作して結果を返します。
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SCMSITENAME%" xdt:Locator="Match(name)">
<application path="/filecounterMVC" applicationPool="%XDT_APPPOOLNAME%" xdt:Transform="Insert">
<virtualDirectory path="/" physicalPath="%XDT_EXTENSIONPATH%" />
</application>
</site>
</sites>
</system.applicationHost>
</configuration>
これを kudu のサイトでテストするためには、プロジェクトを右クリックして、Publish を選択して、Folder を選択して、パッケージを作ります。Publish したら、バイナリが作成されているのがわかります。
Kudu の Deubg console から、SiteExtensions ディレクトリを作成して、その下に自分の作った Extension を置いておきます。ドラッグ&ドロップで先ほど作成した、アプリケーションをコピーします。
あとは設定した通りに、サイトにアクセスします。動作しています。
ここからは、IIS のコンフィグの知識が必要になるので、まだまだ勉強が必要ですが、例えば私は、%XDT_SCMSITENAME%
を変更して、本番側のURLにマップしたいと思ったので、%XDT_SITENAME%
にして、本番側のリスタートを行ったのですが、途中で、kudu が死にました。多分設定が根本的に間違っているのでしょう。このようなケースは、AppSettings に WEBSITE_PRIVATE_EXTENSIONS=0
を設定すると、Private のExtensionが無効になり、IIS の設定が無効になるのでサイトが回復します。
デバッグの際は、C:\home\LogFiles\Transform
にトランスフォーメーションのログがあります。また、変更されたapplicationhost.config
は、地球アイコン (Site の意味)をクリックしてその配下のConfig
に実態が存在します。
%XDT_SITENAME%
に変更したものを見てみるとこんな感じになっていました。多分問題なのでしょう。(これから勉強しますw)
<application path="/filecounterMVC" applicationPool="tsushiextension">
<virtualDirectory path="/" physicalPath="C:\home\SiteExtensions\FileCounterMVC" />
</application>
参考資料
何か SiteExtensions を作る必要があったわけではなく、単なる興味で調べたのでまずはここまでですが、しばやんさんにリソースを教えてもらったので共有します。
Azure Site Extensions
これを読めば大体理解できます。他にも正式版として Publish する方法などが載っています。
Xdt transform samples
設定資料のリファレンスが欲しいところですが、ないみたいなので、サンプルを参照します。しばやんさんの場合、Azure Functions のものとかも参照されているようです。Functions もSite Extensions として登録されるようですね。
IIS 関連の資料
今後自分の読書メモとして、IIS の ApplicationHost.config
の設定の書き方を理解する必要がありそうです。