Botbuilder-dotnet: CreateConversationAsync doesn't pass the tenantId

Created on 6 Sep 2019  Â·  8Comments  Â·  Source: microsoft/botbuilder-dotnet

I created issue in #2199 , actually, i pointed two bugs in that issue, but only one bug was fixed, the other bug is that the tenantId is not used at all in CreateConversationAsync method, see below screenshot:
image

The eventActivity.Conversation should have tenantId value, see below screenshot:

image

Then when run the TenantIdWorkaroundForTeamsMiddleware, the turnContext.Activity.Conversation.TenantId is empty, and will try parse the turnContext.Activity.ChannelData, but the ChannelData is null, see below screenshot:

image

I don't know how the contributor pass the test, can they CreateConversationAsync using the msteams channel to do the test ?

[bug]

Bot Services bug customer-replied-to customer-reported

Most helpful comment

Thanks a lot for all your help, the workaround works perfect, and I will use it for short term.
And @mdrichardson the reason why I chose Adapter.CreateConversationAsync is that it's the most obvious method I can find to send a proactive message, and the Adapter do return the conversationId in the callback ( turnContext.Activity.Conversation ), below is how I use it:

image

All 8 comments

@EricDahlvang, this is an issue with Teams, please take a look. Thanks.

@searlin, We are doing a major iteration on the Bot Framework integration with Teams in the 4.6 cycle (shipping on Oct 31). This work involves full support for Teams in the v4 SDK and will include examples around proactive messaging. @EricDahlvang should be able to get you working in the short term, but be aware of a new version coming soon.

@searlin I'll continue looking into this, but a quick workaround would be to either use this override (which that PR addressed):

public virtual async Task CreateConversationAsync(string channelId, string serviceUrl, MicrosoftAppCredentials credentials, ConversationParameters conversationParameters, BotCallbackHandler callback, ConversationReference reference, CancellationToken cancellationToken)

Edit: Disregard the first option. It looks like it strips out the ChannelData here

or, use Connector Edit: Still valid ✔:

var teamConversationData = turnContext.Activity.GetChannelData<TeamsChannelData>();
var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl), _credentialProvider.AppId, _credentialProvider.Password);

var userId = <UserIdToSendTo>;
var tenantId = teamConversationData.Tenant.Id;
var parameters = new ConversationParameters
{
    Members = new[] { new ChannelAccount(userId) },
    ChannelData = new TeamsChannelData
    {
        Tenant = new TenantInfo(tenantId),
    },
};

var conversationResource = await connectorClient.Conversations.CreateConversationAsync(parameters);
var message = Activity.CreateMessageActivity();
message.Text = "This is a proactive message.";
await connectorClient.Conversations.SendToConversationAsync(conversationResource.Id, (Activity)message);

A Teams message must have ChannelData in order to work with Teams, so I'll look into the specific override you're using and see if there's a PR worth filing against it.

Have a solution w/ the help of @EricDahlvang. Working on PR. Might take a bit to put appropriate tests together. Will also be doing a lot of manual smoke testing to make sure adding in ChannelData doesn't break anything unexpected.

Hi @searlin

Thank you for reporting this, and the clear and concise description of the problem.

Until the fix is released, please let us know if the workaround @mdrichardson provided unblocks you.

@searlin

I don't know how the contributor pass the test, can they CreateConversationAsync using the msteams channel to do the test ?

Turns out the test I wrote for that previous PR uses MockAdapter (which I didn't catch), which overrides the CreateConversationAsync method that needs to be fixed and appropriately sets the ChannelData (whereas the un-Mocked -Adapter does not):

public async override Task CreateConversationAsync(string channelId, string serviceUrl, MicrosoftAppCredentials credentials, ConversationParameters conversationParameters, BotCallbackHandler callback, CancellationToken cancellationToken)
{
    var activity = conversationParameters.Activity;
    activity.ChannelData = new
    {
        conversationParameters.TenantId,
    };
    await RunPipelineAsync(new TurnContext(this, conversationParameters.Activity), callback, cancellationToken).ConfigureAwait(false);

    return;
}

Looks like I've got some work to do and some tests to fix.

@searlin

PR submitted. If I may ask, why are you using Adapter.CreateConversationAsync instead of Connector.CreateConversationAsync? I believe that to do a proactive message, you'd need a reference to the conversationId and Adapter... doesn't return it, whereas Connector... does. Can you share how you're using it (for my own benefit)?

Thanks a lot for all your help, the workaround works perfect, and I will use it for short term.
And @mdrichardson the reason why I chose Adapter.CreateConversationAsync is that it's the most obvious method I can find to send a proactive message, and the Adapter do return the conversationId in the callback ( turnContext.Activity.Conversation ), below is how I use it:

image

Was this page helpful?
0 / 5 - 0 ratings