Calling The Microsoft Bot Framework Using The Direct Line API

Oct 9

Written by:
10/9/2016 12:05 AM  RssIcon

image

You may need to call your Microsoft Bot Framework Bot directly from a custom application, a service, or a website. The Microsoft Bot Connector Direct Line REST API allows you to do this. In addition, it allows you to authenticate a user in your application, and securely communicate with the Bot as that user.

image

The Direct Line API exposes a REST API that allows you to communicate with a single Bot that has been registered with the Microsoft Bot Connector Service. This API is intended for developers who want to communicate with their Bot from their own client applications, such as mobile apps, a service, or even a HoloLens.

image

The procedure for working with the API is:

  1. Register your Bot with the Microsoft Bot Connector
  2. Configure the Direct Line Connector
  3. Use the credentials obtained from the Bot Framework developer portal to make REST based calls to communicate with the Bot (in our example, we will use the Microsoft.Bot.Connector.DirectLine Nuget package to help us make the calls).

image

Note, the rendering of the output will be the responsibility of the developer of the custom application that is calling the Direct Line API.

Media such a images, cards, and buttons will require custom code to render in a manner that is appropriate for the particular application.

image

The example application we will build, will create a custom client that will allow a user to create an account, sign-in, and securely communicate with the same Bot that was deployed in the article: Creating a Skype Bot Using The Microsoft Bot Framework and updated and enhanced in the article: Implementing Language Understanding Intelligent Service (LUIS) In Microsoft Bot Framework.

Configuring The Direct Line Connector

image

We want to configure the Direct Line connector for our Bot.

Go to: https://dev.botframework.com/, log in, and select My Bots.

Open a Bot that has been deployed (using the directions in the article: Creating a Skype Bot Using The Microsoft Bot Framework and further enhanced in the article: Implementing Language Understanding Intelligent Service (LUIS) In Microsoft Bot Framework).

image

The first step is to make a note of the Bot handle you gave your Bot. You will need this later when you create the Web Application.

image

Under Add another channel, click the Add button next to Direct Line.

image

When the Configure Direct Line screen appears, click the Generate Direct Line secret button.

 

image

Copy the Secret code. You will need this later when you create the Web Application.

Click the I’m done configuring Direct Line button.

The screen will close.

Create The Web Application

image

Open Visual Studio.

image

From the toolbar in Visual Studio, select File, then New, then Project.

image

Select Web, then ASP.NET Web Application (.Net Framework).

Enter DirectLineBot for the Name.

Select the Create directory for solution box.

Press OK.

image

When the application configuration box appears, select the MVC template.

Ensure that Individual User Accounts is selected for Authentication (if not, click the Change Authentication button and change it).

Press OK.

image

The application will be created.

image

We need to add the Microsoft.Bot.Connector.DirectLine Nuget package that will allow us to easily communicate with the DirectLine API.

In the Solution Explorer, right-click on the DirectLineBot project node (not the Solution node), and select Manage Nuget Packages.

image

When the Nuget Packages configuration window appears…

Click the Browse button.

Enter Microsoft.Bot.Connector.DirectLine in the search box to conduct the search.

When the Microsoft.Bot.Connector.DirectLine package shows up, click on it (so that it’s properties appears in the window on the right).

Click the Install button to install the package.

image

Click Ok when the Preview window shows.

image

Click the I Accept button when the License Acceptance window appears.

image

The Microsoft.Bot.Connector.DirectLine assembly will be installed.

image

Hit F5 to debug and run the application.

The application will open in the web browser.

image

You will see that the default web application, created by the MVC template, contains an About and a Contact page. We can stop the application (by closing the web browser), and remove the code for these pages because we don’t need them.

If you don’t know how to do that, you can leave them in the application (note: You can download the completed application from the downloads page on this site).

What we do care about is the ability to click the Register button to create a new account.

We can also click the Log in button to log in using a registered account.

Complete The Web Application

image

We will update the home page to show the chat box and the Bot response only if the user has created an account and logged in.

Open the Index.cshtml file (in the Views/Home folder), and replace all the code with the following code:

 

@model DirectLine.Controllers.Chat
<h2>Direct Line Bot Example</h2>
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    <p>
        Hello: @((User.Identity.IsAuthenticated == true)
        ? User.Identity.Name
        : "[Unknown]")
    </p>
    @Html.TextBoxFor(m => m.ChatMessage,
    new { style = "width:600px" })
    <input type="submit" value="Send" />
}
<br />
<p>@Html.Raw(Model.ChatResponse)</p>

 

image

Open the HomeController.cs file (in the Controllers folder), and replace all the code with the following code:

 

