Change flow of messages in Microsoft Bot Framework
This is a great question.The key thing is to use the SetActive and SetNext methods of the Field<T>
class. You should consider using the FieldReflector class; though you can implement your own IField.
SetActive is described in the Dynamic Fields section of the FormFlow documentation. Basically it provides a delegate that enables the field based on a condition.
SetNext will allow you to decide what step of the form should come next based on your custom logic.
You can take a look to the ContosoFlowers sample. In the Order form; something similar is being done.
public static IForm<Order> BuildOrderForm()
{
return new FormBuilder<Order>()
.Field(nameof(RecipientFirstName))
.Field(nameof(RecipientLastName))
.Field(nameof(RecipientPhoneNumber))
.Field(nameof(Note))
.Field(new FieldReflector<Order>(nameof(UseSavedSenderInfo))
.SetActive(state => state.AskToUseSavedSenderInfo)
.SetNext((value, state) =>
{
var selection = (UseSaveInfoResponse)value;
if (selection == UseSaveInfoResponse.Edit)
{
state.SenderEmail = null;
state.SenderPhoneNumber = null;
return new NextStep(new[] { nameof(SenderEmail) });
}
else
{
return new NextStep();
}
}))
.Field(new FieldReflector<Order>(nameof(SenderEmail))
.SetActive(state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.SetNext(
(value, state) => (state.UseSavedSenderInfo == UseSaveInfoResponse.Edit)
? new NextStep(new[] { nameof(SenderPhoneNumber) })
: new NextStep()))
.Field(nameof(SenderPhoneNumber), state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.Field(nameof(SaveSenderInfo), state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.Build();
}
}
}
Cancel Or Exit from PromptDialog.Choice Flow in Microsoft Bot Framework
First of all this is not a Form Flow. This is prompt.
Now You can do something like, either you exit the dialog from the stack like this
try
{
string optionSelected = await result;
switch (optionSelected)
{
case FlightsOption:
context.Call(new FlightDialog(), this.ResumeAfterOptionDialog);
break;
case HotelsOption:
context.Call(new HotelsDialog(), this.ResumeAfterOptionDialog);
break;
case TrainOption:
context.Call(new TrainDialog(), this.ResumeAfterOptionDialog);
break;
case GobackOption:
context.Done<object>(null);
break;
}
}
Or,
You can tell something and then wait for other message in the same dialog like this
try
{
string optionSelected = await result;
switch (optionSelected)
{
case FlightsOption:
context.Call(new FlightDialog(), this.ResumeAfterOptionDialog);
break;
case HotelsOption:
context.Call(new HotelsDialog(), this.ResumeAfterOptionDialog);
break;
case TrainOption:
context.Call(new TrainDialog(), this.ResumeAfterOptionDialog);
break;
case GobackOption:
await context.PostAsync("Ok, you came back. Now tell something new.");
context.Wait(MessageReceivedAsync);
break;
}
}
And the next message will go here
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
context.Wait(MessageReceivedAsync);
}
How can i customize answer of Bot Framework Help Command?
You can use the Template attribute on top of your Form definition to override the Help string pattern. The pattern is located in the Resources.resx of Microsoft.Bot.Builder project.
[Template(TemplateUsage.Help, new string[] { "My custom Help message" })]
MS Bot Framework Conversation with Decisions
This, as suspected, turned out to be much easier that I thought..
Here is my solution...
This is my controller:
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
// check if activity is of type message
if (activity != null && activity.GetActivityType() == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new Dialogs.BillSharkDialog());
}
else
{
HandleSystemMessage(activity);
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}
And here is the "Dialog" with just 2 steps...
[Serializable]
public class BillSharkDialog : IDialog<object>
{
Model.Customer customer = new Model.Customer();
public async Task StartAsync(IDialogContext context)
{
context.Wait(WelcomeMessageAsync);
}
public async Task WelcomeMessageAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
await context.PostAsync("We're excited to start helping you save! Let's start by getting your name?");
context.Wait(CaptureCustomerNameAsync);
}
public async Task CaptureCustomerNameAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
customer.customerName = message.Text;
await context.PostAsync($"Thanks {message.Text}. Now we need your email address?");
context.Wait(CaptureCustomerEmailAsync);
}
}
You can obviously change the route by checking the incoming message..
Here is an example:
public async Task DoesCustomerHaveBillAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
switch (message.Text.ToLower())
{
case "yes":
await context.PostAsync($"Great. Go ahead and take a picture of the first couple of pages and attach them to this conversation.\n\n\nWhen you have finished, please send the message 'finished'.");
context.Wait(CustomerHasBillAsync);
break;
case "no":
await context.PostAsync($"That's OK. Do you happen to have the login information for your provider account?");
context.Wait(CustomerDoesntHaveBillAsync);
break;
default:
await context.PostAsync($"Sorry, I didn't undestand. Please reply with 'yes' or 'no'.");
context.Wait(DoesCustomerHaveBillAsync);
break;
}
}
How do I give a delayed response in Microsoft Bot Framework
Try instantiating the client in the following way
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var client = scope.Resolve<IConnectorClient>();
client.Messages.SendMessage(message);
}
Related Topics
How to Delete a Row from Gridview
Rotate a Graphics Bitmap at Its Center
How to Get the Text of a Messagebox When It Has an Icon
Open a Folder Using Process.Start
Collection Was Modified; Enumeration May Not Execute Error When Removing a Listitem from a Listbox
How to Compile and Run C# Program Without Using Visual Studio
Proper Datagrid Search from Textbox in Wpf Using Mvvm
Checking If an Object Is a Number in C#
ASP.NET Dynamically Button with Event Handler
Different Ways of Adding to Dictionary
When Not to Use Yield (Return)
In C#, Is "This" Keyword Required
Datetime.Adddays() Not Working as Expected
Getting Time Span Between Two Times in C#
C# Code for Association, Aggregation, Composition
Best Way to Share Data Between Two Child Components in Blazor