简体   繁体   English

BOT框架主动消息无法正常工作

[英]BOT Framework Proactive message not working

I am working on Proactive message for a BOT hosted in IIS and registered in Azure as a BOT Channel registration BOT. 我正在为IIS中托管的BOT处理Proactive消息,并在Azure中注册为BOT频道注册BOT。

I am getting below error, 我收到以下错误,

Message: Operation returned an invalid status code 'Unauthorized' 消息:操作返回无效的状态代码'未授权'

StackTrace : at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Bot.Connector.ConversationsExtensions.d__17.MoveNext() StackTrace:位于Microsoft.Bot.Connector.ConversationsExtensions.d__17.MoveNext()的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)

The code is as given below, 代码如下,

-- Notify.cs - Notify.cs

public class Notify
    {
        private readonly IBotFrameworkHttpAdapter _adapter;
        private readonly string _appId;
        private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;

        public Notify(IBotFrameworkHttpAdapter adapter, string appId, ConcurrentDictionary<string, ConversationReference> conversationReferences)
        {
            _adapter = adapter;
            _appId = appId;
            _conversationReferences = conversationReferences;
         }

        public async Task<IActionResult> Get()
        {
            try
            {
                foreach (var conversationReference in _conversationReferences.Values)
                {
                    await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
                }

                // Let the caller know proactive messages have been sent
                return new ContentResult()
                {
                    Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
                    ContentType = "text/html",
                    StatusCode = (int)HttpStatusCode.OK,
                };
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
        {
            await turnContext.SendActivityAsync("proactive hello");
        }
    }

Edit 1 : 编辑1:

I am trying to send the proactive message to the bot displayed in the systray icon. 我正在尝试将主动消息发送到系统托盘图标中显示的机器人。 We have created a windows application through which we are sending a windows notification to users. 我们创建了一个Windows应用程序,通过它我们向用户发送Windows通知。 When the user clicks on the notification it opens the bot present in sys tray icon and it should display the same message notification message in BOT as a proactive message. 当用户点击通知时,它会打开sys托盘图标中出现的bot,它应该在BOT中显示相同的消息通知消息作为主动消息。

We are using direct line API to create the conversation reference. 我们使用直接API来创建会话参考。 We are passing the same conversation reference and using ContinueConversationAsync of BotApadater to populate the same message from the opened bot. 我们传递相同的对话参考,并使用BotApadater的ContinueConversationAsync从打开的机器人填充相同的消息。 The entire code of form.cs and Notify.cs is return in the windows application and the bot is hosted on IIS and registered in Azure as a BOT Channel registration BOT. form.cs和Notify.cs的整个代码在Windows应用程序中返回,僵尸程序托管在IIS上,并在Azure中注册为BOT频道注册BOT。

Currently, we are not getting Unauthorized error and code is executed successfully, but we are not getting any proactive message from the bot. 目前,我们没有收到未经授权的错误并且代码已成功执行,但我们没有收到来自机器人的任何主动消息。 For opening the bot we are using iframe URL in windows application. 为了打开机器人,我们在Windows应用程序中使用iframe URL。

Kindly help what I am doing wrong here or suggest some other ways. 请帮助我在这里做错了或建议一些其他方法。

Window systray application Form.cs Method Window系统应用程序Form.cs方法

using (HttpClient httpClient = new HttpClient())
            {
                httpClient.BaseAddress = new Uri("https://directline.botframework.com/api/tokens");
                httpClient.DefaultRequestHeaders.Accept.Clear();
                //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "Directline secret");     
                HttpResponseMessage response = httpClient.GetAsync(httpClient.BaseAddress).Result;


                if (response.IsSuccessStatusCode)
                {
                    var jsonString = response.Content.ReadAsStringAsync();
                    var token = jsonString.Result;
                    var finaltoken = token.Replace(@"\", string.Empty);
                    finaltoken = finaltoken.Replace('"', ' ').Trim();

                    HttpClient client = new HttpClient();
                    client.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations");
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(finaltoken);
                    var httptokenResponse = httpClient.PostAsync("/api/conversations/", new StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"));
                    var tokenResponse = httptokenResponse.Result;
                    string convId = string.Empty;
                    string activityId = string.Empty;
                    HttpClient finalclient = new HttpClient();
                    Microsoft.Bot.Schema.Activity act = new Microsoft.Bot.Schema.Activity();
                    ConversationReference convRef = new ConversationReference();
                    if (tokenResponse.IsSuccessStatusCode)
                    {
                        var tokenjsonString = tokenResponse.Content.ReadAsStringAsync().Result;
                        var conversationToken = Newtonsoft.Json.JsonConvert.DeserializeObject<Conversation>(tokenjsonString.ToString());

                        HttpClient lastclient = new HttpClient();
                        lastclient.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations/" + conversationToken.conversationId + "/activities");
                        lastclient.DefaultRequestHeaders.Accept.Clear();
                        lastclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                        lastclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Directline secret");

                        string conversationUrl = conversationToken.conversationId + "/activities/";       
                        string msg2 = "User Message";

                        Rootobject rootobject = new Rootobject();
                        rootobject.type = "message";
                        rootobject.text = msg2;
                        From from = new From();
                        from.id = "User ID";
                        from.user = "User Name";
                        rootobject.from = from;

                        string json = "";
                        json = Newtonsoft.Json.JsonConvert.SerializeObject(rootobject);

                        var httpconvResponse = lastclient.PostAsync(lastclient.BaseAddress, new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
                        var tokenconvResponse = httpconvResponse.Result;

                        if (tokenconvResponse.IsSuccessStatusCode)
                        {
                            var tokenconvjsonString = tokenconvResponse.Content.ReadAsStringAsync().Result;
                            var conversationconvToken = Newtonsoft.Json.JsonConvert.DeserializeObject<ConversationActivityInfo>(tokenconvjsonString.ToString());

                            convId = conversationToken.conversationId;
                            activityId = conversationconvToken.id.Split('|')[1];

                            finalclient.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations/" + conversationToken.conversationId + "/activities");
                            finalclient.DefaultRequestHeaders.Accept.Clear();
                            finalclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            finalclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Directline Secret");

                            var httpconvfinalResponse = finalclient.GetAsync(finalclient.BaseAddress).Result;      
                            var jsonResponseString = httpconvfinalResponse.Content.ReadAsStringAsync();
                            var finalresponse = jsonResponseString.Result;
                            var activitiesObject = Newtonsoft.Json.JsonConvert.DeserializeObject<ActivitiesRO>(finalresponse);
                            act = activitiesObject.activities[1];

                            convRef = act.GetConversationReference();
            }


                    }
        string MicroSoftAppId = "YOUR Microsoft APP ID";
                    string MicroSoftAppPassword = "YOUR Microsoft APP PASSWORD";
        ICredentialProvider credentialProvider = new SimpleCredentialProvider(MicroSoftAppId, MicroSoftAppPassword);
        MicrosoftAppCredentials.TrustServiceUrl(convRef.ServiceUrl);

                    IBotFrameworkHttpAdapter adapter = new BotFrameworkHttpAdapter(credentialProvider);
                    ConcurrentDictionary<string, ConversationReference> conversationReferences = new ConcurrentDictionary<string, ConversationReference>();

                    convRef.Bot = new ChannelAccount("Bot ID", "Bot Name");

                    conversationReferences.GetOrAdd("test", convRef);

                    Notify notify = new Notify(adapter, MicroSoftAppId, conversationReferences);
                    Task<IActionResult> obj = notify.Get();

            }
        }

**Edit 2: ** Please refer below screenshot, we are getting three activity ids after sending a request to below URL, https://directline.botframework.com/v3/directline/conversations/ " + conversationToken.conversationId + "/activities" **编辑2:**请参考下面的屏幕截图,我们在向以下网址发送请求后获得三个活动ID, https://directline.botframework.com/v3/directline/conversations/ “+ conversationToken.conversationId +”/活动”

Out of which we are using Index 1 activity as it contains service URL and user details to whom proactive message needs to send and it does not have BOT details(Bot property), so we are assigning it manually. 我们使用索引1活动,因为它包含主动消息需要发送的服务URL和用户详细信息,并且它没有BOT详细信息(Bot属性),因此我们手动分配它。

在此输入图像描述

I believe your issue could be that you're trying to create a ConversationReference for a conversation that doesn't exist (although I can't tell where convoId comes from). 我相信你的问题可能是你正在尝试为不存在的对话创建一个ConversationReference (尽管我无法分辨convoId来自哪里)。

If this is for a brand new conversation, where the user has not interacted with the bot, you can use CreateConversationAsync . 如果这是一个全新的对话,用户没有与机器人交互,您可以使用CreateConversationAsync You can see how we do it in tests, here : 你可以在这里看到我们如何在测试中做到这一点

var activity = new Activity()
{
    Type = ActivityTypes.Message,
    Recipient = User,
    From = Bot,
    Text = "TEST Create Conversation",
};

var param = new ConversationParameters()
{
    Members = new ChannelAccount[] { User },
    Bot = Bot,
    Activity = activity,
};

var convoId = await client.Conversations.CreateConversationAsync(param);

Note: Some clients don't allow proactive messages when a user has never spoken to the bot (mostly email/SMS-related channels) 注意:当用户从未与机器人通话时,某些客户端不允许主动消息(主要是电子邮件/短信相关频道)

If the user has interacted with the bot, you can use the Proactive Sample for reference. 如果用户与机器人交互,您可以使用主动样本作为参考。 Particularly, here : 特别是, 这里

var conversationReference = activity.GetConversationReference();

Alternatively, it's possibly a TrustServiceUrl Issue . 或者,它可能是TrustServiceUrl问题

You can fix it by adding your channel's ServiceUrls to the list of trusted URLs: 您可以通过将频道的ServiceUrls添加到可信URL列表来解决此问题:

var serviceUrl = <GetThisFrom Activity.ServiceUrl>;

MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

Here's the method definition . 这是方法定义 Note: you can add expiration for this, as well. 注意:您也可以为此添加到期日期。 Otherwise, browsing these issues should help. 否则, 浏览这些问题应该有所帮助。

It's also possible that your bot is sleeping. 您的机器人也可能正在睡觉。 You may be able to resolve the issue by going to Azure Portal > Your App Service > Configuration > General Settings > Always On <enable> 您可以通过转到Azure Portal > Your App Service > Configuration > General Settings > Always On <enable>来解决此问题

Note to others: 别人注意:

This "Trust Service URL Issue" is pretty common. 这种“信任服务URL问题”非常普遍。 This happens for lots of other URLs when trying to use Proactive messaging. 尝试使用主动消息传递时,许多其他URL会发生这种情况。 Just replace serviceUrl with whatever is appropriate for your use case. 只需将serviceUrl替换为适合您用例的内容即可。 And yes, if you're using multiple channels, you can add multiple URLs when using MicrosoftAppCredentials.TrustServiceUrl() by calling it multiple times. 是的,如果您使用多个频道,则可以通过多次调用MicrosoftAppCredentials.TrustServiceUrl()来添加多个URL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM