I am working on Proactive message for a BOT hosted in IIS and registered in Azure as a BOT Channel registration 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()
The code is as given below,
-- 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 :
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. 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.
We are using direct line API to create the conversation reference. We are passing the same conversation reference and using ContinueConversationAsync of BotApadater to populate the same message from the opened bot. 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.
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.
Kindly help what I am doing wrong here or suggest some other ways.
Window systray application Form.cs Method
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"
Out of which we are using Index1 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.
convRef.Bot
. If you can provide yourappId
, I can dig into this a little further. – mdrichardsonfrom
property. 2) Is your client connected via web socket? If not, it has to retrieve the activities – mdrichardson