Closed DrWala closed 6 years ago
Just an update. For some reason the access token now works. However I'm getting this exception:
Error: Unable to deserialize the response.
Trace: at Microsoft.Bot.Connector.Conversations.
Source: Microsoft.Bot.Connector
Key Data: System.Collections.ListDictionaryInternal
This looks very much like some of the existing issues such as #618 and a few other existing stackoverflow posts. I understand that it isn't my place to ask but this task is blocking some other things at the moment, and I'm sort of in need of help fast. If that is possible I would really really appreciate it.
Looking into this, thanks for reporting
Thanks @JasonSowers
I've got some new information which may or may not help. I can reply to normal messages, but that error seems to only occur when responding with a typing activity. The activity is created as such:
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
Activity typing = message.CreateReply();
typing.Type = ActivityTypes.Typing;
typing.Text = null;
await connector.Conversations.ReplyToActivityAsync(typing);
where message
is the incoming activity.
The error occurs when the last line await connector.Conversations.ReplyToActivityAsync(typing);
is being executed, throwing the exception in my post earlier.
What about other activity types is typing the only one throwing the error? Still working on getting a version up and running, feel free to share you mock channel if you can.
From what I see, the error is only thrown only when responding with a typing activity and when I do a manual post to the bot. If I use the existing channels such as Telegram/Web chat/Direct Line, it doesn't throw any errors. I am able to get a typing indicator as well as the expected response
I will test with IActivity typing = message.CreateReply().AsTypingActivity();
and get back to you. My mock channel is merely an ngrok tunnel to my own machine, so it won't always be up haha
Just tested with IActivity typing = message.CreateReply().AsTypingActivity()
. It doesnt send the typing indicator at all.
We are trying pretty hard to reproduce still, but running into our own issues 👎. This is going to end up being a blog post with samples when all is said and done. Again, thanks for reporting this.
Hahahaha thank you @JasonSowers, appreciate the work you guys put in. If you need any more info I'm more than happy to test/help. In the meantime, I've disabled typing when I load test and for some reason the auth tokens work now - which is weird but I'm not complaining.
If I may suggest, could BF eventually have a default message sink for load tests? 😜
Hey guys, any news?
@DrWala Sorry for the extremely delayed response I was out of town then was working on a project. I am unable to reproduce as when I send the typing activity below there is no error:
public static Activity Typing()
{
Activity a = new Activity
{
Type = ActivityTypes.Typing,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
I am sending the activity like this:
var token = GetToken();
var jsonActivity = JsonConvert.SerializeObject(ActivityGenerator.Typing());
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", $"Bearer {token}");
var response = client.UploadString("https://80e5a947.ngrok.io/api/messages", jsonActivity);
//Console.WriteLine(response);
}
I'll dive back into this today and see if I can reproduce with the way you are creating and sending the message. I created this class below to generate all types of activities. It may or may not help you, but i figured I would share. I know it probably needs some edits to be fully useful but it's a good start:
public static class ActivityGenerator
{
public static Activity Message()
{
Activity a = new Activity
{
Type = ActivityTypes.Message,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new {clientActivityId = "1506483656068.11949484894092266.2"})
};
return a;
}
public static Activity ConversationUpdate()
{
Activity a = new Activity();
a.Type = ActivityTypes.ConversationUpdate;
a.Id = "9dn3fa6lh4hd9dn3fa6lh4hd";
a.ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console;
a.Conversation = new ConversationAccount(id: "9dn3fa6lh4hd");
a.From = new ChannelAccount(id: "user", name: "username");
a.Recipient = new ChannelAccount(id: "bot", name: "botname");
a.Text = "Legit Nachos";
a.ServiceUrl = @"http://localhost:55086/api/values";
a.MembersAdded = new List<ChannelAccount>();
a.MembersRemoved = new List<ChannelAccount>();
a.Locale = "en-US";
a.Attachments = new List<Attachment>();
a.ReplyToId = "nii4344blg42";
a.TextFormat = "plain";
a.Timestamp = DateTime.Now;
a.ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" });
return a;
}
public static Activity ContactRelationUpdate()
{
Activity a = new Activity
{
Type = ActivityTypes.ContactRelationUpdate,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity DeleteUserData()
{
Activity a = new Activity
{
Type = ActivityTypes.DeleteUserData,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity EndOfConversation()
{
Activity a = new Activity
{
Type = ActivityTypes.EndOfConversation,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity Event()
{
Activity a = new Activity
{
Type = ActivityTypes.Event,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity InstallationUpdate()
{
Activity a = new Activity
{
Type = ActivityTypes.InstallationUpdate,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity Invoke()
{
Activity a = new Activity
{
Type = ActivityTypes.Invoke,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity MessageReaction()
{
Activity a = new Activity
{
Type = ActivityTypes.MessageReaction,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity Ping()
{
Activity a = new Activity
{
Type = ActivityTypes.Ping,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Legit Nachos",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
return a;
}
public static Activity Typing()
{
Activity a = new Activity
{
Type = ActivityTypes.Typing,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new {clientActivityId = "1506483656068.11949484894092266.2"})
};
return a;
}
}
is there any more code in this method, also where are you calling this method from? I am still unable to reproduce sending a typing activity like below:
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
Activity typing = message.CreateReply();
typing.Type = ActivityTypes.Typing;
typing.Text = null;
await connector.Conversations.ReplyToActivityAsync(typing);
Hi @JasonSowers - So as mentioned earlier the typing activity only messes up when I'm doing the load test following instructions from the BF blog. Under normal situations, it throws no errors and workes seamlessly. So that's kinda odd.
Regarding what else is in that method, the flow is essentially: recieve activity -> check if type is message -> send typing activity -> process message -> send response.
During load testing, if I comment out the send typing bit, I don't get any errors. For the purposes of the load test I wrapped it in a try catch :P
To reporoduce the error, try following the load test instructions at https://blog.botframework.com/2017/06/19/load-testing-a-bot/ and see if returning a typing activity to your sink causes an error.
Regarding the creation of a typing activity altogether, that's odd as the following code returns a typing response on fb, telegram, web chat and direct line
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
Activity typing = message.CreateReply();
typing.Type = ActivityTypes.Typing;
typing.Text = null;
await connector.Conversations.ReplyToActivityAsync(typing);
@DrWala are you at all getting a 415 error "unsupported media type"? I was able to produce this error so far. The flow you are talking about is it...
BOT receive activity -> check if type is message -> send typing activity -> process message -> send response.
or
Mock Channel receive activity -> check if type is message -> send typing activity -> process message -> send response.
@JasonSowers I got the 415 when I missed a content type header only.
Regarding the flow, its technically the mock channel receiving the activity I suppose. What is your definition of Bot vs mock channel?
The bot is the bot itself, the mock channel is what receives the message from the bot.
I set up a message sink using a node server. So I would do a direct post to the bot's endpoint (localhost:3979), it would then receive activity -> check if type is message -> send typing activity -> process message -> send response (to message sink).
Given that's the case, then the flow I'm talking about is the former - Bot receive activity -> ... etc.
I really wish I had a better answer for you but I am just unable to reproduce the Unauthorized 401. Maybe you could put what you have in a repo for us to take a look?
Hi @JasonSowers Give me some time and I will recreate the project I had. Been a busy week, but will get back to you soon
Sounds good, please @ mention me as I have been working on other projects lately and have not been checking GitHub daily.
@DrWala why do u use https://mybotname.azurewebsites.net/api/messages
if in docs, it's said to use
POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
GET https://login.botframework.com/v1/.well-known/openidconfiguration
POST https://smba.trafficmanager.net/apis/v3/conversations/${conversationId}/activities
Question2 : From where u took http://localhost:55086/api/values
? So far I kinda know what /api/messages
fro, but /values? SOmething new. I did not see in docs. Can u point me to docs URL?
PS. I kind stuck on this stage - I want to send simple AJAX call to Bot API so that API triggers skype channel message. I have either 401 or CORS with MS server, and I don't get why and what to do next.
@JasonSowers My schedule has opened up now, I'll restart my testing of this on Monday. Will keep you updated. I'm really sorry for making you wait on this.
@alundiak The first POST request you typed above is the same one I use to get the token. The second GET request is probably only useful if you are using OpenID to authenticate requests from bot connector to your bot, which I personally think is too much hassle.
Additionally, I'm quite sure https://smba.trafficmanager.net/apis/v3/conversations/${conversationId}/activities
is a sample bot url, which can be replaced with any bot url you have.
Lastly, /api/values is probably a custom controller endpoint which @JasonSowers is using to test as a message sink.
If I'm wrong about any of this do let me know :)
Going to close this for inactivity let me know if you are still having issues
Hi @JasonSowers, no issues on my end now. Will reopen if need be.
can any one help me with how to create message sink in c#? and from where I would get Conversation ID?
Are you using c# or node @KetanVidhate
c#
Just create a web API project and hit the endpoint. I just used the default valuesController
that was generated and modified the post
method. you will need to add the Bot.Builder
package to the project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Microsoft.Bot.Connector;
using Newtonsoft.Json;
namespace MockChannel.Controllers
{
public class ValuesController : ApiController
{
public HttpResponseMessage Post([FromBody]Activity value)
{
ConnectorClient connector = new ConnectorClient(new Uri(value.ServiceUrl));
Activity typing = value.CreateReply();
typing.Type = ActivityTypes.Typing;
typing.Text = null;
connector.Conversations.ReplyToActivityAsync(typing);
Activity a = new Activity
{
Type = ActivityTypes.Message,
Id = "9dn3fa6lh4hd9dn3fa6lh4hd",
ChannelId = Microsoft.Bot.Builder.Dialogs.ChannelIds.Console,
Conversation = new ConversationAccount(id: "9dn3fa6lh4hd"),
From = new ChannelAccount(id: "user", name: "username"),
Recipient = new ChannelAccount(id: "bot", name: "botname"),
Text = "Mock Channel",
ServiceUrl = @"http://localhost:55086/api/values",
MembersAdded = new List<ChannelAccount>(),
MembersRemoved = new List<ChannelAccount>(),
Locale = "en-US",
Attachments = new List<Attachment>(),
ReplyToId = "nii4344blg42",
TextFormat = "plain",
Timestamp = DateTime.Now,
ChannelData = JsonConvert.SerializeObject(new { clientActivityId = "1506483656068.11949484894092266.2" })
};
connector.Conversations.SendToConversationAsync(a);
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
}
}
@DrWala How did you solve the problem with the post api/messages.... I have exactly the same problem trying to use load testing to my bot.... everything runs ok but in the last part i get a 401 status code.
Bot Info
Issue Description
I'm attempting to load test my bot using the instructions found here: https://blog.botframework.com/2017/06/19/load-testing-a-bot/ but keep getting a 401 when posting to my bot with the access token.
I attempted to generate an access token by POSTing to https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token with the following header values:
The request returned the generated access token, but I'm unable to send anything to my bot's URL. I'm sending a POST to https://mybotname.azurewebsites.net/api/messages with the following headers
and a sample JSON payload as follows
This results in a 401 with the error message of "BotAuthenticator failed to authenticate incoming request!". However, I can test my bot through direct line, web chat, emulator (both local and remote) as well as telegram. I'm guessing I am doing something wrong with regards to authentication. I've set up a message sink using ngrok for load testing purposes. I don't think it is an issue with the payload as the bot doesn't even authenticate the request in the first place. I've also tried posting to /api/messages/v3 to no avail.
If any more information is needed I'm happy to send it over. Would appreciate any help :)