using Microsoft.Bot.Connector.DirectLine;
using Microsoft.Bot.Connector.DirectLine.Models;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace DirectLine.Controllers
{
    #region public class Chat
    public class Chat
    {
        public string ChatMessage { get; set; }
        public string ChatResponse { get; set; }
        public string watermark { get; set; }
    }
    #endregion
    public class HomeController : Controller
    {
        private static string DiretlineUrl
            = @"https://directline.botframework.com";
        private static string directLineSecret =
            "** INSERT YOUR SECRET CODE HERE **";
        private static string botId =
            "** INSERT YOUR BOTID HERE **";
        #region public async Task<ActionResult> Index()
        public async Task<ActionResult> Index()
        {
            // Create an Instance of the Chat object
            Chat objChat = new Chat();
            // Only call Bot if logged in
            if (User.Identity.IsAuthenticated)
            {
                // Pass the message to the Bot 
                // and get the response
                objChat = await TalkToTheBot("Hello");
            }
            else
            {
                objChat.ChatResponse = "Must be logged in";
            }
            // Return response
            return View(objChat);
        }
        #endregion
    }
}

 

At this point the code is not complete, however, it sets up the basic framework.

Remember to replace, ** INSERT YOUR SECRET CODE HERE ** and ** INSERT YOUR BOTID HERE ** with the values from you own published Bot.

When a logged in user loads the page, or submits text to the Bot, the TalkToTheBot method is called.

To implement it, add the following method to the HomeController class:

 

        #region private async Task<Chat> TalkToTheBot(string paramMessage)
        private async Task<Chat> TalkToTheBot(string paramMessage)
        {
            // Connect to the DirectLine service
            DirectLineClient client = new DirectLineClient(directLineSecret);
            // Try to get the existing Conversation
            Conversation conversation =
                System.Web.HttpContext.Current.Session["conversation"] as Conversation;
            // Try to get an existing watermark 
            // the watermark marks the last message we received
            string watermark =
                System.Web.HttpContext.Current.Session["watermark"] as string;
            if (conversation == null)
            {
                // There is no existing conversation
                // start a new one
                conversation = client.Conversations.NewConversation();
            }
            // Use the text passed to the method (by the user)
            // to create a new message
            Message message = new Message
            {
                FromProperty = User.Identity.Name,
                Text = paramMessage
            };
            // Post the message to the Bot
            await client.Conversations.PostMessageAsync(conversation.ConversationId, message);
            // Get the response as a Chat object
            Chat objChat =
                await ReadBotMessagesAsync(client, conversation.ConversationId, watermark);
            // Save values
            System.Web.HttpContext.Current.Session["conversation"] = conversation;
            System.Web.HttpContext.Current.Session["watermark"] = objChat.watermark;
            // Return the response as a Chat object
            return objChat;
        }
        #endregion

 

The TalkToTheBot method calls the ReadBotMessagesAsync method to read the response from the Bot.

To implement it, add the following method to the HomeController class:

 

        #region 
        private async Task<Chat> ReadBotMessagesAsync(
            DirectLineClient client, string conversationId, string watermark)
        {
            // Create an Instance of the Chat object
            Chat objChat = new Chat();
            // We want to keep waiting until a message is received
            bool messageReceived = false;
            while (!messageReceived)
            {
                // Get any messages related to the conversation since the last watermark 
                var messages =
                    await client.Conversations.GetMessagesAsync(conversationId, watermark);
                // Set the watermark to the message received
                watermark = messages?.Watermark;
                // Get all the messages 
                var messagesFromBotText = from message in messages.Messages
                                          where message.FromProperty == botId
                                          select message;
                // Loop through each message
                foreach (Message message in messagesFromBotText)
                {
                    // We have Text
                    if (message.Text != null)
                    {
                        // Set the text response
                        // to the message text
                        objChat.ChatResponse
                            += " "
                            + message.Text.Replace("\n\n", "<br />");
                    }
                    // We have an Image
                    if (message.Images.Count > 0)
                    {
                        // Set the text response as an HTML link
                        // to the image
                        objChat.ChatResponse
                            += " "
                            + RenderImageHTML(message.Images[0]);
                    }
                }
                // Mark messageReceived so we can break 
                // out of the loop
                messageReceived = true;
            }
            // Set watermark on the Chat object that will be 
            // returned
            objChat.watermark = watermark;
            // Return a response as a Chat object
            return objChat;
        }
        #endregion

 

 

When there is an image that is returned by the Bot, the ReadBotMessagesAsync method calls the RenderImageHTML method.

To implement it, add the following method to the HomeController class:

 

        #region private static string RenderImageHTML(string ImageLocation)
        private static string RenderImageHTML(string ImageLocation)
        {
            // Construct a URL to the image
            string strReturnHTML =
                String.Format(@"<img src='{0}/{1}'><br />",
                DiretlineUrl,
                ImageLocation);
            return strReturnHTML;
        }
        #endregion

 

