The Microsoft Bot Framework provides a template that creates a simple bot: The "Bot Builder Echo Bot". It is named this because it echoes back any text you send it, along with the length of that text.
The bot is simply an ASP.NET Web API application that exposes web services to Channel clients. As such, it uses the default routing for Web API applications of "api/controllername"
where controllername is the name of the Controller class with the word “Controller” removed.
A channel will submit an HTTP POST to a URL containing "api/message", which will call the Post method in the MessagesController class. Let's take a look at this class.
[BotAuthentication] public class MessagesController : ApiController { ////// POST: api/Messages /// Receive a message from a user and reply to it /// public async Task Post([FromBody]Activity activity) { if (activity.GetActivityType() == ActivityTypes.Message) { await Conversation.SendAsync(activity, () => new Dialogs.RootDialog()); } else { HandleSystemMessage(activity); } var response = Request.CreateResponse(HttpStatusCode.OK); return response; } private Activity HandleSystemMessage(Activity message) { string messageType = message.GetActivityType(); if (messageType == ActivityTypes.DeleteUserData) { // Implement user deletion here // If we handle user deletion, return a real message } else if (messageType == ActivityTypes.ConversationUpdate) { // Handle conversation state changes, like members being added and removed // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info // Not available in all channels } else if (messageType == ActivityTypes.ContactRelationUpdate) { // Handle add/remove from contact lists // Activity.From + Activity.Action represent what happened } else if (messageType == ActivityTypes.Typing) { // Handle knowing that the user is typing } else if (messageType == ActivityTypes.Ping) { } return null; }
Listing 1
A channel posts an activity to the service. If the activity type is anything other than "Message", it calls the HandleSystemMessage method. Notice that nothing is actually implemented in this method. You will have to write this yourself.
However, if the activity type is "Message", the Post method asynchronously calls the Dialogs.RootDialog class. Here is that class:
[Serializable] public class RootDialog : IDialog<object> { public Task StartAsync(IDialogContext context) { context.Wait(MessageReceivedAsync); return Task.CompletedTask; } private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) { var activity = await result as Activity; // Calculate something for us to return int length = (activity.Text ?? string.Empty).Length; // Return our reply to the user await context.PostAsync($"You sent {activity.Text} which was {length} characters"); context.Wait(MessageReceivedAsync); } }
Listing 2
The StartAsync method is called first, which waits for a message to be completely received; then, calls the MessageReceivedAsync method.
This method reads the text of the activity and forms a string that contains the original message text and the length of that text. It then Posts this back to the channel with the line below:
await context.PostAsync($"You sent {activity.Text} which was {length} characters");
Finally, it waits for the next message to come in via the following line
context.Wait(MessageReceivedAsync);
The rest of this project is Web API plumbing, setting up things like routing and where to store state information.
As you can see, this is a fairly simple architecture built on an established framework (Web API). This makes it easier to understand and to modify.
This simple bot is a good starting place that demonstrates the structure of a bot. You can modify this dialog, add new dialogs, or modify the logic as suits your purposes.