protected async Task <T> InvokeChannelApiAsync <T>(ClaimsIdentity claimsIdentity, string method, string conversationId, params object[] args) { var skillConversation = new SkillConversation(conversationId); var channelApiInvokeActivity = Activity.CreateInvokeActivity(); channelApiInvokeActivity.Name = InvokeActivityName; channelApiInvokeActivity.ChannelId = "unknown"; channelApiInvokeActivity.ServiceUrl = skillConversation.ServiceUrl; channelApiInvokeActivity.Conversation = new ConversationAccount(id: skillConversation.ConversationId); channelApiInvokeActivity.From = new ChannelAccount(id: "unknown"); channelApiInvokeActivity.Recipient = new ChannelAccount(id: "unknown", role: RoleTypes.Bot); var activityPayload = args?.Where(arg => arg is Activity).Cast <Activity>().FirstOrDefault(); if (activityPayload != null) { // fix up activityPayload with original conversation.Id and id activityPayload.Conversation.Id = skillConversation.ConversationId; activityPayload.ServiceUrl = skillConversation.ServiceUrl; // use the activityPayload for channel accounts, it will be in From=Bot/Skill Recipient=User, // We want to send it to the bot as From=User, Recipient=Bot so we have correct state context. channelApiInvokeActivity.ChannelId = activityPayload.ChannelId; channelApiInvokeActivity.From = activityPayload.Recipient; channelApiInvokeActivity.Recipient = activityPayload.From; // We want ActivityPayload to also be in User->Bot context, if it is outbound it will go through context.SendActivity which will flip outgoing to Bot->User // regardless this gives us same memory context of User->Bot which is useful for things like EndOfConversation processing being in the correct memory context. activityPayload.From = channelApiInvokeActivity.From; activityPayload.Recipient = channelApiInvokeActivity.Recipient; } var channelApiArgs = new ChannelApiArgs { Method = method, Args = args }; channelApiInvokeActivity.Value = channelApiArgs; // We call our adapter using the BotAppId claim, so turnContext has the bot claims // var claimsIdentity = new ClaimsIdentity(new List<Claim> // { // new Claim(AuthenticationConstants.AudienceClaim, this.BotAppId), // new Claim(AuthenticationConstants.AppIdClaim, this.BotAppId), // new Claim(AuthenticationConstants.ServiceUrlClaim, skillConversation.ServiceUrl), // }); // send up to the bot to process it... await ChannelAdapter.ProcessActivityAsync(claimsIdentity, (Activity)channelApiInvokeActivity, Bot.OnTurnAsync, CancellationToken.None).ConfigureAwait(false); if (channelApiArgs.Exception != null) { throw channelApiArgs.Exception; } // Return the result that was captured in the middleware handler. return((T)channelApiArgs.Result); }