Run The Application

image

Hit F5 to run the application.

The application will open in the web browser. Initially we are not logged in so we will be unable to communicate with the Bot.

image

Click the Register button to create an account.

image

Fill in the required information and click the Register button.

image

After you have created an account, you can click the Log in button to log in (if you are not already logged in).

image

You will know you are logged in when you see your email address in the menu bar and on the Home page.

image

You can now communicate with the Bot and run the same code that was created and deployed in the article: Implementing Language Understanding Intelligent Service (LUIS) In Microsoft Bot Framework.

image

When we look at the data in the database on Azure (see: Implementing A SQL Server Database With The Microsoft Bot Framework to see how this is configured and deployed), we see that the UserID, and UserName, for messages posted to the Bot, are completely under the control of the following custom code:

 

    // Use the text passed to the method (by the user)
    // to create a new message
    Message message = new Message
    {
        FromProperty = User.Identity.Name,
        Text = paramMessage
    };
    // Post the message to the Bot
    await client.Conversations.PostMessageAsync(conversation.ConversationId, message);

 

This demonstrates that we are able to authenticate users using our own custom code, and have them communicate with the Bot securely, when using the Direct Line API.

 

Ai Help Website Links

Creating a Hello World! Bot Using The Microsoft Bot Framework

Creating a Skype Bot Using The Microsoft Bot Framework

Implementing Language Understanding Intelligent Service (LUIS) In Microsoft Bot Framework

Microsoft Links

Microsoft Bot Framework

Bot Builder (GitHub)

Bot Framework Forum (stack overflow)

Direct Line REST API

Direct Line Nuget package

Download

You can download the code from the Download page

10 comment(s) so far...


Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

Question: In your sample code the only message you ever send is "Hello". No matter what is entered into the text box. (objChat = await TalkToTheBot("Hello");) Can you fix it up to submit actual text?

By markbschramm on   11/17/2016 4:38 PM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

When you download the code, you will see another method:

[HttpPost]
public async Task Index(Chat model)
{
// Create an Instance of the Chat object
Chat objChat = new Chat();

// Only call Bot if logged in
if (User.Identity.IsAuthenticated)
{
// Pass the message to the Bot
// and get the response
objChat = await TalkToTheBot(model.ChatMessage);
}
else
{
objChat.ChatResponse = "Must be logged in";
}

// Return response
return View(objChat);
}


This method is called when you input text into the text box. That method will pass what you type to the TalkToTheBot method.

By Administrator on   11/17/2016 7:27 PM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

y si no tengo ningun login solamente quiero probar de esa manera mi bots?, que necesito hacer
(Translated: And if I do not have any login I just want to try that way my bots ?, what I need to do)

By perdomo24 on   12/2/2016 10:27 AM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

@perdomo24 - You can remove the code that requires you to be logged into the web site. I do not have an example, sorry.

By Administrator on   12/2/2016 11:02 AM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

I'm getting this error:

Operation returned an invalid status code 'InternalServerError'

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'InternalServerError'



On line 107 (HomeController.cs)

await client.Conversations.PostMessageAsync(conversation.ConversationId, message);


By Marcio on   12/5/2016 5:21 AM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

@Marcio - Please post a message to the forums on this site. Also, you will need more information such as are you connecting to your own bot? Are you using your own code or the sample downloaded from this site?

By Administrator on   12/5/2016 5:47 AM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

With the Direct Line API can i use the features of Form Flow and Dialog's the code which was given in this article.
[ aihelpwebsite.com/Blog/EntryId/8/Introduction-To-FormFlow-With-The-Microsoft-Bot-Framework ]
and
[ aihelpwebsite.com/Blog/EntryId/9/Introduction-To-Using-Dialogs-With-The-Microsoft-Bot-Framework ]

By demo4 on   12/25/2016 11:05 PM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

@demo4 - Yes, the Directline will call your normal BotFramework code, so if it uses Dialogs or FormView that code will continue to work. However, at the time of this writing there is a bug when you use DirectLine with LUIS. See: github.com/Microsoft/BotBuilder/issues/1549

By Administrator on   12/26/2016 5:23 AM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

I have developed a bot using C# and deployed it using direct line api. I are trying to find a way for the bot to receive a parameter from the website when it initially loads. I want the same bot to work on different websites and want the bot to recognize the website using this parameter sent by the website to the bot and then act according to that website. Is there a way to take a parameter from the website automatically when it loads ?

By nupur on   6/18/2017 9:18 PM
Gravatar

Re: Calling The Microsoft Bot Framework Using The Direct Line API

@nupur - In your Bot code you can determine when a user response is coming from Directline or other channels. If you have further questions please post to the forums on this site.

By Administrator on   6/19/2017 4:35 AM