Reputation: 61
How can I get user input before building the form. For example if the user typed "exit" at any time during the formflow, I want to save the user input into a status variable and check if it equals "exit" and if it does then return null or do some code.
namespace MyBot.Helpers
{
public enum Person
{
// [Describe("I am a Student")]
IAmStudent,
// [Describe("I am an Alumni")]
IAmAlumni,
// [Describe("Other")]
Other
};
public enum HardInfo { Yes, No };
[Serializable]
public class FeedBackClass
{
public bool AskToSpecifyOther = true;
public string OtherRequest = string.Empty;
[Prompt("May I Have Your Name?")]
[Pattern(@"^[a-zA-Z ]*$")]
public string Name { get; set; }
[Prompt("What is your Email Address?")]
public string Email { get; set; }
[Prompt("Please Select From The Following? {||}")]
[Template(TemplateUsage.NotUnderstood, "What does \"{0}\" mean?", ChoiceStyle = ChoiceStyleOptions.Auto)]
public Person? PersonType { get; set; }
[Prompt("Please Specify Other? {||}")]
public string OtherType { get; set; }
[Prompt("Was The Information You Are Looking For Hard To Find? {||}")]
[Template(TemplateUsage.NotUnderstood, "What does \"{0}\" mean?", ChoiceStyle = ChoiceStyleOptions.Auto)]
public HardInfo? HardToFindInfo { get; set; }
public static IForm<FeedBackClass> MYBuildForm()
{
var status = "exit";
if (status == null) {
return null;
}
else
{
return new FormBuilder<FeedBackClass>()
.Field(nameof(Name), validate: ValidateName)
.Field(nameof(Email), validate: ValidateContactInformation)
.Field(new FieldReflector<FeedBackClass>(nameof(PersonType))
.SetActive(state => state.AskToSpecifyOther)
.SetNext(SetNext))
.Field(nameof(OtherType), state => state.OtherRequest.Contains("oth"))
.Field(nameof(HardToFindInfo)).Confirm("Is this your selection?\n{*}")
.OnCompletion(async (context, state) =>
{
await context.PostAsync("Thanks for your feedback! You are Awsome!");
context.Done<object>(new object());
})
.Build();
}
Upvotes: 1
Views: 643
Reputation: 27825
if the user typed "exit" at any time during the formflow, I want to save the user input into a status variable and check if it equals "exit" and if it does then return null or do some code.
It seems that you’d like to implement global handler to process "exit" command. Scorables can intercept every message sent to a Conversation and apply a score to the message based on logic you define, which can help you achieve it, you can try it.
For detailed information, please refer to Global message handlers using scorables or this Global Message Handlers Sample
The following code snippet work for me, you can refer to it.
ExitDialog:
public class ExitDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("This is the Settings Dialog. Reply with anything to return to prior dialog.");
context.Wait(this.MessageReceived);
}
private async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if ((message.Text != null) && (message.Text.Trim().Length > 0))
{
context.Done<object>(null);
}
else
{
context.Fail(new Exception("Message was not a string or was an empty string."));
}
}
}
ExitScorable:
public class ExitScorable : ScorableBase<IActivity, string, double>
{
private readonly IDialogTask task;
public ExitScorable(IDialogTask task)
{
SetField.NotNull(out this.task, nameof(task), task);
}
protected override async Task<string> PrepareAsync(IActivity activity, CancellationToken token)
{
var message = activity as IMessageActivity;
if (message != null && !string.IsNullOrWhiteSpace(message.Text))
{
if (message.Text.ToLower().Equals("exit", StringComparison.InvariantCultureIgnoreCase))
{
return message.Text;
}
}
return null;
}
protected override bool HasScore(IActivity item, string state)
{
return state != null;
}
protected override double GetScore(IActivity item, string state)
{
return 1.0;
}
protected override async Task PostAsync(IActivity item, string state, CancellationToken token)
{
var message = item as IMessageActivity;
if (message != null)
{
var settingsDialog = new ExitDialog();
var interruption = settingsDialog.Void<object, IMessageActivity>();
this.task.Call(interruption, null);
await this.task.PollAsync(token);
}
}
protected override Task DoneAsync(IActivity item, string state, CancellationToken token)
{
return Task.CompletedTask;
}
}
GlobalMessageHandlersBotModule:
public class GlobalMessageHandlersBotModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder
.Register(c => new ExitScorable(c.Resolve<IDialogTask>()))
.As<IScorable<IActivity, double>>()
.InstancePerLifetimeScope();
}
}
Register the module:
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new ReflectionSurrogateModule());
builder.RegisterModule<GlobalMessageHandlersBotModule>();
});
Test result:
Upvotes: 1