Bot Framework chatbot in VNET using Directline Extension and App Service

Directline Extension integration in Bot Framework | chatbot in VNET using Bot Framework

Enable Direct Line App Service extension

The complete code is available in this GitHub Repo:

Update bot code

  • In Visual Studio, open your bot project.

  • Allow your app to use named pipes:

  • Open the Startup.cs file. In the Configure method, add a call to the UseNamedPipes method.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDefaultFiles()
        .UseStaticFiles()
        .UseWebSockets()
         // Allow the bot to use named pipes.
        .UseNamedPipes(System.Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_SITE_NAME") + ".directline");
        .UseRouting()
        .UseAuthorization()
        .UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

    // app.UseHttpsRedirection();
}
  • Save the Startup.cs file.

  • Deploy your updated bot to Azure.

Enable bot Direct Line App Service extension

  • In the Azure portal, go to your Azure Bot resource.

  • From the left panel menu under Bot management select Channels to configure the Azure Bot Service channels your bot accepts messages from.

  • If it is not already enabled, select the Direct Line channel and follow instructions to enable the channel.
  • In the Connect to channels table select the Edit link on the Direct Line row.
  • Scroll down to the App Service extension Keys section.
  • Select the Show link to reveal one of the keys. Copy this value for use later.
  • Go to the home page, select App Services at the top of the page. Alternatively, display the portal menu and then select the App Services menu item, in the left panel. Azure displays the App Services page.

  • In the search box enter your Azure Bot resource name. Your resource will be listed.

  • Notice that if you hover over the icon or the menu item, you get the list of the last resources you viewed. Chances are your Azure Bot resource will be listed.

  • Select your resource link.

  • In the Settings section, select the Configuration menu item.

  • In the right panel, add the following settings:

Name - Value DirectLineExtensionKey - The value of the App Service extension key you copied earlier. DIRECTLINE_EXTENSION_VERSION - latest

  • If your bot is hosted in a sovereign or otherwise restricted Azure cloud, where you don't access Azure via the public portal, you will also need to add the following setting:
  • Still within the Configuration section, select the General settings section and turn on Web sockets.

  • Select Save to save the settings. This restarts the Azure App Service.

Confirm the extension and the bot are configured

  • In your browser, navigate to .azurewebsites.net/.bot. If everything is correct, the page will return this JSON content: {"v":"123","k":true,"ib":true,"ob":true,"initialized":true}. This is the information you obtain when everything works correctly, where

  • v displays the build version of the Direct Line App Service extension.

  • k determines whether the extension can read an extension key from its configuration. initialized determines whether the extension can use the extension key to download the bot metadata from Azure Bot Service.
  • ib determines whether the extension can establish an inbound connection with the bot.
  • ob determines whether the extension can establish an outbound connection with the bot.

Use Web Chat with the Direct Line App Service extension

Generally speaking, the approach is the same as before. With the exception that in version 4.9.1 or later of Web Chat there is built-in support for establishing a two-way WebSocket, which instead of connecting to directline.botframework.com connects directly to the Direct Line App Service extension hosted with your bot. The Direct Line URL for your bot will be .azurewebsites.net/.bot, the Direct Line endpoint on your app service extension. If you configure your own domain name, or your bot is hosted in a sovereign Azure cloud, substitute in the appropriate URL and append the /.bot/ path to access the Direct Line App Service extension's REST APIs.

Exchange the secret for a token by following the instructions in the Authentication article. Instead of obtaining a token at directline.botframework.com/v3/directline/t.., you will generate the token directly from your Direct Line App Service extension at .azurewebsites.net/.bot/v3/directline/token...

For an example that shows how to fetch a token see Web Chat Samples.

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <title>Web Chat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script
      crossorigin="anonymous"
      src="https://cdn.botframework.com/botframework-webchat/latest/webchat-minimal.js"
    ></script>
    <style>
      html,
      body {
        background-color: #f7f7f7;
        height: 100%;
      }

      body {
        margin: 0;
      }

      #webchat {
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
        height: 100%;
        margin: auto;
        max-width: 480px;
        min-width: 360px;
      }
    </style>
  </head>
  <body>
    <div id="webchat" role="main"></div>
    <script>
      (async function() {
        <!-- NOTE: It is highly recommended to replace the below fetch with a call to your own token service as described in step 2 above, and to avoid exposing your channel secret in client side code. -->
        const res = await fetch('https://<your_app_service>.azurewebsites.net/.bot/v3/directline/tokens/generate', { method: 'POST', headers:{'Authorization':'Bearer ' + '<Your Bot's Direct Line channel secret>'}});
        const { token } = await res.json();

        window.WebChat.renderWebChat(
          {
            directLine: await window.WebChat.createDirectLineAppServiceExtension({
              domain: 'https://<your_app_service>.azurewebsites.net/.bot/v3/directline',
              token
            })
          },
          document.getElementById('webchat')
        );

        document.querySelector('#webchat > *').focus();
      })().catch(err => console.error(err));
    </script>
  </body>
</html>

In the JavaScript bot implementation, make sure that WebSockets are enabled in the web.config file, as shown below.

<configuration>
    <system.webServer>
        <webSocket enabled="true"/>
        ...
    </system.webServer>
</configuration>

Troubleshooting

In this GitHub Repo i have integrated the SeriLog so that any issue you face after implementing this you can see the logs in log stream in app service by following this article:

Thanks.