かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Azure Bot Services の SDK が v4.3.x にアップデートして色々変わってる件について

噂には聞いてたんですが、ダウンロードしてびっくりしました。 気づいた点をさくっと書いておこうと思います。

因みにリリースノートはこちら。

github.com

Controller クラス復活

今まで api/messages エンドポイントを定義するのは Azure Bot Services の SDK が内部的にやってくれてました。これからは ASP.NET MVC Core の Controller を作る感じです。

こんな感じで、Controllers フォルダーに定義されてます。なるほどね。まぁ、今まで ASP.NET MVC とか WebAPI とか Core の MVC とかやってた人にとってはわかりやすいのかな。

[Route("api/messages")]
[ApiController]
public class BotController : ControllerBase
{
    private readonly IBotFrameworkHttpAdapter _adapter;
    private readonly IBot _bot;

    public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
    {
        _adapter = adapter;
        _bot = bot;
    }

    [HttpPost]
    public async Task PostAsync()
    {
        // Delegate the processing of the HTTP POST to the adapter.
        // The adapter will invoke the bot.
        await _adapter.ProcessAsync(Request, Response, _bot);
    }
}

IBotFrameworkHttpAdapter に ProcessAsync に丸投げですか。内部的に今までこれやってたんだろうなぁ。

Startup.cs では何やってんの…

Configure メソッドでは UseMvc とかしてます。そして ConfigureServices メソッドで色々登録しています。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    if (!string.IsNullOrEmpty(Configuration[BotOpenIdMetadataKey]))
        ChannelValidation.OpenIdMetadataUrl = Configuration[BotOpenIdMetadataKey];

    // Create the credential provider to be used with the Bot Framework Adapter.
    services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

    // Create the channel provider to be used with the Bot Framework Adapter.
    services.AddSingleton<IChannelProvider, ConfigurationChannelProvider>();

    // Create the Bot Framework Adapter with error handling enabled. 
    services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

    // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.) 
    services.AddSingleton<IStorage, MemoryStorage>();

    // Create the User state. (Used in this bot's Dialog implementation.)
    services.AddSingleton<UserState>();

    // Create the Conversation state. (Used by the Dialog system itself.)
    services.AddSingleton<ConversationState>();

    // The Dialog that will be run by the bot.
    services.AddSingleton<MainDialog>();

    // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
    services.AddTransient<IBot, DialogAndWelcomeBot<MainDialog>>();
}

この中で必須だと思われるのが IBotFrameworkHttpAdapter は必須だと思います。 これはデフォルト実装として BotFrameworkHttpAdapter が提供されています。なんかデフォルトのボットを Web App ボットでやってるやつは色々継承して拡張してますが、特に特別なことをしたくなければ、BotFrameworkHttpAdapter をそのまま登録しててもよさそうです。

BotFrameworkHttpAdapter のインスタンスを作るためには ICredentialProvider と IChannelProvider あたりがいるみたいです。以下のような定義になっているので。

public BotFrameworkHttpAdapter(ICredentialProvider credentialProvider = null, IChannelProvider channelProvider = null, ILogger<BotFrameworkHttpAdapter> logger = null)

null がデフォルト引数なので、もしかしたらなくてもワンチャン…?(要確認)

ICredentialProvider

前は SimpleCredentialProvider を使ってたのですが、ConfigurationCredentialProvider を使うようになっています。これは、どっちのクラスも ICredentialProvider を実装していて、どちらかが登録されてれば動きそうです。

ConfigurationCredentialProvider はSimpleCredentalProvider を継承していて IConfiguration から MicrosoftAppId と MicrosoftAppPassword を抜き取って認証してくれてるみたいです。

因みにローカル実行時に認証外したい場合は以下のようなアプローチが考えられます。 appsettings.json の MicrosoftAppId と MicrosoftAppPassword は空にしておいて、本番での値の設定は Azure App Service のアプリケーション設定でやる感じ。

もしくは ConfigureService で開発環境か本番環境かを判定して開発環境では特に値を設定していない SimpleCredentialProvider を IServiceCollection に追加して本番は ConfigurationCredentialProvider を設定とかって感じです。

IChannelProvider

このインターフェースの実装のコードを見たけど特に何してるのかわからなかったので、とりあえず ConfigurationChannelProvider を指定しておけばよさそう。

オプション

状態管理

ステートを管理したかったら IStorage のインターフェースを実装したものを登録してから UserState と ConversationState を登録しておけばよさそう。

ボットクラスについて

IBot インターフェースを実装してましたが ActivityHandler クラスを継承する感じです。まぁ ActivityHandler クラスは IBot インターフェースを実装してて、よくあるメッセージハンドリングの流れをやってくれてるだけなので使わなくてもいいですね。

ボットにも DI したい場合は IServiceCollection に登録しておきましょう。Controller にコンストラクターインジェクションしてやれば OK です。

LUIS, QnA メーカーは?

個人的に、これは特に決まりも何もないと思うので好きなところに設定書いて、好きなようにインスタンス化して使うなり、IServiceCollection に登録して使えばいいはず…。

ダイアログ

大きな変更はなさそう?

まとめ

重要なことなのですが下位互換を破壊するような大きな変更はないはずです。 今まで通り .bot ファイルに構成を書いて BotConfiguration クラスを使って読み込んでとかも出来ます。クラスは消えてたりしないはずです。インテリセンスにも出ます!

f:id:okazuki:20190417001337p:plain

なので前までの書き方でも動きます。 でも新しい書き方としては ASP.NET Core の MVC に寄せてきたみたいです。 こうすると、ASP.NET Core MVC のプロジェクトに追加でさくっと足すときの心理的な負担が少ないようにも感じます。

あと、App Service のアプリケーション設定を使うようになったのも、アプリケーション設定を前提とした各種 Azure の機能を利用するために利用者としては利便性が上がってると思います。私は歓迎。

ということで、楽しいボット開発を!