Getting Started Adaptive Card Design Using Microsoft Bot Framework
The Bot Framework has supported the different type of rich cards and provides a richer interaction experience to the user. In this article, I will share about how to integrate adaptive card UI design in Bot Application. The Adaptive Card can contain any combination of text, speech, images, buttons, and input controls.Adaptive Cards are created using the JSON format specified in Adaptive Cards schema and Microsoft provided Microsoft.AdaptiveCards NuGet package for .Net Developer to building these cards and handles the serialization.
I have explained about Bot framework Installation, deployment and implementation in the below article
Getting Started with Chatbot Using Azure Bot Service
Getting Started with Bots Using Visual Studio 2017
Deploying A Bot to Azure Using Visual Studio 2017
How to Create ChatBot In Xamarin
Getting Started with Dialog Using Microsoft Bot Framework
Getting Started with Prompt Dialog Using Microsoft Bot Framework
Getting Started With Conversational Forms And FormFlow Using Microsoft Bot Framework
Getting Started With Customizing A FormFlow Using Microsoft Bot Framework
Sending Bot Reply Message With Attachment Using Bot Framework
Getting Started with Chatbot Using Azure Bot Service
Getting Started with Bots Using Visual Studio 2017
Deploying A Bot to Azure Using Visual Studio 2017
How to Create ChatBot In Xamarin
Getting Started with Dialog Using Microsoft Bot Framework
Getting Started with Prompt Dialog Using Microsoft Bot Framework
Getting Started With Conversational Forms And FormFlow Using Microsoft Bot Framework
Getting Started With Customizing A FormFlow Using Microsoft Bot Framework
Sending Bot Reply Message With Attachment Using Bot Framework
Create New Bot Application
Let's create a new bot application using Visual Studio 2017. Open Visual Studio > Select File > Create New Project (Ctrl + Shift +N) > Select Bot application.
The Bot application template was created with all the components and all required NuGet references installed in the solutions.
The Microsoft.AdaptiveCards library implements classes for building and serializing adaptive card objects and Visual studio intelligent will help us for implement Adaptive card in the bot application.
The Bot application template was created with all the components and all required NuGet references installed in the solutions.
Install AdaptiveCard Nuget package
The Microsoft.AdaptiveCards library implements classes for building and serializing adaptive card objects and Visual studio intelligent will help us for implement Adaptive card in the bot application.
Right click on Solution > Select Manage NuGet Package for Solution > Search “ Microsoft AdaptiveCards” > select Project and Install the package
Create New AdaptiveCardDialog Class
Step 1: You can Create new AdaptiveCardDialog class for a show the Adaptive dialog. Right Click on project > Select Add New Item > Create a class that is marked with the [Serializable] attribute (so the dialog can be serialized to state) and implement the IDialog interface.using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using System.IO;
using System.Web;
using System.Collections.Generic;
namespace BotAdaptiveCard.Dialogs
{
[Serializable]
public class AdaptiveCardDialog: IDialog<object>
{
Step 2
IDialog interface has only StartAsync() method. StartAsync() is called when the dialog becomes active. The method is passed the IDialogContext object, used to manage the conversation.
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
Step 3: Create a MessageReceivedAsync method and write following code for the welcome message and show the list of demo options dialog. [Serializable]
{
context.Wait(this.MessageReceivedAsync);
}
Step 3: Create a MessageReceivedAsync method and write following code for the welcome message and show the list of demo options dialog. [Serializable]
public class AdaptiveCardDialog : IDialog<object>
{
public Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
return Task.CompletedTask;
}
private readonly IDictionary<string, string> options = new Dictionary<string, string>
{
{ "1", "1. Show Demo Adaptive Card " },
{ "2", "2. Show Demo for Adaptive Card Design with Column" },
{"3" , "3. Input Adaptive card Design" }
};
public async virtual Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
var welcomeMessage = context.MakeMessage();
welcomeMessage.Text = "Welcome to bot Adaptive Card Demo";
await context.PostAsync(welcomeMessage);
this.DisplayOptionsAsync(context);
}
public void DisplayOptionsAsync(IDialogContext context)
{
PromptDialog.Choice<string>(
context,
this.SelectedOptionAsync,
this.options.Keys,
"What Demo / Sample option would you like to see?",
"Please select Valid option 1 to 6",
6,
PromptStyle.PerLine,
this.options.Values);
}
public async Task SelectedOptionAsync(IDialogContext context, IAwaitable<string> argument)
{
var message = await argument;
var replyMessage = context.MakeMessage();
Attachment attachment = null;
switch (message)
{
case "1":
attachment = CreateAdapativecard();
replyMessage.Attachments = new List<Attachment> { attachment };
break;
case "2":
attachment = CreateAdapativecardWithColumn();
replyMessage.Attachments = new List<Attachment> { attachment };
break;
case "3":
replyMessage.Attachments = new List<Attachment> { CreateAdapativecardWithColumn(), CreateAdaptiveCardwithEntry() };
break;
}
await context.PostAsync(replyMessage);
this.DisplayOptionsAsync(context);
}
After user enter the first message, bot will reply welcome message and list of demo option and wait for user input like below
{
public Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
return Task.CompletedTask;
}
private readonly IDictionary<string, string> options = new Dictionary<string, string>
{
{ "1", "1. Show Demo Adaptive Card " },
{ "2", "2. Show Demo for Adaptive Card Design with Column" },
{"3" , "3. Input Adaptive card Design" }
};
public async virtual Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
var welcomeMessage = context.MakeMessage();
welcomeMessage.Text = "Welcome to bot Adaptive Card Demo";
await context.PostAsync(welcomeMessage);
this.DisplayOptionsAsync(context);
}
public void DisplayOptionsAsync(IDialogContext context)
{
PromptDialog.Choice<string>(
context,
this.SelectedOptionAsync,
this.options.Keys,
"What Demo / Sample option would you like to see?",
"Please select Valid option 1 to 6",
6,
PromptStyle.PerLine,
this.options.Values);
}
public async Task SelectedOptionAsync(IDialogContext context, IAwaitable<string> argument)
{
var message = await argument;
var replyMessage = context.MakeMessage();
Attachment attachment = null;
switch (message)
{
case "1":
attachment = CreateAdapativecard();
replyMessage.Attachments = new List<Attachment> { attachment };
break;
case "2":
attachment = CreateAdapativecardWithColumn();
replyMessage.Attachments = new List<Attachment> { attachment };
break;
case "3":
replyMessage.Attachments = new List<Attachment> { CreateAdapativecardWithColumn(), CreateAdaptiveCardwithEntry() };
break;
}
await context.PostAsync(replyMessage);
this.DisplayOptionsAsync(context);
}
After user enter the first message, bot will reply welcome message and list of demo option and wait for user input like below
Step 4: Design Adaptive Card
The Adaptive Cards are created using JSON, but with the Microsoft.AdaptiveCards NuGet we can create them by composing card objects. We can create AdaptiveCard objects and attach to the attachment and post message to a message
The following code showing design the welcome message with image, textblock and speech.
public Attachment CreateAdapativecard()
{
AdaptiveCard card = new AdaptiveCard();
// Specify speech for the card.
card.Speak = "Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com";
// Body content
card.Body.Add(new Image()
{
Url = "https://i1.social.s-msft.com/profile/u/avatar.jpg?displayname=j%20suthahar&size=extralarge&version=88034ca2-9db8-46cd-b767-95d17658931a",
Size = ImageSize.Small,
Style = ImageStyle.Person,
AltText = "Suthahar Profile"
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "Technical Lead and C# Corner MVP",
Size = TextSize.Large,
Weight = TextWeight.Bolder
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "jssutahhar@gmail.com"
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "97XXXXXX12"
});
// Create the attachment with adapative card.
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will generate adaptive card and reply to the user
public Attachment CreateAdapativecard()
{
AdaptiveCard card = new AdaptiveCard();
// Specify speech for the card.
card.Speak = "Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com";
// Body content
card.Body.Add(new Image()
{
Url = "https://i1.social.s-msft.com/profile/u/avatar.jpg?displayname=j%20suthahar&size=extralarge&version=88034ca2-9db8-46cd-b767-95d17658931a",
Size = ImageSize.Small,
Style = ImageStyle.Person,
AltText = "Suthahar Profile"
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "Technical Lead and C# Corner MVP",
Size = TextSize.Large,
Weight = TextWeight.Bolder
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "jssutahhar@gmail.com"
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "97XXXXXX12"
});
// Create the attachment with adapative card.
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will generate adaptive card and reply to the user
Step 5: Design Adaptive Card with Column
The Adaptive Cards contain many elements that allow to design UI content in a common and consistent way.
Container - A Container is a CardElement which contains a list of CardElements that are logically grouped.
ColumnSet and Column - The columnSet element adds the ability to have a set of Column objects and align the column object.
FactSet - The FactSet element is displayed row and column like a tabular form.
TextBlock - The TextBlock element allows for the inclusion of text, we can modify font sizes, weight and color.
ImageSet and Image - The ImageSet allows for the inclusion of a collection images like a photo set, and the Image element allows for the inclusion of images.
The following code showing, adding multiple columns and design the UI Adaptive Card
public Attachment CreateAdapativecardWithColumn()
{
AdaptiveCard card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
// Container
new Container()
{
Speak = "<s>Hello!</s><s>Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com</s>",
Items = new List<CardElement>()
{
// first column
new ColumnSet()
{
Columns = new List<Column>()
{
new Column()
{
Size = ColumnSize.Auto,
Items = new List<CardElement>()
{
new Image()
{
Url = "https://i1.social.s-msft.com/profile/u/avatar.jpg?displayname=j%20suthahar&size=extralarge&version=88034ca2-9db8-46cd-b767-95d17658931a",
Size = ImageSize.Small,
Style = ImageStyle.Person
}
}
},
new Column()
{
Size = "300",
Items = new List<CardElement>()
{
new TextBlock()
{
Text = "Suthahar Jegatheesan MCA",
Weight = TextWeight.Bolder,
IsSubtle = true
},
new TextBlock()
{
Text = "jssuthahar@gmail.com",
Weight = TextWeight.Lighter,
IsSubtle = true
},
new TextBlock()
{
Text = "97420XXXX2",
Weight = TextWeight.Lighter,
IsSubtle = true
},
new TextBlock()
{
Text = "http://www.devenvexe.com",
Weight = TextWeight.Lighter,
IsSubtle = true
}
}
}
}
},
// second column
new ColumnSet()
{
Columns = new List<Column>()
{
new Column()
{
Size = ColumnSize.Auto,
Separation =SeparationStyle.Strong,
Items = new List<CardElement>()
{
new TextBlock()
{
Text = "Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com",
Wrap = true
}
}
}
}
}
}
}
},
};
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will generate following card design and reply the message
The following sample code included collecting basic information from the users with action button
ColumnSet and Column - The columnSet element adds the ability to have a set of Column objects and align the column object.
FactSet - The FactSet element is displayed row and column like a tabular form.
TextBlock - The TextBlock element allows for the inclusion of text, we can modify font sizes, weight and color.
ImageSet and Image - The ImageSet allows for the inclusion of a collection images like a photo set, and the Image element allows for the inclusion of images.
The following code showing, adding multiple columns and design the UI Adaptive Card
public Attachment CreateAdapativecardWithColumn()
{
AdaptiveCard card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
// Container
new Container()
{
Speak = "<s>Hello!</s><s>Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com</s>",
Items = new List<CardElement>()
{
// first column
new ColumnSet()
{
Columns = new List<Column>()
{
new Column()
{
Size = ColumnSize.Auto,
Items = new List<CardElement>()
{
new Image()
{
Url = "https://i1.social.s-msft.com/profile/u/avatar.jpg?displayname=j%20suthahar&size=extralarge&version=88034ca2-9db8-46cd-b767-95d17658931a",
Size = ImageSize.Small,
Style = ImageStyle.Person
}
}
},
new Column()
{
Size = "300",
Items = new List<CardElement>()
{
new TextBlock()
{
Text = "Suthahar Jegatheesan MCA",
Weight = TextWeight.Bolder,
IsSubtle = true
},
new TextBlock()
{
Text = "jssuthahar@gmail.com",
Weight = TextWeight.Lighter,
IsSubtle = true
},
new TextBlock()
{
Text = "97420XXXX2",
Weight = TextWeight.Lighter,
IsSubtle = true
},
new TextBlock()
{
Text = "http://www.devenvexe.com",
Weight = TextWeight.Lighter,
IsSubtle = true
}
}
}
}
},
// second column
new ColumnSet()
{
Columns = new List<Column>()
{
new Column()
{
Size = ColumnSize.Auto,
Separation =SeparationStyle.Strong,
Items = new List<CardElement>()
{
new TextBlock()
{
Text = "Suthahar J is a Technical Lead and C# Corner MVP. He has extensive 10+ years of experience working on different technologies, mostly in Microsoft space. His focus areas are Xamarin Cross Mobile Development ,UWP, SharePoint, Azure,Windows Mobile , Web , AI and Architecture. He writes about technology at his popular blog http://devenvexe.com",
Wrap = true
}
}
}
}
}
}
}
},
};
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will generate following card design and reply the message
Step 6: Adaptive Card Design with Input Control:
The Adaptive Cards can include input controls for collecting information from the user, it will support following input control is : Text, Date, Time, Number and for selecting options(choiceset) and toggle .The following sample code included collecting basic information from the users with action button
Input.Text – Collect the text content from the user
Input.Date - Collect a Date from the user
Input.Time - Collect a Time from the user
Input.Number - Collect a Number from the user
Input.ChoiceSet - provide the user a set of choices and have them pick
Input.ToggleChoice - provide the user a single choice between two items and have them pick
public Attachment CreateAdaptiveCardwithEntry()
{
var card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
// Hotels Search form
new TextBlock() { Text = "Please Share your detail for contact:" },
new TextInput()
{
Id = "Your Name",
Speak = "<s>Please Enter Your Name</s>",
Placeholder = "Please Enter Your Name",
Style = TextInputStyle.Text
},
new TextBlock() { Text = "When your Free" },
new DateInput()
{
Id = "Free",
Placeholder ="Your free Date"
},
new TextBlock() { Text = "Your Experence" },
new NumberInput()
{
Id = "No of Year experence",
Min = 1,
Max = 20,
},
new TextBlock() { Text = "Email" },
new TextInput()
{
Id = "Email",
Speak = "<s>Please Enter Your email</s>",
Placeholder = "Please Enter Your email",
Style = TextInputStyle.Text
},
new TextBlock() { Text = "Phone" },
new TextInput()
{
Id = "Phone",
Speak = "<s>Please Enter Your phone</s>",
Placeholder = "Please Enter Your Phone",
Style = TextInputStyle.Text
},
},
Actions = new List<ActionBase>()
{
new SubmitAction()
{
Title = "Contact",
Speak = "<s>Contact</s>",
}
}
};
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will return following adaptive card design
Input.Date - Collect a Date from the user
Input.Time - Collect a Time from the user
Input.Number - Collect a Number from the user
Input.ChoiceSet - provide the user a set of choices and have them pick
Input.ToggleChoice - provide the user a single choice between two items and have them pick
public Attachment CreateAdaptiveCardwithEntry()
{
var card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
// Hotels Search form
new TextBlock() { Text = "Please Share your detail for contact:" },
new TextInput()
{
Id = "Your Name",
Speak = "<s>Please Enter Your Name</s>",
Placeholder = "Please Enter Your Name",
Style = TextInputStyle.Text
},
new TextBlock() { Text = "When your Free" },
new DateInput()
{
Id = "Free",
Placeholder ="Your free Date"
},
new TextBlock() { Text = "Your Experence" },
new NumberInput()
{
Id = "No of Year experence",
Min = 1,
Max = 20,
},
new TextBlock() { Text = "Email" },
new TextInput()
{
Id = "Email",
Speak = "<s>Please Enter Your email</s>",
Placeholder = "Please Enter Your email",
Style = TextInputStyle.Text
},
new TextBlock() { Text = "Phone" },
new TextInput()
{
Id = "Phone",
Speak = "<s>Please Enter Your phone</s>",
Placeholder = "Please Enter Your Phone",
Style = TextInputStyle.Text
},
},
Actions = new List<ActionBase>()
{
new SubmitAction()
{
Title = "Contact",
Speak = "<s>Contact</s>",
}
}
};
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
The above code will return following adaptive card design
Run Bot Application
The emulator is a desktop application that lets us test and debug our bot on localhost. Now, you can click on "Run the application" in Visual studio and execute in the browser- Test Application on Bot Emulator
- You can follow the below steps to test your bot application.
- Open Bot Emulator.
- Copy the above localhost url and paste it in emulator e.g. - http://localHost:3979
- You can append the /api/messages in the above url; e.g. - http://localHost:3979/api/messages.
- You won't need to specify Microsoft App ID and Microsoft App Password for localhost testing, so click on "Connect".
0 Comments