In the first step of this Dialog, I want to ask the user what they want to do with a Choice prompt. After the return, where I would expect the dialog to go to the next Waterfallstep (HandleChoiceAsync), it instead returns to it's parentdialog.
I seem to remember this used to work before. Thanks in advance!
MainDialog
OrdersDialog
private async Task<DialogTurnResult> AskForProductsAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
productList = (List<Product>)stepContext.Options;
if(productList.Count > 0)
{
string producten = "";
foreach(Product p in productList)
{
producten += p.GetProductName() + ", ";
}
producten = producten.Remove(producten.Length - 2);
await stepContext.Context.SendActivityAsync("In je bestelling staan nu de volgende producten: " + producten + ".");
}
//choice prompt does not go to next waterfallstep, instead returns to parent dialog
return await stepContext.PromptAsync(nameof(ChoicePrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Wil je nog een product toevoegen of verwijderen?"),
RetryPrompt = MessageFactory.Text("Probeer het nog een keer"),
Choices = ChoiceFactory.ToChoices(new List<string> { "Toevoegen", "Verwijderen", "Klaar met bestellen" })
}, cancellationToken);
}
private async Task<DialogTurnResult> HandleChoiceAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
FoundChoice choice = (FoundChoice)stepContext.Result;
switch (choice.Index)
{
case 0:
toevoegen = true;
var messageText = "Welk product wil je toevoegen?";
var promptMessage = MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = promptMessage }, cancellationToken);
case 1:
toevoegen = false;
List<string> productsString = new List<string>();
foreach (Product p in productList)
{
productsString.Add(p.GetProductName());
}
return await stepContext.PromptAsync(nameof(ChoicePrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Welk product wil je verwijderen?"),
Choices = ChoiceFactory.ToChoices(productsString)
}, cancellationToken);
case 2:
return await stepContext.EndDialogAsync(productList);
default:
break;
}
return await stepContext.NextAsync();
}
Related
I have an async operation that takes in an List of Airline as parameter and returns some data, and I have a list of Airlines for which I want to get data for.
However, if I can't get the data for all those Airlines after some predefined amount of time, I want to stop waiting and return something else to the user.
public async Task Run()
{
var watch = System.Diagnostics.Stopwatch.StartNew();
await RunAirline();
watch.Stop();
Console.WriteLine($"Total Execution Time: {watch.ElapsedMilliseconds + Environment.NewLine}");
//return $"Total Execution Time: {watch.ElapsedMilliseconds + Environment.NewLine}";
//Console.ReadLine();
}
private static async Task RunAirline()
{
try
{
List<string> AirlineList = GetAirLineCodes();
List<Task<WebsiteDataModel.WebsiteDataModel>> taskList = new List<Task<WebsiteDataModel.WebsiteDataModel>>();
foreach (string AirlineCode in AirlineList)
{
taskList.Add(Task.Run(() => CallindividualAirline(AirlineCode)));
}
var result = await Task.WhenAll(taskList);
foreach (WebsiteDataModel.WebsiteDataModel model in result)
{
Display(model);
}
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message.ToString());
}
}
private static List<string> GetAirLineCodes()
{
return new List<string>()
{
"A",
"B",
"C"
};
}
private static void Display(WebsiteDataModel.WebsiteDataModel result)
{
Console.WriteLine($"Website Content as {result.DataContent} , Website Name as : {result.WebsiteName} Status as : {result.Status} , Content length as : {result.WebsiteData.Length} ----- Error as : {result.error.FaultException.ToString()}." + Environment.NewLine);
}
private static WebsiteDataModel.WebsiteDataModel CallindividualAirline(string AirlineCode)
{
WebsiteDataModel.WebsiteDataModel LobjWebsiteDataModel = new WebsiteDataModel.WebsiteDataModel();
WebsiteDataModel.ErrorData LobjErrorData = new WebsiteDataModel.ErrorData();
try
{
switch (AirlineCode)
{
// calling Airline API...........
case "A":
ClsAirOne LobjAirOne = new ClsAirOne();
LobjWebsiteDataModel = LobjAirOne.GetAirDataData("https://book.xxxxx.com");
return LobjWebsiteDataModel;
case "B":
ClsAirTwo LobjAirTwo = new ClsAirTwo();
LobjWebsiteDataModel = LobjAirTwo.GetAirData("https://book.xxxxx.in");
return LobjWebsiteDataModel;
case "C":
ClsAirThree LobjAirThree = new ClsAirThree();
LobjWebsiteDataModel = LobjAirThree.GetAirData("https://xxxxx.in/");
return LobjWebsiteDataModel;
default:
return LobjWebsiteDataModel;
}
}
catch (Exception Ex)
{
LobjWebsiteDataModel.Status = "0";
LobjWebsiteDataModel.WebsiteData = "";
LobjErrorData.FaultException = "ERR-01" + Ex.Message.ToString();
LobjWebsiteDataModel.error = LobjErrorData;
return LobjWebsiteDataModel;
}
}
The best way to do this is to cancel each operation passed to the Task.WhenAll. You can create a cancellation token source with a timeout, and then pass its CancellationToken down to the methods that actually do the I/O.
E.g.:
public async Task Run()
{
...
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await RunAirline(cts.Token);
...
}
private static async Task RunAirline(CancellationToken cancellationToken)
{
...
foreach (string AirlineCode in AirlineList)
taskList.Add(Task.Run(() => CallindividualAirline(AirlineCode, cancellationToken)));
...
}
private static WebsiteDataModel.WebsiteDataModel CallindividualAirline(string AirlineCode, CancellationToken cancellationToken)
{
...
ClsAirOne LobjAirOne = new ClsAirOne();
LobjWebsiteDataModel = LobjAirOne.GetAirDataData("https://book.xxxxx.com", cancellationToken);
...
ClsAirTwo LobjAirTwo = new ClsAirTwo();
LobjWebsiteDataModel = LobjAirTwo.GetAirData("https://book.xxxxx.in", cancellationToken);
...
}
This is Task Code
public async Task Demo(int row_index, CancellationToken token)
{
Task t1 = Task.Run(() =>
{
ChromeOptions chromeOptions = new ChromeOptions();
ChromeDriverService chromeDriverService = ChromeDriverService.CreateDefaultService();
chromeDriverService.SuppressInitialDiagnosticInformation = true;
chromeDriverService.HideCommandPromptWindow = true;
this.chrome[row_index] = new ChromeDriver(chromeDriverService, chromeOptions);
this.chrome[row_index].Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(59.0);
Dologin(row_index);
//Lay Ten Fb
chrome[row_index].Url = "https://facebook.com/profile";
var conchim = chrome[row_index].FindElementByCssSelector("#fb-timeline-cover-name > a");
this.dataGridView1.Rows[row_index].Cells["trangthai"].Value = "Tiến Hành Lấy Tên Facebook";
foreach (DataGridViewRow r in dataGridView1.Rows)
{
string value1 = r.Cells[0].Value.ToString() ?? string.Empty;
if (value1 == tkfacebook)
{
r.Cells[4].Value = conchim.Text;
break;
}
}
},token);
}
This is Code Run Task And Cancel Task.
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token;
public async void HandleValue(DataGridViewCell cell, int row_index)
{
switch (cell.Value.ToString())
{
case "Bắt đầu":
bool flag7 = Convert.ToInt32(this.txtClickStart.Value) > Convert.ToInt32(this.txtClickEnd.Value);
if (radioButton1.Checked && !flag7)
{
cell.Value = "Kết Thúc";
token = source.Token;
await Demo(row_index,token);
}
if (flag7)
{
this.dataGridView1.Rows[row_index].Cells["trangthai"].Value = "Cài đặt thời gian không đúng";
MessageBox.Show(new Form
{
TopMost = true
}, "Cài đặt thời gian không đúng, hãy cài đặt lại!", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
bool flag3 = !radioButton1.Checked || !radioButton1.Checked && !radioButton2.Checked;
if (flag3)
{
MessageBox.Show("Vui Lòng Chọn Trình Duyệt Để Bắt Đầu Chạy");
}
break;
case "Kết Thúc":
source.Cancel();
chrome[row_index].Quit();
cell.Value = "Bắt đầu";
this.dataGridView1.Rows[row_index].Cells["trangthai"].Value = "Bạn đã chọn kết thúc làm việc";
break;
}
}
Thread is not working so i do Task . But it still Run when i already Do Task Cancel. ...............
source.Cancel();
Make Post Longger to Avablie To Post . Dont Care this Rows ..dfsdfsdfsddfsddsadasdsadasdsadasdasdassdasdasdasdasdasdasdasdasdasdadda
If you aim to cancel the execution of logic, then you need to check IsCancellationRequested flag.
while(!token.IsCancellationRequested)
{
//whatever logic you want run should be placed here. This logic won't be
//executed after you call Cancel()
}
Above logic will continue to execute your logic until you called Cancel() on token source. You can find some example 1 and 2.
Your Code for Demo should include a check on the cancelation-Token. Try something like this:
Task t1 = Task.Run(() =>
{
ChromeOptions chromeOptions = new ChromeOptions();
ChromeDriverService chromeDriverService = ChromeDriverService.CreateDefaultService();
chromeDriverService.SuppressInitialDiagnosticInformation = true;
chromeDriverService.HideCommandPromptWindow = true;
this.chrome[row_index] = new ChromeDriver(chromeDriverService, chromeOptions);
this.chrome[row_index].Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(59.0);
Dologin(row_index);
//Lay Ten Fb
chrome[row_index].Url = "https://facebook.com/profile";
var conchim = chrome[row_index].FindElementByCssSelector("#fb-timeline-cover-name > a");
this.dataGridView1.Rows[row_index].Cells["trangthai"].Value = "Tiến Hành Lấy Tên Facebook";
foreach (DataGridViewRow r in dataGridView1.Rows)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Task was cancelled by user.");
token.ThrowIfCancellationRequested();
}
string value1 = r.Cells[0].Value.ToString() ?? string.Empty;
if (value1 == tkfacebook)
{
r.Cells[4].Value = conchim.Text;
break;
}
}
},token);
Please also refer the example here:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken.iscancellationrequested?view=netframework-4.8
I have in total 4 dialogs. In one of the dialogs (named "product issue") I have to go a new dialog named "resolution", at the end of that dialog their itself at particular condition. An adaptive card is displayed from product issue have 4 option in it, on "Overload" ,"Computer Rebooting", "Low Backup" it goes to new dialog named "resolution", where it has two steps: in step one display an adaptive card again with 4 options named
"Restart Machine", "off device","Press,Need assistance...when I select any option three open from step 1 like "Restart Machine", "off device","Press..it should display the adaptive card and end their itself and need assistance it will go back to product issue and will display defined steps for it. But when I choose
"Restart Machine", "off device" or press ..dialog is not ending and it it going back to product issue.
Product issue:
namespace Microsoft.BotBuilderSamples
{
public class ProductIssue : ComponentDialog
{
private const string UserInfo = "value-userInfo";
protected readonly ILogger _logger;
protected readonly string[] _end =
{
Path.Combine(".", "Resources", "ValidationCard.json"),
};
protected readonly string[] _date =
{
Path.Combine(".", "Resources", "Datepicker.json"),
};
protected readonly string[] _time =
{
Path.Combine(".", "Resources", "Timepicker.json"),
};
protected readonly string[] _cards =
{
Path.Combine(".", "Resources", "State.json"),
};
protected readonly string[] _card =
{
Path.Combine(".", "Resources", "City.json"),
};
protected readonly string[] _purchase =
{
Path.Combine(".", "Resources", "purchase.json"),
};
protected readonly string[] _service =
{
Path.Combine(".", "Resources", "Service.json")
};
public ProductIssue(string dialogId) : base(dialogId)
{
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
if (dialogId == $"{nameof(MainDialog)}.fromMain")
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
optionAsync,
InoptionAsync,
AnyOthersAsync,
OtpAsync,
UserauthenticationAsync,
CityAsync,
purchaseAsync,
purchaseYesAsync,
reviewAsync,
lastAsync,
EndAsync
}));
else if (dialogId == $"{ nameof(Resolution)}.resolution")
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
OtpAsync,
UserauthenticationAsync,
CityAsync,
purchaseAsync,
purchaseYesAsync,
reviewAsync,
lastAsync,
EndAsync
}));
else
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
InoptionAsync,
AnyOthersAsync,
OtpAsync,
UserauthenticationAsync,
CityAsync,
purchaseAsync,
purchaseAsync,
purchaseYesAsync,
reviewAsync,
lastAsync,
EndAsync
}));
InitialDialogId = nameof(WaterfallDialog);
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new TextPrompt($"{nameof(MainDialog)}.fromMain", ValidateAsync));
}
private async Task<DialogTurnResult> optionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var attachments = new List<Attachment>();
var reply = MessageFactory.Attachment(attachments);
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment4());
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment5());
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment6());
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment7());
var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Please select any option.") };
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
}
private async Task<DialogTurnResult> InoptionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice == "Inverter" || choice == "Fan" || choice == "Battery")
{
var attachments = new List<Attachment>();
var reply = MessageFactory.Attachment(attachments);
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment8());
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
}
else
{
var attachments = new List<Attachment>();
var reply = MessageFactory.Attachment(attachments);
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.GetHeroCard5().ToAttachment());
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("I will be here if you need me further."), cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("i will") };
return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
}
private async Task<DialogTurnResult> AnyOthersAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice == "Any Others")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("We are here to help you."), cancellationToken);
}
else if(choice == "Overload" || choice == "Computer Rebooting" || choice == "Low Backup")
{
return await stepContext.BeginDialogAsync($"{nameof(Resolution)}.start", null, cancellationToken);
}
var anyothers = new PromptOptions { Prompt = MessageFactory.Text("Please enter your specific problem.") };
return await stepContext.PromptAsync(nameof(TextPrompt), anyothers, cancellationToken);
}
private async Task<DialogTurnResult> OtpAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values[UserInfo] = new UserInput();
await stepContext.Context.SendActivityAsync(MessageFactory.Text("To proceed further, we will be verifying your mobile number by sending an OTP."), cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("We have just sent an OTP to your number"), cancellationToken);
var num = new PromptOptions
{
Prompt = MessageFactory.Text("Kindly enter the OTP sent(6 digit number)"),
RetryPrompt = MessageFactory.Text("Incorrect OTP entered. Kindly re-enter the OTP sent (6 digit number).")
};
return await stepContext.PromptAsync($"{nameof(MainDialog)}.fromMain", num, cancellationToken);
}
private async Task<DialogTurnResult> UserauthenticationAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var Otp = (UserInput)stepContext.Values[UserInfo];
int value;
var len = (stepContext.Result.ToString()).Length;
bool success = int.TryParse(stepContext.Result.ToString(), out value);
if (success == true && len == 6)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Thanks. Your OTP is confirmed."), cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("We are now validating your number against our database. This may take a minute."), cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("We will be registering you as a user in our system. Please provide a few details."), cancellationToken);
}
var attachments = new List<Attachment>();
var reply = MessageFactory.Attachment(attachments);
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment9());
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Hello"), cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Please select the state you are located in"), cancellationToken);
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_cards[r.Next(_cards.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
var num = new PromptOptions
{
Prompt = MessageFactory.Text(" Selected state is:")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> CityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_card[r.Next(_card.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
var num = new PromptOptions
{
Prompt = MessageFactory.Text(" Selected city is:")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> purchaseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_purchase[r.Next(_purchase.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
var num = new PromptOptions
{
Prompt = MessageFactory.Text("")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> purchaseYesAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice.ToLower() == "yes")
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_date[r.Next(_date.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
}
else if (choice.ToLower() == "no")
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_service[r.Next(_service.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
}
var num = new PromptOptions
{
Prompt = MessageFactory.Text("")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> reviewAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice.ToLower() == "no")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Our representative will be reviewing your comments shortly."), cancellationToken);
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_end[r.Next(_end.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
else
{
ServiceDate serviceDate = JsonConvert.DeserializeObject<ServiceDate>(choice);
Random r2 = new Random();
var validationcards = Cards.CreateAdaptiveCardAttachment2(_service[r2.Next(_service.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcards), cancellationToken);
}
var num = new PromptOptions
{
Prompt = MessageFactory.Text("")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> lastAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice.ToLower() == "yes")
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_time[r.Next(_time.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
}
else if (choice.ToLower() == "no")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Our representative will be reviewing your comments shortly."), cancellationToken);
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_end[r.Next(_end.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
var num = new PromptOptions
{
Prompt = MessageFactory.Text("")
};
return await stepContext.PromptAsync(nameof(TextPrompt), num, cancellationToken);
}
private async Task<DialogTurnResult> EndAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
ServiceDate serviceDate = JsonConvert.DeserializeObject<ServiceDate>(choice);
if (serviceDate.id == "12")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Starting to raise service request with the team. Please give it a minute."), cancellationToken);
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Our representative will be reviewing your comments shortly."), cancellationToken);
}
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_end[r.Next(_end.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
private Task<bool> ValidateAsync(PromptValidatorContext<string> promptContext, CancellationToken cancellationToken)
{
int value;
int len = (promptContext.Context.Activity.Text).Length;
bool success = int.TryParse(promptContext.Context.Activity.Text, out value);
if (success == true && len == 6)
{
return Task.FromResult(true);
}
else
{
return Task.FromResult(false);
}
}
}
public class ServiceDate
{
public string id { get; set; }
public string value { get; set; }
public string date { get; set; }
}
}
**resolution dialog**
namespace Microsoft.BotBuilderSamples
{
public class Resolution : ComponentDialog
{
protected readonly string[] _solution =
{
Path.Combine(".", "Resources", "resolution.json"),
};
protected readonly string[] _action =
{
Path.Combine(".", "Resources", "ValidationCard.json"),
};
public Resolution(string dialogId) : base(dialogId)
{
AddDialog(new TextPrompt($"{nameof(Resolution)}.solution"));
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
AddDialog(new WaterfallDialog($"{nameof(Resolution)}.start", new WaterfallStep[]
{
solutionAsync,
actionAsync
}));
InitialDialogId = $"{nameof(Resolution)}.start";
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new TextPrompt($"{nameof(Resolution)}.end"));
}
private async Task<DialogTurnResult> solutionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_solution[r.Next(_solution.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
var anyothers = new PromptOptions { Prompt = MessageFactory.Text("Please select the problem resloution.") };
return await stepContext.PromptAsync($"{nameof(Resolution)}.solution", anyothers, cancellationToken);
}
private async Task<DialogTurnResult> actionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = stepContext.Result.ToString();
if (choice == "Restart Machice" || choice == "off device" || choice == "Press")
{
Random r = new Random();
var validationcard = Cards.CreateAdaptiveCardAttachment2(_action[r.Next(_action.Length)]);
await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(validationcard), cancellationToken);
return await stepContext.EndDialogAsync($"{nameof(Resolution)}.end", cancellationToken);
}
else
{
return await stepContext.BeginDialogAsync($"{ nameof(Resolution)}.resolution", null, cancellationToken);
} } }}
If you want to end a dialog and NOT return to ANY previous dialog, you need to use CancellAllDialogs. It looks like you are using only EndDialog, which only ends the currently active dialog.
I need to do a condition depending on the Id of the active dialog something like this.
var dc = await _dialogs.CreateContextAsync(turnContext);
if (dc.ActiveDialog != null && dc.ActiveDialog.id == "SkipLuisDialog")
{
var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}
When i check my active dialog on OnTurnAsync() like this:
if (dc.ActiveDialog != null)
{
await dc.Context.SendActivityAsync(dc.ActiveDialog.Id.ToString());
}
It always say "mainDialog" which is the ID of my main dialog. Even when im on the "FAQDialog" or "complaintDialog" the active dialog ID is always "mainDialog". Why is the active dialog Id not changing to "FAQDialog" when im in the FAQ dialog or to "complaintDialog" when im in the complaint dialog?
My main dialog and other dialogs are in another class.
This is how i call the mainDialog on OnTurnAsync():
if (!dc.Context.Responded)
{
switch (dialogResult.Status)
{
case DialogTurnStatus.Empty:
switch (topIntent) // topIntent // text
{
case GetStartedIntent:
await dc.BeginDialogAsync(MainDialogId);
break;
case NoneIntent:
default:
await dc.Context.SendActivityAsync("I didn't understand what you just said to me.");
break;
}
break;
case DialogTurnStatus.Waiting:
// The active dialog is waiting for a response from the user, so do nothing.
break;
case DialogTurnStatus.Complete:
await dc.EndDialogAsync();
break;
default:
await dc.CancelAllDialogsAsync();
break;
}
}
The Main Dialog:
namespace CoreBot.Dialogs
{
public class MainDialog : ComponentDialog
{
private const string InitialId = "mainDialog";
private const string TextPromptId = "textPrompt";
private const string ComplaintDialogId = "complaintDialog";
private const string FAQDialogId = "FAQDialog";
public MainDialog(string dialogId) : base(dialogId)
{
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new FAQDialog(FAQDialogId));
AddDialog(new FileComplaintDialog(ComplaintDialogId));
AddDialog(new TextPrompt(TextPromptId));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
TextPromptId,
new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = $"What can i do for you?",
SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Frequently Asked Questions", Type = ActionTypes.ImBack, Value = "Frequently Asked Questions" },
new CardAction() { Title = "File a Complaint Ticket", Type = ActionTypes.ImBack, Value = "File a Complaint Ticket" },
},
},
},
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var response = stepContext.Result.ToString().ToLower();
string[] FAQArray = { "frequently asked questions", "question", "ask question" };
string[] ComplaintsArray = { "file a complaint ticket", "complaint", "file a complaint" };
if (FAQArray.Contains(response))
{
return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken);
}
if (ComplaintsArray.Contains(response))
{
await stepContext.EndDialogAsync();
return await stepContext.BeginDialogAsync(ComplaintDialogId, cancellationToken: cancellationToken);
}
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.ReplaceDialogAsync(InitialId);
}
}
}
The Main Dialog calls 2 dialogs. This is one of them.
namespace CoreBot.Dialogs
{
public class FAQDialog : ComponentDialog
{
private const string InitialId = "FAQDialog";
private const string ChoicePromptId = "choicePrompt";
private const string TextPromptId = "textPrompt";
private const string ConfirmPromptId = "confirmPrompt";
public FAQDialog(string dialogId) : base(dialogId)
{
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
FourthStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new ChoicePrompt(ChoicePromptId));
AddDialog(new ConfirmPrompt(ConfirmPromptId));
AddDialog(new TextPrompt(TextPromptId));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var choices = new List<Choice>();
choices.Add(new Choice { Value = "This is Sample Question 1", Synonyms = new List<string> { "Question 1" } });
choices.Add(new Choice { Value = "This is Sample Question 2", Synonyms = new List<string> { "Question 2" } });
return await stepContext.PromptAsync(
ChoicePromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Welcome to FAQ! Choose the number of the question or type your own question."),
Choices = choices,
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var choiceResult = (stepContext.Result as FoundChoice).Value.ToLower();
switch (choiceResult)
{
case "this is sample question 1":
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Answer to question 1."));
break;
case "this is sample question 2":
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Answer to question 2."));
break;
default:
break;
}
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
ConfirmPromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Have another question?"),
});
}
private static async Task<DialogTurnResult> FourthStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var confirmResult = (bool)stepContext.Result;
if (confirmResult)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Ask away!"));
return await stepContext.ReplaceDialogAsync(InitialId);
}
else
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Great!"));
return await stepContext.EndDialogAsync();
}
}
}
}
This is because all of your dialogs are being called within MainDialog.
Dialog Stack Concept
Here's more or less what's going on:
In MyBot.cs (or whatever your main .cs file is), you have something like Dialogs = new DialogSet(_dialogStateAccessor) which creates an empty dialog stack:
___________
You then use something like await dc.BeginDialogAsync(MainDialogId);, which adds MainDialog to the top of your dialog stack:
______________
| MainDialog |
|______________|
If you call return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken); outside of your MainDialog, your stack will look something like this:
______________
| FAQDialogId |
|______________|
______________
| MainDialog |
|______________|
However, you call return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken); from within MainDialog, which has it's own stack, so FAQDialog is the active dialog within MainDialog, but your Dialogs stack still has MainDialog as the ActiveDialog. So, your stack is more or less like this:
_______________________
| ______________ |
| |__FAQDialog__| |
| |
| MainDialog |
|_______________________|
Doing What You Want
You have a couple of options:
1. Call all of your other dialogs from outside of MainDialog.
If you're not going to come back to MainDialog, you could do something like:
In MainDialog:
return await stepContext.EndDialogAsync("FAQDialog");
In MyBot.cs:
switch (dialogResult)
{
case "FAQDialog":
dc.BeginDialogAsync(FAQDialogId, cancellationToken);
break;
case "ComplaintDialog":
dc.BeginDialogAsync(ComplaintDialogId, cancellationToken);
break;
}
2. Dig for the the dialog's ID within the ActiveDialog's stack
if (dc.ActiveDialog != null && IsDialogInStack(dc.ActiveDialog, "SkipLuisDialog"))
{
var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}
[...]
private bool IsDialogInStack(DialogInstance activeDialog, string searchId)
{
if (activeDialog.Id == searchId)
{
return true;
};
foreach (KeyValuePair<string, object> item in activeDialog.State)
{
if (item.Key == "dialogs" && item.Value is DialogState)
{
DialogState dialogState = (DialogState)item.Value;
foreach (DialogInstance dialog in dialogState.DialogStack)
{
return IsDialogInStack(dialog, searchId);
}
}
}
return false;
}
Note: I'm not a C# expert and there might be a better way to code IsDialogInStack, but the code above works fine.
using suggestedactions in waterstepcontext
private static async Task PromptOptions3(string prompt, string optionA, string optionB, string optionC, WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var reply = stepContext.Context.Activity.CreateReply(prompt);
reply.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = optionA, Value = optionA },
new CardAction() { Title = optionB, Value = optionB },
new CardAction() { Title = optionC, Value = optionC },
},
};
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
}
private async Task<DialogTurnResult> PromptForRequestStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Save name, if prompted.
var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context);
var lowerCaseName = stepContext.Result as string;
if (string.IsNullOrWhiteSpace(greetingState.Name) && lowerCaseName != null)
{
// Capitalize and set name.
greetingState.Name = char.ToUpper(lowerCaseName[0]) + lowerCaseName.Substring(1);
await UserProfileAccessor.SetAsync(stepContext.Context, greetingState);
}
if (greetingState.Request == "1")
{
var opts = new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = "please work"
},
};
await PromptOptions3("Choose from the following:", "Login to OneDrive", "Upload a file", "Create a folder", stepContext, cancellationToken);
return await stepContext.PromptAsync(OneDrivePrompt, opts);
}
The suggested actions do not show up. I expected it to show up and the user can just click it as an input instead of typing. It worked when i tried it in a simpler code not in waterfallstep.. I have no idea how to fix this as I am not familar with the bot framework.
So, I don't know what kind of prompt your OneDrivePrompt is right now, but I'm going to guess that it's not a ChoicePrompt and, frankly, that's what you really want here because it will do all the work of presenting a set of options and making sure a person chooses one of them.
First, you want to change your OneDrivePrompt to a ChoicePrompt configured like so:
yourDialogSet.Add(new ChoicePrompt(OneDrivePrompt) { Style = ListStyle.SuggestedAction });
Next you'll want to change your waterfall step to work with the ChoicePrompt specifically to let it present the options and validate that one of them is chosen:
private async Task<DialogTurnResult> PromptForRequestStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Save name, if prompted.
var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context);
var lowerCaseName = stepContext.Result as string;
if (string.IsNullOrWhiteSpace(greetingState.Name) && lowerCaseName != null)
{
// Capitalize and set name.
greetingState.Name = char.ToUpper(lowerCaseName[0]) + lowerCaseName.Substring(1);
await UserProfileAccessor.SetAsync(stepContext.Context, greetingState);
}
if (greetingState.Request == "1")
{
var opts = new PromptOptions
{
Prompt = MessageFactory.Text("Choose from the following:")
Choices = new List<Choice>
{
new Choice("Login to OneDrive"),
new Choice("Upload a file"),
new Choice("Create a folder"),
},
};
return await stepContext.PromptAsync(OneDrivePrompt, opts);
}