问题
Hi Guys im new to bot development, and im trying to figure out how can i forward the conversation to a QnaDialog after formflow. My formflow simply asks the user his/her name after he/she was identified, it would simply say hi (username) afterwards what I want is that any message afterwards would be forwarded to a QnaDialog already since the user was already identified. I tried adding a checker once to flag that a greeting was done already, however since you are only allowed one Conversation.SendAsync I am now lost for ideas on how to correct this properly.
FORMFLOW
public class ProfileForm
{
// these are the fields that will hold the data
// we will gather with the form
[Prompt("What is your name? {||}")]
public string Name;
// This method 'builds' the form
// This method will be called by code we will place
// in the MakeRootDialog method of the MessagesControlller.cs file
public static IForm<ProfileForm> BuildForm()
{
return new FormBuilder<ProfileForm>()
.Message("Welcome to the profile bot!")
.OnCompletion(async (context, profileForm) =>
{
// Set BotUserData
context.PrivateConversationData.SetValue<bool>("ProfileComplete", true);
context.PrivateConversationData.SetValue<string>("Name", profileForm.Name);
// Tell the user that the form is complete
await context.PostAsync("Your profile is complete.");
})
.Build();
}
}
MessageController
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
//ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
//await Conversation.SendAsync(activity, () => new QnADialog());
#region Formflow
// Get any saved values
StateClient sc = activity.GetStateClient();
BotData userData = sc.BotState.GetPrivateConversationData(
activity.ChannelId, activity.Conversation.Id, activity.From.Id);
var boolProfileComplete = userData.GetProperty<bool>("ProfileComplete");
if (!boolProfileComplete)
{
// Call our FormFlow by calling MakeRootDialog
await Conversation.SendAsync(activity, MakeRootDialog);
}
else
{
//Check if Personalized Greeting is done
if (userData.GetProperty<bool>("Greet"))
{
//this doesnt work since their should be only one Conversation.SendAsync.
//ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
//await Conversation.SendAsync(activity, () => new QnADialog());
}
else
{
// Get the saved profile values
var Name = userData.GetProperty<string>("Name");
userData.SetProperty<bool>("Greet", true);
sc.BotState.SetPrivateConversationData(activity.ChannelId, activity.Conversation.Id,activity.From.Id, userData);
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity replyMessage = activity.CreateReply(string.Format("Hi {0}!", Name));
await connector.Conversations.ReplyToActivityAsync(replyMessage);
}
}
#endregion
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
回答1:
Here is an example using your example. I made a few small changes but nothing you wouldn't be able to spot. A bit of explanation:
Controller: I cleaned it up. It should really only be calling the root dialog. This is much cleaner.
RootDialog: Will first call the form. If the form was successful it will continue to the QnA dialog.
ProfileForm: only deleted the FormCompleted boolean. Was not necessary.
QnADialog: Will start the dialog and ask a question, using the name filled in. I kept the default code to get some feedback.
Hope this helps
Controller
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
RootDialog
[Serializable]
public class RootDialog : IDialog<object>
{
public Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task ResumeAfterForm(IDialogContext context, IAwaitable<ProfileForm> result)
{
if (context.PrivateConversationData.TryGetValue("Name", out string name))
{
context.Call(new QnADialog(), MessageReceivedAsync);
}
else
{
await context.PostAsync("Something went wrong.");
context.Wait(MessageReceivedAsync);
}
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var form = new FormDialog<ProfileForm>(new ProfileForm(), ProfileForm.BuildForm, FormOptions.PromptInStart);
context.Call(form, ResumeAfterForm);
}
}
ProfileForm
[Serializable]
public class ProfileForm
{
// these are the fields that will hold the data
// we will gather with the form
[Prompt("What is your name? {||}")]
public string Name;
// This method 'builds' the form
// This method will be called by code we will place
// in the MakeRootDialog method of the MessagesControlller.cs file
public static IForm<ProfileForm> BuildForm()
{
return new FormBuilder<ProfileForm>()
.Message("Welcome to the profile bot!")
.OnCompletion(async (context, profileForm) =>
{
// Set BotUserData
//context.PrivateConversationData.SetValue<bool>("ProfileComplete", true);
context.PrivateConversationData.SetValue<string>("Name", profileForm.Name);
// Tell the user that the form is complete
await context.PostAsync("Your profile is complete.");
})
.Build();
}
}
QnADialog
[Serializable]
public class QnADialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.PrivateConversationData.TryGetValue("Name", out string name);
await context.PostAsync($"Hello {name}. The QnA Dialog was started. Ask a question.");
context.Wait(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
// calculate something for us to return
int length = (activity.Text ?? string.Empty).Length;
// return our reply to the user
await context.PostAsync($"You sent {activity.Text} which was {length} characters");
context.Wait(MessageReceivedAsync);
}
}
来源:https://stackoverflow.com/questions/43652451/how-to-forward-conversation-from-formflow-to-qnadialog