任何人都知道如何在另一个对话框类中调用此类,我是使用microsoft bot框架的初学者。我从https://ankitbko.github.io/2017/03/human-handover-bot/获得了此代码,我需要从我的FormBuilder对话框中调用它。请帮我。我传递文本LiveChat来触发实时聊天对话框类。
我收到此错误
邮件失败:无效类型:预期 Microsoft.Bot.Connector.IMessageActivity,具有String Bot异常: 堆栈为空[文件类型'text / plain']
接口类对话框:
namespace AgentTransferBot
{
[Serializable]
public class EchoDialog : IDialog<object>
{
private readonly IUserToAgent _userToAgent;
public EchoDialog(IUserToAgent userToAgent)
{
_userToAgent = userToAgent;
}
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceived);
}
private async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if (message.Text.StartsWith("LiveChat"))
{
var agent = await _userToAgent.IntitiateConversationWithAgentAsync(message as Activity, default(CancellationToken));
if (agent == null)
await context.PostAsync("All our customer care representatives are busy at the moment. Please try after some time.");
}
else
{
await context.PostAsync(message.Text);
}
context.Done(true);
}
}
}
RootDialog类
namespace AgentTransferBot.Dialog
{
[Serializable]
public class RootDialog : IDialog<object>
{
private const string Existing = "Existing Customer";
private const string NewCustomer = "New Application";
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if(message.Text.ToLower().Contains("help") || message.Text.ToLower().Contains("support") || message.Text.ToLower().Contains("problem"))
{
//await context.Forward(new SupportDialog(), this.ResumeAfterSupportDialog, message, CancellationToken.None);
}
else
{
this.ShowOptions(context);
}
}
private void ShowOptions(IDialogContext context)
{
context.PostAsync("Welcome to X Company Customer Support!");
PromptDialog.Choice(context, this.OnOptionSelected, new List<string>() { Existing, NewCustomer }, "Are you an existing or new customer?", "Not a valid option", 3);
}
private async Task OnOptionSelected(IDialogContext context, IAwaitable<string> result)
{
try
{
string optionSelected = await result;
switch (optionSelected)
{
case Existing:
context.Call(new ExistingDialog(), this.ResumeAfterOptionDialog);
break;
case NewCustomer:
//context.Call();
break;
}
}
catch (TooManyAttemptsException ex)
{
await context.PostAsync($"Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!");
context.Wait(this.MessageReceivedAsync);
}
}
private async Task ResumeAfterSupportDialog(IDialogContext context, IAwaitable<int> result)
{
var ticketNumber = await result;
await context.PostAsync($"Thanks for contacting our support team. Your ticket number is {ticketNumber}.");
context.Wait(this.MessageReceivedAsync);
}
private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
{
try
{
var message = await result;
}
catch(Exception ex)
{
await context.PostAsync($"Failed with message: {ex.Message}");
}
finally
{
context.Wait(this.MessageReceivedAsync);
}
}
}
}
现有对话类:
namespace AgentTransferBot.Dialog
{
private readonly IUserToAgent _userToAgent;
[Serializable]
public class ExistingDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
var existingCustomerDialog = FormDialog.FromForm(this.ExistingChoiceFormDialog, FormOptions.PromptInStart);
context.Call(existingCustomerDialog, this.ResumeAfterExistingOptionDialog);
}
private IForm<ExistingQuestionsQuery> ExistingChoiceFormDialog()
{
OnCompletionAsyncDelegate<ExistingQuestionsQuery> processExistingChoices = async (context, state) =>
{
var type = state.ExistingChoices.ToString();
if (state.ExistingChoices.Equals(ExistingChoices.Postpaid))
{
await context.PostAsync(type);
}
else if (state.ExistingChoices.Equals(ExistingChoices.Prepaid))
{
await context.PostAsync(type);
}
else if (state.ExistingChoices.Equals(ExistingChoices.LiveChat))
{
await context.Forward(new EchoDialog(_userToAgent), this.ResumeAfterSupportDialog, type, CancellationToken.None);
}
};
return new FormBuilder<ExistingQuestionsQuery>()
.Field(nameof(ExistingQuestionsQuery.PhoneNumber))
.Confirm("Is your phone number correct?: {PhoneNumber} {||}")
.AddRemainingFields()
.OnCompletion(processExistingChoices)
.Build();
}
private async Task ResumeAfterExistingOptionDialog(IDialogContext context, IAwaitable<ExistingQuestionsQuery> result)
{
try
{
var existingQuery = await result;
}
catch (FormCanceledException ex)
{
string reply;
if (ex.InnerException == null)
{
reply = "You have canceled the operation. Quitting from the Existing Dialog";
}
else
{
reply = $"Oops! Something went wrong :( Technical Details: {ex.InnerException.Message}";
}
await context.PostAsync(reply);
}
finally
{
context.Done<object>(null);
}
}
private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
{
try
{
var message = await result;
}
catch (Exception ex)
{
await context.PostAsync($"Failed with message: {ex.Message}");
}
finally
{
context.Done(this);
}
}
}
}
IUserToAgent类
namespace AgentTransferBot
{
public interface IUserToAgent
{
Task<bool> AgentTransferRequiredAsync(Activity message, CancellationToken cancellationToken);
Task SendToAgentAsync(Activity message, CancellationToken cancellationToken);
Task<Agent> IntitiateConversationWithAgentAsync(Activity message, CancellationToken cancellationToken);
}
}
Controller.cs
namespace AgentTransferBot
{
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new RootDialog());
}
else
{
await HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
private async Task<Activity> HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
else if (message.Type == ActivityTypes.Event)
{
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var cancellationToken = default(CancellationToken);
var agentService = scope.Resolve<IAgentService>();
switch (message.AsEventActivity().Name)
{
case "connect":
await agentService.RegisterAgentAsync(message, cancellationToken);
break;
case "disconnect":
await agentService.UnregisterAgentAsync(message, cancellationToken);
break;
case "stopConversation":
await StopConversation(agentService, message, cancellationToken);
await agentService.RegisterAgentAsync(message, cancellationToken);
break;
default:
break;
}
}
}
return null;
}
private async Task StopConversation(IAgentService agentService, Activity agentActivity, CancellationToken cancellationToken)
{
var user = await agentService.GetUserInConversationAsync(agentActivity, cancellationToken);
var agentReply = agentActivity.CreateReply();
if (user == null)
{
agentReply.Text = "Hey! You were not talking to anyone.";
await SendToConversationAsync(agentReply);
return;
}
var userActivity = user.ConversationReference.GetPostToBotMessage();
await agentService.StopAgentUserConversationAsync(
userActivity,
agentActivity,
cancellationToken);
var userReply = userActivity.CreateReply();
userReply.Text = "You have been disconnected from our representative.";
await SendToConversationAsync(userReply);
userReply.Text = "But we can still talk :)";
await SendToConversationAsync(userReply);
agentReply.Text = "You have stopped the conversation.";
await SendToConversationAsync(agentReply);
}
private async Task SendAsync(IMessageActivity toBot, Func<ILifetimeScope, IDialog<object>> MakeRoot, CancellationToken token = default(CancellationToken))
{
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, toBot))
{
DialogModule_MakeRoot.Register(scope, () => MakeRoot(scope));
var task = scope.Resolve<IPostToBot>();
await task.PostAsync(toBot, token);
}
}
}
}
ExistingQuery.cs
namespace AgentTransferBot.Queries
{
public enum CustomerType
{
[Terms(new string[] { "Existing Customer", "New Application" })]
Existing = 1,
NewCustomer
}
public enum ExistingChoices
{
Postpaid = 1,
Prepaid,
[EnumMember(Value = "Live Chat")]
LiveChat
}
[Serializable]
public class ExistingQuestionsQuery
{
[Prompt("What is your phone number?")]
public string PhoneNumber { get; set; }
[Prompt("What is your plan type or do you want to talk to our represantives? {||}")]
public ExistingChoices ExistingChoices { get; set; }
}
}