Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
520 views
in Technique[技术] by (71.8m points)

botframework - Display Welcome Message in v4 Bot Framework Bot (C# + .Net Core Web Application)

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 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);
}
}

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.

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.

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 Code looks like below:

 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");
        }

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.

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 -

Bot Window with two Welcome Messages

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.

Bot Window with only one Welcome Message

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)
);

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 Chat Code

<!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>

Bot Code - 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);
            }
        }
    }
}

Screen Capture

enter image description here

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.

Hope this helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...