Send and receive activities in the v3 C# SDK
APPLIES TO: SDK v3
The Bot Framework Connector provides a single REST API that enables a bot to communicate across multiple channels such as Email, Slack, and more. It facilitates communication between bot and user, by relaying messages from bot to channel and from channel to bot.
This article describes how to use the Connector via the Bot Framework SDK for .NET to exchange information between bot and user on a channel.
Note
While it is possible to construct a bot by exclusively using the techniques that are described in this article, the Bot Framework SDK provides additional features like dialogs and FormFlow that can streamline the process of managing conversation flow and state and make it simpler to incorporate cognitive services such as language understanding.
Create a connector client
The ConnectorClient class contains the methods that a bot uses to communicate with a user on a channel.
When your bot receives an Activity object from the Connector,
it should use the ServiceUrl
specified for that activity to create the connector client that it'll
subsequently use to generate a response.
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
. . .
}
Tip
Because a channel's endpoint may not be stable, your bot should direct communications to the endpoint
that the Connector specifies in the Activity
object, whenever possible (rather than relying upon a cached endpoint).
If your bot needs to initiate the conversation, it can use a cached endpoint for the specified channel
(since there will be no incoming Activity
object in that scenario), but it should refresh cached endpoints often.
Create a reply
The Connector uses an Activity object to pass information back and forth between bot and channel (user).
Every activity contains information used for routing the message to the appropriate destination
along with information about who created the message (From
property),
the context of the message, and the recipient of the message (Recipient
property).
When your bot receives an activity from the Connector, the incoming activity's Recipient
property specifies
the bot's identity in that conversation.
Because some channels (e.g., Slack) assign the bot a new identity when it's added to a conversation,
the bot should always use the value of the incoming activity's Recipient
property as the value of
the From
property in its response.
Although you can create and initialize the outgoing Activity
object yourself from scratch,
the Bot Framework SDK provides an easier way of creating a reply.
By using the incoming activity's CreateReply
method,
you simply specify the message text for the response, and the outgoing activity is created
with the Recipient
, From
, and Conversation
properties automatically populated.
Activity reply = activity.CreateReply($"You sent {activity.Text} which was {length} characters");
Send a reply
Once you've created a reply, you can send it by calling the connector client's ReplyToActivity
method.
The Connector will deliver the reply using the appropriate channel semantics.
await connector.Conversations.ReplyToActivityAsync(reply);
Tip
If your bot is replying to a user's message, always use the ReplyToActivity
method.
Send a (non-reply) message
If your bot is part of a conversation, it can send a message that is not a direct reply to
any message from the user by calling the SendToConversation
method.
await connector.Conversations.SendToConversationAsync((Activity)newMessage);
You may use the CreateReply
method to initialize the new message (which would automatically set
the Recipient
, From
, and Conversation
properties for the message).
Alternatively, you could use the CreateMessageActivity
method to create the new message
and set all property values yourself.
Note
The Bot Framework does not impose any restrictions on the number of messages that a bot may send. However, most channels enforce throttling limits to restrict bots from sending a large number of messages in a short period of time. Additionally, if the bot sends multiple messages in quick succession, the channel may not always render the messages in the proper sequence.
Start a conversation
There may be times when your bot needs to initiate a conversation with one or more users.
You can start a conversation by calling either the CreateDirectConversation
method (for a private conversation with a single user)
or the CreateConversation
method (for a group conversation with multiple users)
to retrieve a ConversationAccount
object.
Then, create the message and send it by calling the SendToConversation
method.
To use either the CreateDirectConversation
method or the CreateConversation
method,
you must first create the connector client by using the target channel's service URL
(which you may retrieve from cache, if you've persisted it from previous messages).
Note
Not all channels support group conversations. To determine whether a channel supports group conversations, consult the channel's documentation.
This code example uses the CreateDirectConversation
method to create a private conversation with a single user.
var userAccount = new ChannelAccount(name: "Larry", id: "@UV357341");
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var conversationId = await connector.Conversations.CreateDirectConversationAsync(botAccount, userAccount);
IMessageActivity message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId.Id);
message.Text = "Hello, Larry!";
message.Locale = "en-Us";
await connector.Conversations.SendToConversationAsync((Activity)message);
This code example uses the CreateConversation
method to create a group conversation with multiple users.
var connector = new ConnectorClient(new Uri(incomingMessage.ServiceUrl));
List<ChannelAccount> participants = new List<ChannelAccount>();
participants.Add(new ChannelAccount("joe@contoso.com", "Joe the Engineer"));
participants.Add(new ChannelAccount("sara@contoso.com", "Sara in Finance"));
ConversationParameters cpMessage = new ConversationParameters(message.Recipient, true, participants, "Quarter End Discussion");
var conversationId = await connector.Conversations.CreateConversationAsync(cpMessage);
IMessageActivity message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = new ChannelAccount("lydia@contoso.com", "Lydia the CFO"));
message.Conversation = new ConversationAccount(id: conversationId.Id);
message.ChannelId = incomingMessage.ChannelId;
message.Text = "Hello, everyone!";
message.Locale = "en-Us";
await connector.Conversations.SendToConversationAsync((Activity)message);