I want to use facebook's quick replies -
at first I tried to use IMessageActivity's SuggestedActions property
IMessageActivity result = Activity.CreateMessageActivity();
result.Type = ActivityTypes.Message;
result.TextFormat = TextFormatTypes.Plain;
result.SuggestedActions = suggestedActions.Select(x => new CardAction()
{
Title = x,
Type = ActionTypes.ImBack,
Value = x
}).ToList()
but, as it didn't work for facebook, I found another solution based on ChanelData
result.ChannelData = JObject.FromObject(new {
quick_replies = suggestedActions.Actions.Select(x => new
{
content_type = "text",
title = x.Title,
payload = x.Value is null ? x.Title : x.Value
}).ToArray()
});
sadly it still doesn't work. Is there anything else to do?
I beleive you can use HeroCards and attach them to an activity and send that via SendActivityAsync.
Activity activity = _context.Context.Activity.CreateReply();
var buttonList = new List<CardAction>();
foreach (var prompt in Prompts)
{
buttonList.Add(
new CardAction { Value = prompt.DisplayText, Type = "imBack", Title = prompt.DisplayText, });
}
var heroCard = new HeroCard { Text = "message text", Subtitle = string.Empty, Buttons = buttonList };
activity.Attachments.Add(heroCard.ToAttachment());
await stepContext.Context.SendActivityAsync(activity).ConfigureAwait(false);
Try using a TextPrompt with the PromptOptions like this:
await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = "¡Bien! Ahora te envié un código de acceso a tu teléfono. Por favor ingrésalo aquí cuando lo recibas.",
SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Reenviar token", Type = ActionTypes.ImBack, Value = "Reenviar token" }
},
},
}
});
Result:
Edit:
If you dont want to use prompts, try this:
Activity activity = stepContext.Context.Activity.CreateReply();
activity.Type = ActivityTypes.Message;
activity.Text = "This is an example of SuggestedAction";
activity.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Action", Type = ActionTypes.ImBack, Value = "Action" }
}
};
await stepContext.Context.SendActivityAsync(activity);
return await stepContext.EndDialogAsync();
Result:
Related
I'm trying this code to create object Event using C#,
three month ago its worked and I created the events but now doesn't work, I realized that assembly has a new parameter "Event Type" but I don't know if It affects my object event
Event calendarEvent = new Event();
DateTime start = DateTime.Now;
calendarEvent.Kind = "";
calendarEvent.Summary = "test";
calendarEvent.Status = "confirmed";
calendarEvent.Visibility = "public";
calendarEvent.Description = "test";
calendarEvent.Creator = new Event.CreatorData
{
Email= "email#example.com",
Self=true
};
calendarEvent.Organizer = new Event.OrganizerData
{
Email = "email#example.com",
Self = true
};
calendarEvent.Start = new EventDateTime
{
DateTime = start,
TimeZone = "America/Mexico_City"
};
calendarEvent.End = new EventDateTime
{
DateTime = start.AddHours(1),
TimeZone = "America/Mexico_City"
};
calendarEvent.Recurrence = new String[] {"RRULE:FREQ=DAILY;COUNT=1" };
calendarEvent.Sequence = 0;
calendarEvent.HangoutLink = "";
calendarEvent.ConferenceData = new ConferenceData
{
CreateRequest = new CreateConferenceRequest
{
RequestId = "1234abcdef",
ConferenceSolutionKey = new ConferenceSolutionKey
{
Type = "hangoutsMeet"
},
Status = new ConferenceRequestStatus
{
StatusCode = "success"
}
},
EntryPoints = new List<EntryPoint>
{
new EntryPoint
{
EntryPointType = "video",
Uri = "",
Label = ""
}
},
ConferenceSolution = new ConferenceSolution
{
Key = new ConferenceSolutionKey
{
Type = "hangoutsMeet"
},
Name = "Google Meet",
IconUri = ""
},
ConferenceId = ""
};
//calendarEvent.EventType = "default";
When excute the line to create the event:
EventsResource.InsertRequest request = service.Events.Insert(calendarEvent, "email#example.com");
request.ConferenceDataVersion = 1;
Event createdEvent = request.Execute();
I get:
Google.Apis.Requests.Request Error Invalid conference type value. [400] Reason[invalid] Domain[global]"
When creating an event with a new conference data. You just need to specify the createRequest field, and set the conferenceDataVersion request parameter to 1 for all event modification requests.
Try this:
calendarEvent.ConferenceData = new ConferenceData
{
CreateRequest = new CreateConferenceRequest
{
RequestId = "1234abcdef",
ConferenceSolutionKey = new ConferenceSolutionKey
{
Type = "hangoutsMeet"
}
},
};
I have to create a adaptive card which have city of name and each city have different holiday list.
I have to show city name in dropdown list and on selection of each city i have to show child card which contains Holiday list.
I have develop below code:
private async Task<DialogTurnResult> ShowCard(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
List<string> city = new List<string>() { "Delhi", "Bangalore", "Mumbai" };
List<string> date = new List<string>() { "1-Jan", "26-Jan", "15-Aug" };
List<string> des = new List<string>() { "New Year", "Republic Day", "Independence Day" };
List<string> date1 = new List<string>() { "1-Jan", "26-Jan", "15-Aug", "25-Dec" };
List<string> des1 = new List<string>() { "New Year", "Republic Day", "Independence Day", "Christmas Day" };
List<string> date2 = new List<string>() { "1-Jan", "25-Dec" };
List<string> des2 = new List<string>() { "New Year", "Christmas Day" };
List<AdaptiveCard> cards = new List<AdaptiveCard>();
cards.Add(HolidayListAdaptiveCard(date, des));
cards.Add(HolidayListAdaptiveCard(date1, des1));
cards.Add(HolidayListAdaptiveCard(date2, des2));
var mainCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
var column3 = new AdaptiveColumn();
column3.Items.Add(new AdaptiveTextBlock() { Text = "Holiday City", Weight = AdaptiveTextWeight.Bolder });
var columnSet1 = new AdaptiveColumnSet();
columnSet1.Columns.Add(column3);
var container1 = new AdaptiveContainer();
container1.Style = AdaptiveContainerStyle.Emphasis;
container1.Items.Add(columnSet1);
mainCard.Body.Add(container1);
List<AdaptiveShowCardAction> adaptiveShowCardActions = new List<AdaptiveShowCardAction>();
for (int i = 0; i < city.Count; i++)
{
mainCard.Actions.Add(new AdaptiveShowCardAction() { Title = city[i], Card = cards[i] });
}
var attachment = new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = mainCard
};
var reply = MessageFactory.Attachment(attachment);
await stepContext.Context.SendActivityAsync(reply);
return new DialogTurnResult(DialogTurnStatus.Waiting);
}
private AdaptiveCard HolidayListAdaptiveCard(List<string> date, List<string> description)
{
var card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
List<AdaptiveColumn> columns = new List<AdaptiveColumn>();
var column = new AdaptiveColumn();
var column1 = new AdaptiveColumn();
var column2 = new AdaptiveColumn();
var textBlock = new AdaptiveTextBlock();
textBlock.Text = "Sr. No";
textBlock.Weight = AdaptiveTextWeight.Bolder;
textBlock.Size = AdaptiveTextSize.Large;
textBlock.Color = AdaptiveTextColor.Accent;
column.Items.Add(textBlock);
var textBlock1 = new AdaptiveTextBlock();
textBlock1.Text = "Date";
textBlock1.Weight = AdaptiveTextWeight.Bolder;
textBlock1.Size = AdaptiveTextSize.Large;
textBlock1.Color = AdaptiveTextColor.Good;
column1.Items.Add(textBlock1);
var textBlock2 = new AdaptiveTextBlock();
textBlock2.Text = "Description";
textBlock2.Weight = AdaptiveTextWeight.Bolder;
textBlock2.Size = AdaptiveTextSize.Large;
textBlock2.Color = AdaptiveTextColor.Dark;
column2.Items.Add(textBlock2);
for (int i = 0; i < date.Count; i++)
{
column.Items.Add(new AdaptiveTextBlock() { Text = (i + 1).ToString() });
column1.Items.Add(new AdaptiveTextBlock() { Text = date[i] });
column2.Items.Add(new AdaptiveTextBlock() { Text = description[i] });
}
var columnSet = new AdaptiveColumnSet();
columnSet.Columns.Add(column);
columnSet.Columns.Add(column1);
columnSet.Columns.Add(column2);
var container = new AdaptiveContainer();
container.Style = AdaptiveContainerStyle.Emphasis;
container.Items.Add(columnSet);
card.Body.Add(container);
return card;
}
O/P:
Issue: City name coming as separate button but i need city name in dropdown list.
You can create a dropdown menu in an Adaptive Card by using an Input.ChoiceSet element and setting style to "compact". Note that the compact style is the default in Teams.
You can only extend Adaptive Card functionality if you're using Web Chat so you won't be able to respond to events from this dropdown and you won't be able to modify the card as the user is filling it out. You'll need to have the user select a city and then click the submit button. While Teams does allow message updates and so you could update the card in response to the submit action, it's probably better and easier just to send a whole new card with the holiday list.
Is it possible to include HeroCard attachment in WaterfallStepContext, i am able to call ITurnContext but not from WaterfallStepContext
Trying using C# code however .Activity is part of waterfallstep contenxt
var getFeedback = turnContext.Activity.CreateReply();
var feedbackChoices = new HeroCard
{
Text = "Our conversation was helpful?",
Buttons = new List<CardAction>
{
new CardAction() { Title = Constants.userResponseThumbsUp, Type = ActionTypes.ImBack, Value = Constants.userResponseYes},
new CardAction() { Title = Constants.userResponseThumbsDown, Type = ActionTypes.ImBack, Value = Constants.userResponseNo},
},
};
// Add the card to our reply to user.
getFeedback.Attachments = new List<Attachment>() { feedbackChoices.ToAttachment() };
await turnContext.SendActivityAsync(getFeedback, cancellationToken);
Yes, it is possible to include a HeroCard attachment in WaterfallStepContext. Here is the implementation below:
private static async Task<DialogTurnResult> ShowCardStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var getFeedback = stepContext.Context.Activity.CreateReply();
var feedbackChoices = new HeroCard
{
Text = "Our conversation was helpful?",
Buttons = new List<CardAction>
{
new CardAction() { Title = Constants.userResponseThumbsUp, Type = ActionTypes.ImBack, Value = Constants.userResponseYes},
new CardAction() { Title = Constants.userResponseThumbsDown, Type = ActionTypes.ImBack, Value = Constants.userResponseNo},
},
};
// Add the card to our reply to user.
getFeedback.Attachments = new List<Attachment>() { feedbackChoices.ToAttachment() };
await stepContext.Context.SendActivityAsync(getFeedback, cancellationToken);
}
Hope this helps.
I have created one dialog to evaluate our company consultant in our chatbot (C# botframework), but I can't use for or foreach inside of AdaptiveCard. I need to create one TextBlock() and one ChoiceSet() block for each item from List Pergunta, but I can't do it with foreach. Any suggestion or better idea to create this loop ?
Here is my complete dialog code in C#.
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using System.Collections.Generic;
using AdaptiveCards;
using SimpleEchoBot.Formulário;
namespace SimpleEchoBot.Dialogs
{
[Serializable]
public class RatingDialog : IDialog<EntidadeCliente>
{
public Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
return Task.CompletedTask;
}
public async virtual Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var replyMessage = context.MakeMessage();
Attachment attachment = null;
attachment = CriarAdapativecard();
replyMessage.Attachments = new List<Attachment> { attachment };
await context.PostAsync(replyMessage);
}
public Attachment CriarAdapativecard()
{
AdaptiveCard card = new AdaptiveCard()
{
Body = new List<CardElement>()
{
new Container()
{
Items = new List<CardElement>()
{
new ColumnSet()
{
Columns = new List<Column>()
{
new Column()
{
Size = ColumnSize.Auto,
Items = new List<CardElement>()
{
new Image()
{
Url = "D:/EvaWeb.png",
Size = ImageSize.Medium,
Style = ImageStyle.Person
}
}
},
new Column()
{
Size = ColumnSize.Auto,
Items = new List<CardElement>()
{
new TextBlock()
{
Text = "Olá, temos uma novidade!",
Weight = TextWeight.Bolder,
IsSubtle = true
},
new TextBlock()
{
Text = "Gostaria de iniciar a avaliação do consultor?",
Wrap = true
}
}
}
}
}
}
}
},
// Buttons
Actions = new List<ActionBase>()
{
new ShowCardAction()
{
Title = "Sim",
Speak = "<s>Sim</s>",
Card = AvaliarConsultor("")
},
new ShowCardAction()
{
Title = "Não",
Speak = "<s>Não</s>",
Card = PularAvaliacao()
},
}
};
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
return attachment;
}
private static AdaptiveCard PularAvaliacao()
{
//does nothing on No option from user
return new AdaptiveCard()
{ };
}
private static AdaptiveCard AvaliarConsultor(List<string> Pergunta)
{
var adaptiveCard = new AdaptiveCard()
{
Body = new List<CardElement>()
{
new TextBlock()
{
Text = "Avaliação de questionário 1!",
Weight = TextWeight.Bolder,
Size = TextSize.Large
},
new TextBlock() { Text = Pergunta[0]},
new ChoiceSet()
{
Id = "nota",
Style = ChoiceInputStyle.Compact,
IsMultiSelect = false,
Choices = new List<Choice>()
{
new Choice()
{
Title = "⭐",
Value = "1"
},
new Choice()
{
Title = "⭐⭐",
Value = "2"
},
new Choice()
{
Title = "⭐⭐⭐",
Value = "3"
},
new Choice()
{
Title = "⭐⭐⭐⭐",
Value = "4"
},
new Choice()
{
Title = "⭐⭐⭐⭐⭐",
Value = "5"
}
}
}
},
Actions = new List<ActionBase>()
{
new SubmitAction()
{
Title = "Registrar",
Speak = "<s>Registrar avaliação</s>",
DataJson = "{ \"Type\": \"Registrar\" }"
}
}
};
return adaptiveCard;
}
}
}
I need to create one TextBlock() and one ChoiceSet() block for each item from List Pergunta, but I can't do it with foreach.
To achieve your requirement, please refer to the following code snippet.
private static AdaptiveCard AvaliarConsultor(List<string> Pergunta)
{
var adaptiveCard = new AdaptiveCard()
{
Body = new List<CardElement>()
{
new TextBlock()
{
Text = "Avaliação de questionário 1!",
Weight = TextWeight.Bolder,
Size = TextSize.Large
},
},
Actions = new List<ActionBase>()
{
new SubmitAction()
{
Title = "Registrar",
Speak = "<s>Registrar avaliação</s>",
DataJson = "{ \"Type\": \"Registrar\" }"
}
}
};
//dynamically generate TextBlock and ChoiceSet
//and then add to AdaptiveCard Body
foreach (var item in Pergunta)
{
var textblock = new TextBlock() { Text = item };
var choiceset = new ChoiceSet()
{
Id = "nota",
Style = ChoiceInputStyle.Compact,
IsMultiSelect = false,
Choices = new List<Choice>()
{
new Choice()
{
Title = "⭐",
Value = "1"
},
new Choice()
{
Title = "⭐⭐",
Value = "2"
},
new Choice()
{
Title = "⭐⭐⭐",
Value = "3"
},
new Choice()
{
Title = "⭐⭐⭐⭐",
Value = "4"
},
new Choice()
{
Title = "⭐⭐⭐⭐⭐",
Value = "5"
}
}
};
adaptiveCard.Body.Add(textblock);
adaptiveCard.Body.Add(choiceset);
}
return adaptiveCard;
}
Test result:
I am using Adaptive card combo box to show some categories of products. Once the user clicks on the category that category should pass to another method and display all the products of that category in another adaptive card Combo Box and let user select a product.
Here is the code to get all category to combo box.
public async Task GetCategoryAdaptiveCard(IDialogContext context)
{
var replyToConversation = context.MakeMessage();
replyToConversation.Attachments = new List<Attachment>();
HttpResponseMessage response = new HttpResponseMessage();
string query = string.Format(APIChatBot + "/AllCategory");
using (var client = ClientHelper.GetClient())
{
response = await client.GetAsync(query);
}
var categoryList = await response.Content.ReadAsAsync<IEnumerable<CategoryDTO>>();
AdaptiveCard adaptiveCard = new AdaptiveCard();
adaptiveCard.Speak = "Please Select A Category from the list";
adaptiveCard.Body.Add(new TextBlock()
{
Text = "Please Select A Category from the list",
Size = TextSize.Normal,
Weight = TextWeight.Normal
});
adaptiveCard.Body.Add(new TextBlock()
{
Text = "Category List",
Size = TextSize.Normal,
Weight = TextWeight.Normal
});
List<AdaptiveCards.Choice> list = new List<AdaptiveCards.Choice>();
foreach (var item in categoryList)
{
AdaptiveCards.Choice choice = new AdaptiveCards.Choice()
{
Title = item.CategoryName,
Value = item.Id.ToString()
};
list.Add(choice);
}
adaptiveCard.Body.Add(new ChoiceSet()
{
Id = "Category",
Style = ChoiceInputStyle.Compact,
Choices = list
});
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = adaptiveCard
};
replyToConversation.Attachments.Add(attachment);
await context.PostAsync(replyToConversation);
}
Here is the method i used to get the Product for the selected category.
public async Task GetProductForCategory(IDialogContext context, string category)
{
var replyToConversation = context.MakeMessage();
replyToConversation.Attachments = new List<Attachment>();
HttpResponseMessage response = new HttpResponseMessage();
string query = string.Format(APIChatBot + "/ProductByCategory/" + category);
using (var client = ClientHelper.GetClient())
{
response = await client.GetAsync(query);
}
var productList = await response.Content.ReadAsAsync<IEnumerable<ProductDTO>>();
if(productList .Count() == 0)
{
string message = "Sorry There Are No products For this Category" + category;
await context.PostAsync(message);
}
else
{
List<AdaptiveCards.Choice> list = new List<AdaptiveCards.Choice>();
foreach (var item in productList )
{
AdaptiveCards.Choice choice = new AdaptiveCards.Choice()
{
Title = item.ProductName,
Value = item.Id.ToString()
};
list.Add(choice);
}
AdaptiveCard adaptiveCard = new AdaptiveCard();
adaptiveCard.Body.Add(new TextBlock()
{
Text = "List of Products for the Category " + category,
Size = TextSize.Normal,
Weight = TextWeight.Normal
});
adaptiveCard.Body.Add(new TextBlock()
{
Text = "Please Select A Product From The List",
Size = TextSize.Normal,
Weight = TextWeight.Normal
});
adaptiveCard.Body.Add(new ChoiceSet()
{
Id = "ProductForCategory",
Style = ChoiceInputStyle.Compact,
Choices = list
});
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = adaptiveCard
};
replyToConversation.Attachments.Add(attachment);
await context.PostAsync(replyToConversation);
}
}
How can i pass the category selected by the user to the method that selects the product based on category?
If you create an adaptive card something like this:
var reply = context.MakeMessage();
var card = new AdaptiveCard();
var choices = new List<Choice>();
choices.Add(new Choice()
{
Title = "Category 1",
Value = "c1"
});
choices.Add(new Choice()
{
Title = "Category 2",
Value = "c2"
});
var choiceSet = new ChoiceSet()
{
IsMultiSelect = false,
Choices = choices,
Style = ChoiceInputStyle.Compact,
Id = "Category"
};
card.Body.Add(choiceSet);
card.Actions.Add(new SubmitAction() { Title = "Select Category", Data = Newtonsoft.Json.Linq.JObject.FromObject(new { button = "select" }) });
reply.Attachments.Add(new Attachment()
{
Content = card,
ContentType = AdaptiveCard.ContentType,
Name = $"Card"
});
await context.PostAsync(reply);
When the user selects one of the options, and clicks the button, the resulting activity's value will be a jobject you can deserialize and use to create a product specific adaptive card:
class CategorySelection
{
public string Category { get; set; }
}
var activityValue = activity.Value as Newtonsoft.Json.Linq.JObject;
if (activityValue != null)
{
var categorySelection = activityValue.ToObject<CategorySelection>();
var category = categorySelection.Category;
//query the database for products of this category type,
//create another adaptive card displaying the products and send to user
await context.PostAsync(reply);
}