在v4 Bot Framework Bot中显示欢迎消息(C#+ .Net Core Web应用程序)

问题描述:

我用v3(C#)SDK创建了一个漫游器,欢迎消息过去工作得很顺利,没有任何汗水.而且在生产中它仍然对我有用.像这样在HandleSystemMessage中处理代码-

I had created a bot with v3 (C#) SDK and the welcome message used to work just fine without any sweat. And it still does for me in production. The code is handled in HandleSystemMessage like this -

.. v3代码为清晰起见删除了其他代码...

.. v3 Code additional code removed for clarity...

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

//Code to show Welcome Message
if (message.MembersAdded.Any(o => o.Id == message.Recipient.Id))
{
var reply = message.CreateReply();
reply.Attachments = new List<Attachment>();
// Create the attachment.
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = AdaptiveCardHelper.GetOptionsCard()
};
reply.Attachments.Add(attachment);
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
await connector.Conversations.ReplyToActivityAsync(reply);
}
}

我使用的网络聊天版本是BotFramework-WebChat-0.11.4,我在其中进行了一些自定义以实现带评论的facebook点赞/点赞功能.

The Web Chat version that I use is BotFramework-WebChat-0.11.4, I have done certain customizations in it to implement facebook Like/Unlike feature with comment.

现在,我正在将漫游器迁移到v4 SDK(C#+ .Net Core Web App),并且打算使用相同的旧版Webchat.但是我花了两天时间才能在同一网络聊天中显示欢迎消息,同时在模拟器(由于这两个ConversationUpdate)事件上也能很好地工作.

Now I am migrating the bots to v4 SDK (C# + .Net Core Web App), and I am intending to use the same old version of webchat. But I am struggling for two days to get a welcome message displayed in the same web chat while it works well on emulator (given to that two ConversationUpdate) events.

我尝试使用本文提供的解决方案发送消息以及事件,并尝试在Bot中使用不同的异步方法OnEventAsync,OnEventActivityAsync,OnMessageActivityAsync捕获消息.

I have tried sending a message as well as an event using the solution provided in this article and tried to catch that in Bot on different async methods OnEventAsync, OnEventActivityAsync, OnMessageActivityAsync.

https://blog.botframework.com/2018/07/12/how-to-properly-send-a-greeting-message-and-common-issues-from-customers/

V4代码如下:

 protected override async Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            if (turnContext.Activity.MembersAdded != null)
            {
                if (turnContext.Activity.MembersAdded.Any(m => m.Id != turnContext.Activity.Recipient?.Id))
                {
                    //var welcomeCard = CreateAdaptiveCardAttachment();
                    //var response = CreateResponse(turnContext.Activity, welcomeCard);
                    //await turnContext.SendActivityAsync(response, cancellationToken);

                    await Utility.LogTraceAsync("Inside OnConversationUpdateActivityAsync");

                        var eventActivity = turnContext.Activity.AsConversationUpdateActivity();

                        ConnectorClient connector = new ConnectorClient(new Uri(eventActivity.ServiceUrl), Configuration.MicrosoftAppId, Configuration.MicrosoftAppPassword);

                        await Utility.LogTraceAsync("Service URL OnConversationUpdateActivityAsync" + eventActivity.ServiceUrl);

                        await Utility.LogTraceAsync("Recipient ID OnConversationUpdateActivityAsync" + turnContext.Activity.Recipient?.Id);

                        var welcomeCard = CreateAdaptiveCardAttachment();

                        var reply = ((Activity)eventActivity).CreateReply();
                        reply.Attachments.Add(welcomeCard);

                    //var response = CreateResponse(turnContext.Activity, welcomeCard);
                    await connector.Conversations.ReplyToActivityAsync(reply, cancellationToken);// turnContext.SendActivityAsync(response, cancellationToken);

                        await Utility.LogTraceAsync("OnConversationUpdateActivityAsync Response Returned.");

                    await Utility.LogTraceAsync("Exit OnConversationUpdateActivityAsync");
                }
            }
        }

        protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
        {
            await Utility.LogTraceAsync("Inside OnEventActivityAsync");
            if (turnContext.Activity.Type == ActivityTypes.Event)
            {
                var eventActivity = turnContext.Activity.AsEventActivity();

                await Utility.LogTraceAsync("Event Activity from WebChat matched.");

                ConnectorClient connector = new ConnectorClient(new Uri(eventActivity.ServiceUrl), Configuration.MicrosoftAppId, Configuration.MicrosoftAppPassword);

                await Utility.LogTraceAsync("Service URL " + eventActivity.ServiceUrl);

                var welcomeCard = CreateAdaptiveCardAttachment();

                var reply = ((Activity)eventActivity).CreateReply();
                reply.Attachments.Add(welcomeCard);

                var members = await connector.Conversations.GetConversationMembersAsync(eventActivity.Conversation.Id.ToString());
                var membernames = "";
                foreach (var member in members) {
                    membernames += member.Name + ",";
                }

                await Utility.LogTraceAsync(membernames);

                await connector.Conversations.SendToConversationAsync(reply, cancellationToken);

                await connector.Conversations.ReplyToActivityAsync(reply, cancellationToken);// turnContext.SendActivityAsync(response, cancellationToken);

                await Utility.LogTraceAsync("Event Response Returned.");
            }

            await Utility.LogTraceAsync("Exit OnEventActivityAsync");
        }

但是它似乎根本不起作用.我正在拔头发,但对.Net Core App的操作一无所知.我很高兴知道有人是否解决了这个问题.

But it does not seem to work at all. I am pulling my hairs out and there is no clue on how to do for .Net Core App. I will be glad to know if someone has solved this problem.

更新-我在@tdurnford提供的客户端上使用了JS代码,在Bot Side使用了以下两种方法-

Update - I have used the JS code on client-side as provided by @tdurnford and at Bot Side had following two methods -

//Required to Show Welcome Message on Emulator
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in membersAdded ?? Array.Empty<ChannelAccount>())
            {
                // Greet anyone that was not the target (recipient) of this message.
                // To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    Activity reply = ((Activity)turnContext.Activity).CreateReply();
                    AdaptiveCard card = AdaptiveCardHelper.GetWelcomeCard();
                    Attachment attachment = new Attachment()
                    {
                        ContentType = AdaptiveCard.ContentType,
                        Content = card
                    };
                    reply.Attachments.Add(attachment);
                    await turnContext.SendActivityAsync(reply, cancellationToken);
                }
            }
        }

