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

Additional resources