前回書いた Azure Functions の DI の方法だと、ASP.NET Core ではよく使う appsettings.json の読み込みがデフォルトで設定されていません。
local.setting.json ローカルデバッグ用の環境変数の設定はできるけど、
で困るのは Array とか object に対応してないところ。
Cosmos DB のコレクションを定義したいときは配列で定義して、さらにその中でIDやパーティションキーとか定義しておきたいので、Array とか使えないとめんどいです。Azure 上でアプリケーション設定に Array 形式で書くのもめんどいし。
ということで、そこらへんの実装のメモです。
appsettings.json の追加
とりあえずプロジェクトに appsettings.json
を追加します。追加したら、この appsettings.json
を右クリック > プロパティ を選択 > 出力ディレクトリーにコピー の値を用途に応じて「常にコピーする」または「新しい場合はコピーする」にしておきましょう。これをしないとビルドやデバッグ時に出力ディレクトリーに出力されず読み込めないという凡ミスによる混乱を招きます。
今回はサンプルとして、appsettings.Development.json
も追加しました。環境に応じて変更できるかの確認の為です。追加後、こちらも出力ディレクトリーにコピーの設定を忘れずにしましょう。
appsettings.json の中身は、以下のようにしてみました。あえてちょっとごちゃっとしてます。
{ "SampleConfig": { "Name": "sample-config", "Items": [ { "Key": "key1", "Description": "description-1" }, { "Key": "key2", "Description": "description-2" } ] } }
後は、この Json を読み込んだ後に格納する class を作っておきましょう。
public class SampleConfig { public string Name { get; set; } public Item[] Items { get; set; } } public class Item { public string Key { get; set; } public string Description { get; set; } }
Configure メソッド(Starup.cs)で appsettings.json を読み込む
Startup.cs
class の Configure
メソッドで読み込むのみです。
ここでの Startup.cs
class の Configure
メソッドは、前回の DI の設定で使ったものを使います。
実装方法としては、Azure Functions のランタイムでDIされてる IConfiguration
に 自分のカスタムしたい Configuration (今回だと、appsettings.json の読み込み)を追加する っていう簡単な実装です。
解説は後述します。
IHostingEnvironment の取得/ IConfiguration の取得(16行目 ~ 19行目)
appsettings.json
を使ってると、appsettings.Development.json
とかも使うこともあるでしょう。環境名を取得するのに IHostingEnvironment
も取得しておきます。
GetRequiredService
メソッドは、Service とれなかったら InvalidOperationException
を吐いてくれるいいやつです。
同様に Azure Functions のデフォルトで登録されてる IConfiguration
のを取得しています。変数名は defaultConfig
で取得しておきました。
注意:
IHostingEnvironment
のフルネームは Microsoft.Extensions.Hosting.IHostingEnvironment
です。ASP.NET Core で今までよく使っていた Microsoft.AspNetCore.Hosting.IHostingEnvironment
ではないです。
ここでの違いは、SDKの内部的に IHostingEnvironment
の EnvironmentName
プロパティの環境変数の Key が異なります。つまり Azure上でのアプリケーション設定や、ローカルデバッグ実行時の挙動に影響します。
namespace | EnvironmentName を設定する環境変数のキー |
---|---|
Microsoft.AspNetCore.Hosting | ASPNETCORE_ENVIRONMENT |
Microsoft.Extensions.Hosting | AZURE_FUNCTIONS_ENVIRONMENT |
ということで、ローカルでも Azure のリソースの Azure Functions のアプリケーション設定でも、必要に応じて環境名を設定しましょう。
この設定は、私の環境で動作確認をしたうえでの結果ですが、Microsoft.Extensions.Hosting のソースには key が "environment" って書いてるんですよね...ConfigurationBuilder のAddEnvironmentVariables 時の Prefix は除外した値ってこと?とか不明...
追記: こちらのドキュメントに AZURE_FUNCTIONS_ENVIRONMENT
についての記載がありました。
今だと私の環境では正常に動き続けてるけど、ここ数日間で何が悪いのかわからんけど動いたり動かなかったりという謎事象が起きてるので今度も大丈夫かなーなんか間違ってるのかなーと不安要素ありです。環境変数を設定してないときのデフォルト値は、ローカルデバッグ時は Development
, Azure上では Production
のはずですが、なぜか Azure 上でも Development
になったり、設定しても値が反映されないことがあった。。。
そして、Microsoft.Extensions.Hosting.IHostingEnvironment
も .NET Core 3.0系から Breaking changeします(issueはこちら)。ここら辺は今後しらばらくチェックが必要ですなぁ。
appsettings.json を読み込む(23行目 ~ 28行目)
23行目は、appsettings.json のファイルパスを取得する部分です。Functions の実際にコールされる関数の方(日本語変やな)だと、ExecutionCotenxt
の FunctionAppDirectory
から取得できますよねー... この値は 実装上 ExecutionContextOptions
から取得しているためこんな感じで取得しています。
env.IsDevelopement
で If ってますが、とりあえずデバッグ用か Auzre 上かを分けただけなので、応じて書き換える必要があるかもしれません。
25~28 行目で appsettings.json
と 環境名付きの json ( appsettings.Development.json
とか)に対応して json を読み込みます。
31行目で、既存の IConfiguration
と今作成した IConfiguration
を結合しました。
以降は普通にASP.NET Core のやり方で DI の設定してるだけです。
これで、ローカルデバッグでも Azure 上でも動作することは確認できましたが、23行目の 。@"D:\home\site\wwwroot"
べた書きは微妙過ぎて微妙過ぎて震えますね
23行目: appsettings.json のパスの取得について
現時点での Azure Functions 上でのパス D:\home\site\wwwroot をべた書きではなく何らかの形で取得したいのですがよい手段がない....
ブログポストした当初はべた書きで実装してたんですが更新しました。
appsettings.json のパスは、ExecutionContext の FunctionAppDirectory プロパティが持っているので、それを azure-webjobs-sdk 内でセットしてるのがExecutionContextOptions
。これを ServiceProvider からとろうと....私はwebjobs-sdkみて、型を IConfigureOptions<ExecutionContextOptions>
で取得し、その型だと中身を見る手段がない....で詰んだんですが、
そもそも IOptions<ExecutionContextOptions>
でとればいけるやんって話をしばやん先生からありがたくいただきました♪
これでトラブルのひとつは解決です!あざます!
これでどないでしょ(ローカルしか見てないですが pic.twitter.com/izpo2vB3cx
— しばやん (@shibayan) 2019年5月21日
といことで、サンプルコードの全体はこちら。
GitHub - beachside-project/azure-functionsV2-DI-sample