//Required to Show Welcome Message on Web Chat
        protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
        {
            if (turnContext.Activity.Name == "webchat/join")
            {
                Activity reply = ((Activity)turnContext.Activity).CreateReply();
                AdaptiveCard card = AdaptiveCardHelper.GetWelcomeCard();
                Attachment attachment = new Attachment()
                {
                    ContentType = AdaptiveCard.ContentType,
                    Content = card
                };
                reply.Attachments.Add(attachment);
                await turnContext.SendActivityAsync(reply, cancellationToken);
            }
        }

使用这两种方法,聊天窗口中都会显示两条欢迎消息-

With both methods two welcome messages are shown in the chat window -

带有两个欢迎消息的启动窗口

然后,我在C#中注释了OnEventActivityAsync方法,然后再次部署.现在,如窗口所示,它仅显示从OnMemberFyresAsync返回的一条欢迎消息.

Then I've commented the OnEventActivityAsync method in C# and deployed again. Now it shows only one welcome message returned from OnMembersAddedAsync as shown in the window.

只有一个欢迎消息的启动窗口

如果我在网上聊天代码中注释了以下代码行,即不发送活动后信息-

If I comment the following code lines in the webchat code i.e. don't send the post-activity -

botConnection.postActivity({
    from: {
        id: 'myUserId',
        name: 'myUserName'
    },
    type: 'event',
    name: 'webchat/join',
    value: {
        locale: 'en-US'
    }
}).subscribe(
    id => console.log("Posted welcome event, assigned ID ", id),
    error => console.log("Error posting activity", error)
);

在这种情况下,不会显示欢迎消息. @tdurnford,请检查您是否能够复制此行为.

