Building your first chatbot using Microsoft Chatbot Framework for beginners - Part 1
This is how i started with my first chat bot adventure.
- Install Chatbot emulator.
- Install Visual studio template for chatbot.
Download and install Chatbot emulator from https://emulator.botframework.com/
Download and install Visual studio template from http://aka.ms/bf-bc-vstemplate
Now, you got tools to make your first chatbot locally.
First Chat bot
Create a new project in visual studio from the newly installed template called "Bot Application".
You can find that files created are similar to an Web API project.
Now, lets run this project and hook it to Emulator so we can test the default chatbot application that comes with "Bot Application" template. For running the project lets hit F5.
Restore all nuget packages if you have build errors. To restore then right click on project or solution. You will see a message like below.
Click on Restore and that should run the project with no errors. You will see below response in the browser.
As chatbot is like an API. All the requests and responses should go the EndPoints. If you see our files generated we have a folder called Controllers and class called MessagesController which will deal with messages endpoint and is inherited from APIController just like any other web API endpoint class.
Now start your emulator(botFrameWork emulator).
Ignore about Microsoft App ID and Microsoft App Password for now. We will come back to it later. Locale by default is en-us. Depends on what port number your application is running you need to add that to the emulator. Normally it will be on 3978 or 3979. So input http://localhost:3979/api/messages on the emulator. Details pane on the top right shows the details of the request and Log pane on the bottom right shows all the logs for the application.
Let's start interacting with ChatBot. Click on Connect and you are good to start typing.
You can see chatbot is responding to our chat. All it does here is echo your message and count the characters of your message.
Done, You have created your first chatbot.
Let's Discuss the code which created this response in our next blog post.
Creating multiple bots in single endpoint url
I get into to a problem last week where i want all my bots to be available in one single endpoint so i dont need to worry about domain names and SSL certificates for them.
I searched online and could not able to find an answer easily. So, i ended up writing what i have done. If you faced the same problem here it is.
Create MultiCredentialProvider class as below:
public class MultiCredentialProvider : ICredentialProvider
{
public Dictionary<string, string> Credentials = new Dictionary<string, string>
{
{ "AppId1", "AppPassword1" },
{ "AppId2", "AppPassword2" },
{ "AppId3", "AppPassword3" }
};
public Task<bool> IsValidAppIdAsync(string appId)
{
return Task.FromResult(this.Credentials.ContainsKey(appId));
}
public Task<string> GetAppPasswordAsync(string appId)
{
return Task.FromResult(this.Credentials.ContainsKey(appId) ? this.Credentials[appId] : null);
}
public Task<bool> IsAuthenticationDisabledAsync()
{
return Task.FromResult(!this.Credentials.Any());
}
}
Add this MultiCredentialProvider to your controller code:
[BotAuthentication(CredentialProviderType = typeof(MultiCredentialProvider))]
public class MessagesController : ApiController
{
static MessagesController()
{
// Update the container to use the right MicorosftAppCredentials based on
// Identity set by BotAuthentication
var builder = new ContainerBuilder();
builder.Register(c => ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims())
.AsSelf()
.InstancePerLifetimeScope();
builder.Update(Conversation.Container);
}
Add below to your ActivityTypes.ConversationUpdate:
IConversationUpdateActivity update = activity;
// resolve the connector client from the container to make sure that it is
// instantiated with the right MicrosoftAppCredentials
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var client = scope.Resolve<IConnectorClient>();
if (update.MembersAdded.Any())
{
var reply = activity.CreateReply();
foreach (var newMember in update.MembersAdded)
{
if (newMember.Id != activity.Recipient.Id)
{
reply.Text = $"Welcome {newMember.Name}!";
await client.Conversations.ReplyToActivityAsync(reply);
}
}
}
}
That's it. It should now handle multiple appIds and passwords with in the same endpoint URL.
Here is the full code:
// Use the MultiCredentialProvider as credential provider for BotAuthentication
[BotAuthentication(CredentialProviderType = typeof(MultiCredentialProvider))]
//[BotAuthentication]
public class MessagesController : ApiController
{
static MessagesController()
{
// Update the container to use the right MicorosftAppCredentials based on
// Identity set by BotAuthentication
var builder = new ContainerBuilder();
builder.Register(c => ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims())
.AsSelf()
.InstancePerLifetimeScope();
builder.Update(Conversation.Container);
}
/// <summary>
/// POST: api/Messages
/// receive a message from a user and send replies
/// </summary>
/// <param name="activity"></param>
[ResponseType(typeof(void))]
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
if (activity != null)
{
switch (activity.GetActivityType())
{
case ActivityTypes.Message:
await Conversation.SendAsync(activity, () => new RootDialog());
break;
case ActivityTypes.ConversationUpdate:
IConversationUpdateActivity update = activity;
// resolve the connector client from the container to make sure that it is
// instantiated with the right MicrosoftAppCredentials
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var client = scope.Resolve<IConnectorClient>();
if (update.MembersAdded.Any())
{
var reply = activity.CreateReply();
foreach (var newMember in update.MembersAdded)
{
if (newMember.Id != activity.Recipient.Id)
{
reply.Text = $"Welcome {newMember.Name}!";
await client.Conversations.ReplyToActivityAsync(reply);
}
}
}
}
break;
case ActivityTypes.ContactRelationUpdate:
case ActivityTypes.Typing:
case ActivityTypes.DeleteUserData:
case ActivityTypes.Ping:
default:
Trace.TraceError($"Unknown activity type ignored: {activity.GetActivityType()}");
break;
}
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}
Good luck!
RECENT POSTS
POPULAR POSTS
CATEGORIES
- sitecore-unicorn
- sitecore-contacts
- sitecore-xdb
- sitecore-handling-500-errors
- sitecore-bug
- sitecore-media-library
- sitecore-content-editor
- sitecore-patch
- personal-opinions
- programming
- sitecore-error
- sitecore-usermanager
- sitecore-languge-settings
- sitecore-content-language
- microsoft-Bot-Framework
- Chatbot-Beginners
- ChatBot-Emulator
- botFramework
- FirstChatBot
- chatbot
- sitecore-customroutes
- sitecore-api
- sitecore-buckets
- sitecore-wildcards
- sitecore-layoutdetails
- sitecore-modals
- sitecore-client
- sitecore-deviceeditor
- sitecore-best-practises
- sitecore-templates
- sitecore
- sitecore-scheduling
- sitecore-autopublish
- sitecore-autopublish
- extension-method
- sitecore-multisite
- sitecore-events
- sitecore-publishing
- sitecore8.1
- Rendering Parameters
- GlassMapper
- Sitecore