{"id":28469,"date":"2016-12-12T12:22:42","date_gmt":"2016-12-12T20:22:42","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=28469"},"modified":"2016-12-12T12:22:42","modified_gmt":"2016-12-12T20:22:42","slug":"add-yap-to-your-app-with-bot-framework","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/add-yap-to-your-app-with-bot-framework\/","title":{"rendered":"Add Yap to Your App with Bot Framework"},"content":{"rendered":"<p>\t\t\t\t<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/2016-12-14_13-57-09.gif\"><img decoding=\"async\" class=\"wp-image-29119 alignright\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/2016-12-14_13-57-09.gif\" alt=\"2016-12-14_13-57-09\" width=\"286\" height=\"421\" \/><\/a><\/p>\n<p>An emerging trend in technology\u00a0is the idea of conversational computing. Instead of issuing a series of commands via taps and clicks, commands will be extracted from natural conversations. We use conversation as an organic way to interact with analog world, and Xamarin makes it easy to add a native conversational interface to the digital world and to your next app. Combine the chat interface with the <a href=\"https:\/\/dev.botframework.com\/\">Microsoft Bot Framework<\/a>, and the end result is a natural, conversational dialog that will allow you to interact with your users in a new, but familiar, way.<\/p>\n<h2>A Chat Interface in Your App<\/h2>\n<p>The power of conversation as an interface is that the act of conversation is so natural, seamless and intuitive. To foster such an interaction, it is important the the UI feels natural as well. With Xamarin, we are able to design such an interface, one that fits perfectly within the expectations of the app platform. To demonstrate this, we are going to design an iOS chat interface, inspired by the <a href=\"https:\/\/github.com\/Microsoft\/XamarinAzure_ShoppingDemoApp\/\">Xamarin Shopping app<\/a>. We will design an interface that acts as a customer support chat client for the shopping app. To get started, we will create a <strong>Blank App (iPhone)<\/strong> in Visual Studio.<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" class=\"wp-image-28485 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/iOS_NewProject.png\" alt=\"ios_newproject\" width=\"550\" height=\"382\" \/><\/p>\n<p>Our iOS app is going to utilize a fantastic messaging view controller, called <code>JSQMessagesViewController<\/code>, which is available in the Xamarin Component Store. You should be able to add it to your app by opening the Component Store and adding <a href=\"https:\/\/components.xamarin.com\/view\/jsqmessagesviewcontroller\">JSQMessagesViewController<\/a> to the app.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-28486 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/viewcontrolcomp.png\" alt=\"viewcontrolcomp\" width=\"551\" height=\"360\" \/><\/p>\n<p>Furthermore, since we will be making some HTTP calls, we will need to add System.Net.Http via the <strong>Add Reference<\/strong> dialog.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-28487 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/systemnethttp.png\" alt=\"systemnethttp\" width=\"552\" height=\"381\" \/><\/p>\n<p>Now that we have those requirements in place, we can get down to the writing the code! Our first requirement will be to add a UIViewController to our app, which will host the chat interface. For the sample, I created a UIViewController named <code>ChatPageViewController<\/code>, with a base class of <code>MessagesViewController<\/code>.<\/p>\n<p>Once we have our view controller created, we must declare a few class level variables, and instantiate an HttpClient object to manage the communication with the Bot in Azure. Our class level variables should look as follows:<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 MessagesBubbleImage outgoingBubbleImageData, incomingBubbleImageData;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List messages = new List();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int messageCount = 0;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private HttpClient _client;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private Conversation _lastConversation;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string DirectLineKey = \"[Add Direct Line Key]\";\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Tracking of which user said what\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User sender = new User { Id = \"2CC8343\", DisplayName = \"You\" };\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User friend = new User { Id = \"BADB229\", DisplayName = \"Xamarin Bot\" };\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Holds the entire message history for a given session\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 MessageSet ms = new MessageSet();\n<\/pre>\n<p>Within the <code>ViewDidLoad<\/code> method, we need to must instantiate an HttpClient object using the class level variable we declared, as well as set a few view options, and print a welcome message.\u00a0The <code>ViewDidLoad<\/code> method should look similar to:<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override async void ViewDidLoad()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 base.ViewDidLoad();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CollectionView.BackgroundColor = new UIColor(red: 0.00f, green: 0.12f, blue: 0.31f, alpha: 1.0f);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Title = \"Xamarin Shopping Bot\";\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/instantiate an HTTPClient, and set properties to our DirectLine bot\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _client = new HttpClient();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _client.BaseAddress = new Uri(\"https:\/\/directline.botframework.com\/api\/conversations\/\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _client.DefaultRequestHeaders.Accept.Clear();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application\/json\"));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"BotConnector\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 DirectLineKey);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var response = await _client.GetAsync(\"\/api\/tokens\/\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (response.IsSuccessStatusCode)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var conversation = new Conversation();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HttpContent contentPost = new StringContent(JsonConvert.SerializeObject(conversation), Encoding.UTF8,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"application\/json\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 response = await _client.PostAsync(\"\/api\/conversations\/\", contentPost);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (response.IsSuccessStatusCode)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var conversationInfo = await response.Content.ReadAsStringAsync();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _lastConversation = JsonConvert.DeserializeObject(conversationInfo);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ You must set your senderId and display name\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SenderId = sender.Id;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SenderDisplayName = sender.DisplayName;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ These MessagesBubbleImages will be used in the GetMessageBubbleImageData override\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var bubbleFactory = new MessagesBubbleImageFactory();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 outgoingBubbleImageData = bubbleFactory.CreateOutgoingMessagesBubbleImage(UIColorExtensions.MessageBubbleLightGrayColor);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 incomingBubbleImageData = bubbleFactory.CreateIncomingMessagesBubbleImage(new UIColor(red: 0.88f, green: 0.07f, blue: 0.55f, alpha: 1.0f));\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Remove the AccessoryButton as we will not be sending pics\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 InputToolbar.ContentView.LeftBarButtonItem = null;\n\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Remove the Avatars\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CollectionView.CollectionViewLayout.IncomingAvatarViewSize = CoreGraphics.CGSize.Empty;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CollectionView.CollectionViewLayout.OutgoingAvatarViewSize = CoreGraphics.CGSize.Empty;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Load some messagees to start\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 messages.Add(new Message(friend.Id, friend.DisplayName, NSDate.DistantPast, \"I am the Shopping Bot!\"));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FinishReceivingMessage(true);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>As our <code>MessageViewController<\/code> is essentially a customized <code>UICollectionViewController<\/code>, we must add some methods in to build the\n<code>UICollectionView<\/code>.<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var cell = base.GetCell(collectionView, indexPath) as MessagesCollectionViewCell;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Override GetCell to make modifications to the cell\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ In this case darken the text for the sender\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var message = messages[indexPath.Row];\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (message.SenderId == SenderId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cell.TextView.TextColor = UIColor.Black;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return cell;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override nint GetItemsCount(UICollectionView collectionView, nint section)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return messages.Count;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override IMessageData GetMessageData(MessagesCollectionView collectionView, NSIndexPath indexPath)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return messages[indexPath.Row];\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override IMessageBubbleImageDataSource GetMessageBubbleImageData(MessagesCollectionView collectionView, NSIndexPath indexPath)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var message = messages[indexPath.Row];\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (message.SenderId == SenderId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return outgoingBubbleImageData;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return incomingBubbleImageData;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override IMessageAvatarImageDataSource GetAvatarImageData(MessagesCollectionView collectionView, NSIndexPath indexPath)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>Finally, we have a few classes to create to handle our messages and identities.<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0 public class MessageSet\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public BotMessage[] messages { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string watermark { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string eTag { get; set; }\n\n\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0 public class BotMessage\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string id { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string conversationId { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public DateTime created { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string from { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string text { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string channelData { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string[] images { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public Attachment[] attachments { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string eTag { get; set; }\n\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0 public class Attachment\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string url { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string contentType { get; set; }\n\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0 public class Conversation\n\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string conversationId { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string token { get; set; }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string eTag { get; set; }\n\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>Now that we have all of our objects created and variables set, we can get down to the business of sending and receiving messages from our Bot! Our first task is to respond to the button click on the &#8220;send&#8221; button. Here we want to gather the message, display some indicators, and send the message to our Bot:<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override async void PressedSendButton(UIButton button, string text, string senderId, string senderDisplayName, NSDate date)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Clear the text and play a send sound\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 InputToolbar.ContentView.TextView.Text = \"\";\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 InputToolbar.ContentView.RightBarButtonItem.Enabled = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SystemSoundPlayer.PlayMessageSentSound();\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/set message details and add to the message queue\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var message = new Message(\"2CC8343\", \"You\", NSDate.Now, text);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 messages.Add(message);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FinishReceivingMessage(true);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Show typing indicator to add to the natual feel of the bot\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ShowTypingIndicator = true;\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/send message to bot and await the message set\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ms = await SendMessage(text);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/iterate through our message set, and print new messasges from the bot\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while (ms.messages.Length &gt; messageCount)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (ms.messages[messageCount].from == \"XamarinBot\")\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ScrollToBottom(true);\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SystemSoundPlayer.PlayMessageReceivedSound();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messageBot = new Message(friend.Id, friend.DisplayName, NSDate.Now, ms.messages[messageCount].text);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 messages.Add(messageBot);\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FinishReceivingMessage(true);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 InputToolbar.ContentView.RightBarButtonItem.Enabled = true;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 messageCount++;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>Now we come down to our last bit of code for our view controller, which is the <code>SendMessage<\/code> method. Here, we take the text input from <code>PressedSendButton<\/code> and communicate with our Bot via DirectLine.<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public async Task SendMessage(string messageText)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messageToSend = new BotMessage() { text = messageText, conversationId = _lastConversation.conversationId };\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var contentPost = new StringContent(JsonConvert.SerializeObject(messageToSend), Encoding.UTF8, \"application\/json\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var conversationUrl = \"https:\/\/directline.botframework.com\/api\/conversations\/\" + _lastConversation.conversationId + \"\/messages\/\";\n\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var response = await _client.PostAsync(conversationUrl, contentPost);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messageInfo = await response.Content.ReadAsStringAsync();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messagesReceived = await _client.GetAsync(conversationUrl);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messagesReceivedData = await messagesReceived.Content.ReadAsStringAsync();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var messages = JsonConvert.DeserializeObject(messagesReceivedData);\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return messages;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 catch (Exception ex)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(ex.Message);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>Finally, we must use the AppDelegate to launch the <code>ChatPageViewController<\/code> when the application is opened, and we do this via:<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public override bool FinishedLaunching(UIApplication app, NSDictionary options)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ create a new window instance based on the screen size\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 window = new UIWindow(UIScreen.MainScreen.Bounds);\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ If you have defined a root view controller, set it here:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 window.RootViewController = new UINavigationController(new ChatPageViewController());\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ make the window visible\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 window.MakeKeyAndVisible();\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>Now that the app is designed, we will want to configure a bot for the conversation.<\/p>\n<h2>Adding Microsoft Bot Framework<\/h2>\n<p>The bot service consists of two parts, one being the <a href=\"https:\/\/www.luis.ai\/\">language processor (LUIS)<\/a> and the other being the Bot Service application, which we will host in Azure. For our purposes, we are going to import a custom LUIS app created for this sample. To get LUIS configured, you will want to go to\u00a0<a href=\"https:\/\/luis.ai\">luis.ai<\/a> and sign in using your Microsoft account. Once on the main page, you will want click on &#8220;New App&#8221; and then &#8220;Import Existing App&#8221;.\u00a0 You can download the LUIS app in JSON format from <a href=\"https:\/\/gist.github.com\/anonymous\/6ac446635e316ec8399f66198b4be490\">GitHub<\/a>.<\/p>\n<p>Now that we have a LUIS service created, it is time to get busy creating the Bot application! You may have noticed that for the client, we only need to make a few HTTP calls. This is because most of the processing for the conversation is done within the Bot Service application. This allows you to use the exact same Bot service for many different platforms, including integrations such as Skype. To get started, you will want to ensure that you have the bot template installed. These items can be downloaded from the <a href=\"http:\/\/(https:\/\/docs.botframework.com\/en-us\/downloads\">Bot Framework page<\/a>.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-28490 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/newproject.png\" alt=\"newproject\" width=\"550\" height=\"382\" \/><\/p>\n<p>The bot project consists of a controller and a dialog. The template includes a default controller which will echo input back to the user. Once we have our dialog configured, we will circle back to our controller and tell it to use the newly created dialog. To create the dialog, add a new class file to your project, naming it something reasonable. The class itself should inherit from the base class of <code>LuisDialog<\/code> and you will also want to mark the class as <code>[Serializable]<\/code>.<\/p>\n<p>Within the class we just created, we need to create a method for each Intent defined within our LUIS app.<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [LuisIntent(\"\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public async Task None(IDialogContext context, LuisResult result)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string message = \"Sorry, I do not understand. Try asking me for order information or customer service help\";\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 await context.PostAsync(message);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 context.Done(true);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n<\/pre>\n<p>As you can see from the code snippet, we create a &#8220;public async&#8221; method which returns a <code>Task<\/code> and takes an <code>IDialogContext<\/code> and a <code>LuisResult<\/code> as inputs. The <code>IDialogContext<\/code> is the conversation that is taking place, while the <code>LuisResult<\/code> is the JSON string returned from the LUIS service. Furthermore, the method is marked with an attribute of <code>[LuisIntent(\"\")]<\/code>, which denotes which LUIS Intent the given method is designed to respond to. When the Intent is blank, it becomes the catchall for any utterance which can&#8217;t be matched to a known intent. If this method were intended to handle all utterances that are matched with the &#8220;Customer Service&#8221; intent, we would mark this method with the attribute <code>[LuisIntent(\"CustomerService\")]<\/code>. However, as this is the catchall intent, we want inform the user that we could not understand what was said, and to suggest some things they can ask about. We post the message to the user via <code>context.PostAsync(message)<\/code> and mark this conversation as complete.<\/p>\n<p>For more complex conversations, or for conversations where data lookups or other tasks need to occur, there may\u00a0 be a need to call upon other methods from one of our <code>LuisIntent<\/code> marked methods. For example, the following snippet from a <code>LuisIntent<\/code> marked method denotes a completion handler to call upon receiving the results of a question prompted to the user.<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [LuisIntent(\"CustomerService\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public async Task customerServiceRequest(IDialogContext context, LuisResult result)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach(var entity in result.Entities)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (entity.Type == \"ServiceKeyword\" &amp;&amp; customerSupportKeywords.Contains(entity.Entity.ToLower()))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 switch(entity.Entity.ToLower())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case \"password\":\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PromptDialog.Text(context, SupportUsernameEntered, \"What is the email address associated with your account?\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n                    }\n                    [...]\n                }\n            }\n        }\n<\/pre>\n<p>In this truncated method, we detect that the user is asking a question regarding their password, so we want to verify the user by requesting their email address. <code>PromptDialog.Text<\/code> requests information from the user, and contains a completion handler which calls <code>SupportUsernameEntered<\/code>.<\/p>\n<pre class=\"\">        private async Task SupportUsernameEntered(IDialogContext context, IAwaitable result)\n        {\n            var item = await result;\n            {\n                if (Account.IsFound(item))\n                {\n                    [...send email...]\n                    await context.PostAsync(\"Account was found, we've sent a reset email to your registered email account\");\n                    context.Done(true);\n                }\n                [..]\n            }\n        }\n<\/pre>\n<p>Within this method, we confirm the account, and send a reset email if the account is found. Once this email is sent, we can consider this interaction completed and end the conversation. In order to have a natural dialog between the user and the app, the Bot service should include many of these conversation paths. Much of these child actions can be defined in LUIS as well, though in our example the conversation is more basic and linear.<\/p>\n<p>Now that we have a basic Bot created, we will need to publish the Bot to Azure. For our purposes, the <a href=\"https:\/\/docs.botframework.com\/en-us\/csharp\/builder\/sdkreference\/gettingstarted.html\">official documentation<\/a> should be followed.<\/p>\n<p>Finally, we need to set up a service to communicate with the bot in Azure, using a service called Direct Line. This is a simple REST service which allows for communication between a custom client and the Bot. The <a href=\"https:\/\/docs.botframework.com\/en-us\/restapi\/directline\/\">Direct Line documentation<\/a> covers the steps required to connect DirectLine to your bot instance. Once Direct Line is configured, you must modify the DirectLineKey variable within your iOS View Controller to match the API Key for Direct Line.<\/p>\n<p style=\"text-align: left\">And that&#8217;s it! If we run our app, we can have a realistic conversation with our Bot, as seen below:<\/p>\n<p style=\"text-align: left\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/sd.png\"><img decoding=\"async\" class=\"size-full wp-image-29121 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/sd.png\" alt=\"sd\" width=\"489\" height=\"738\" \/><\/a><\/p>\n<p>The Microsoft Bot Framework is an incredibly powerful system, and we have only scratched the surface of what is possible. To try out the full sample, download it from <a href=\"https:\/\/go.microsoft.com\/fwlink\/?linkid=837780\">GitHub<\/a>.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An emerging trend in technology\u00a0is the idea of conversational computing. Instead of issuing a series of commands via taps and clicks, commands will be extracted from natural conversations. We use conversation as an organic way to interact with analog world, and Xamarin makes it easy to add a native conversational interface to the digital world [&hellip;]<\/p>\n","protected":false},"author":561,"featured_media":29119,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5,6,4,16],"class_list":["post-28469","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-android","tag-ios","tag-xamarin-platform","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>An emerging trend in technology\u00a0is the idea of conversational computing. Instead of issuing a series of commands via taps and clicks, commands will be extracted from natural conversations. We use conversation as an organic way to interact with analog world, and Xamarin makes it easy to add a native conversational interface to the digital world [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/28469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=28469"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/28469\/revisions"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=28469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=28469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=28469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}