In this case, no welcome message is displayed. @tdurnford, please check if you are able to replicate this behavior.

尽管这样还有另一个问题,当用户在机器人中键入问题时,会再次显示欢迎消息. 启动窗口中有两个欢迎消息,一个正在加载,另一个在第一个问题后出现

Although there is another problem here in this way that when a user types a question in the bot, then a welcome message is displayed again. Bot window with two welcome messages one on load and another after the first question

通常,初始化对话后,通道会发送两个对话更新事件-一个是针对漫游器的,另一个是针对用户的.第二个事件-用户事件-旨在触发欢迎消息.与某些其他渠道不同,Web Chat等待发送第二个会话更新事件,直到用户向漫游器发送消息为止.显然,只有在第一条消息之后才发送欢迎消息.要解决此问题,开发人员可以在建立DirectLine连接时向机器人发送反向通道欢迎事件,并从onEventAsync处理程序(而不是onMember Leicester)发送欢迎消息.有关更多详细信息,请查看下面的代码段.

Typically, the channel sends two conversation update events when the conversation is initialized - one for the bot and another for the user. The second one - the event for the user - is intended to trigger the welcome message. Unlike some other channels, Web Chat waits to send the second conversation update event until after the user messages the bot. Evidently, the welcome message won't be sent until after the first message. To workaround this issue, developers can send a back channel welcome event to the bot when the DirectLine connection is established and send a welcome message from the onEventAsync handler instead of onMembersAdded. For more details, take a look at the code snippets below.

Bot聊天代码

<!DOCTYPE html>
<html>
  <head>
    <link href="https://cdn.botframework.com/botframework-webchat/0.11.4/botchat.css" rel="stylesheet" />
    <style>
      #webchat {
        height: 100%;
        width: 100%;
      }
    </style>

  </head>
  <body>
    <div style="display: flex">
      <div style="position: relative; height: 500px; width: 500px"><div id="bot" ></div></div>
    </div>


    <script src="https://cdn.botframework.com/botframework-webchat/0.11.4/botchat.js"></script>

    <script>

      (async function() {

        const res = await fetch('/directline/token', { method: 'POST' });
        const { token }  = await res.json();

        var userinfo = {
              id: 'user-id',
              name: 'user name',
              locale: 'es'
          };

        var botConnection = new window.BotChat.DirectLine({ token });

        botConnection.connectionStatus$
          .subscribe(connectionStatus => {
              switch(connectionStatus) {
                  case window.BotChat.ConnectionStatus.Online:
                    botConnection.postActivity({
                        from: { id: 'myUserId', name: 'myUserName' },
                        type: 'event',
                        name: 'webchat/join',
                        value: { locale: 'en-US' }
                    }).subscribe(
                        id => console.log("Posted welcome event, assigned ID ", id),
                        error => console.log("Error posting activity", error)
                    );
                    break;
              }
          });


        BotChat.App({
          botConnection: botConnection,
          user: userinfo,
          bot: { id: 'botid' },
          resize: 'detect'
        }, document.getElementById("bot"));

      })().catch(err => console.log(err));

    </script>
  </body>
</html>

批号-C#

protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
    if (turnContext.Activity.Name == "webchat/join") {
      await turnContext.SendActivityAsync("Welcome Message!");
    }
}

protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    if (turnContext.Activity.ChannelId != "webchat" && turnContext.Activity.ChannelId != "directline") {

        foreach (var member in membersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                await turnContext.SendActivityAsync($"Hi there - {member.Name}. {WelcomeMessage}", cancellationToken: cancellationToken);
                await turnContext.SendActivityAsync(InfoMessage, cancellationToken: cancellationToken);
                await turnContext.SendActivityAsync(PatternMessage, cancellationToken: cancellationToken);
            }
        }
    }
}

屏幕截图

还请注意,Web Chat v0.11.4被称为Bot Chat或Web Chat v3.抱歉,我对此感到迷恋.

Also note, Web Chat v0.11.4 is referred to as either Bot Chat or Web Chat v3. Sorry I got tripped up on that.

希望这会有所帮助!