2
votes

I have a bot built using the Microsoft Bot Framework, published in Azure App Service, that I want to post in a Microsoft Teams channel in response to a POST call. I have the following in a WebhookAPIController class, inheriting from ApiController:

[HttpPost]
[Route("api/WebhookAPI")]
public async Task<HttpResponseMessage> RespondToWebhook([FromBody] PostTestModel value)
{
    try
    {
        await CreateChannelConversation(value.text);
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        return resp;
    }
    catch (Exception ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
    }            
}

private async Task CreateChannelConversation(string value)
{
    var connector = new ConnectorClient(new Uri(System.Configuration.ConfigurationManager.AppSettings["serviceUrl"]));
    var channelData = new Dictionary<string, string>();
    channelData["teamsChannelId"] = System.Configuration.ConfigurationManager.AppSettings["ChannelId"];
    IMessageActivity newMessage = Activity.CreateMessageActivity();
    newMessage.Type = ActivityTypes.Message;
    newMessage.Text = "Hello channel.";
    ConversationParameters conversationParams = new ConversationParameters(
        isGroup: true,
        bot: null,
        members: null,
        topicName: "Test Conversation",
        activity: (Activity)newMessage,
        channelData: channelData);
    var result = await connector.Conversations.CreateConversationAsync(conversationParams);
}

This code gets the service URL and Channel ID from AppSettings; as far as I can tell, the channel ID never changes for a given Teams channel. However, when I make a POST call to (bot URL)/api/WebhookAPI, no message gets posted and I get this error message in response:

{
    "message": "An error has occurred.",
    "exceptionMessage": "Authorization for Microsoft App ID [ID omitted] failed with status code Unauthorized and reason phrase 'Unauthorized'",
    "exceptionType": "System.UnauthorizedAccessException",
    "stackTrace": "   at Microsoft.Bot.Connector.JwtTokenRefresher.<SendAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)\r\n   at Microsoft.Bot.Connector.Conversations.<CreateConversationWithHttpMessagesAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Bot.Connector.ConversationsExtensions.<CreateConversationAsync>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at WebhookTestBot.Controllers.WebhookAPIController.<CreateChannelConversation>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at WebhookTestBot.Controllers.WebhookAPIController.<RespondToWebhook>d__1.MoveNext()",
    "innerException": {
    "message": "An error has occurred.",
    "exceptionMessage": "Response status code does not indicate success: 401 (Unauthorized).",
    "exceptionType": "System.Net.Http.HttpRequestException",
    "stackTrace": "   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()\r\n   at Microsoft.Bot.Connector.JwtTokenRefresher.<SendAsync>d__2.MoveNext()"
}

However, if I @-mention the bot in the channel first, the POST call returns 200 and the bot posts in the channel. Is there a way I can configure my bot to be able to post in the channel without being mentioned?

3

3 Answers

4
votes

Got it working, thanks to this answer. Adding the following code to CreateChannelConversation() before the call to CreateConversationAsync() worked:

MicrosoftAppCredentials.TrustServiceUrl(ConfigurationManager.AppSettings["serviceUrl"], DateTime.MaxValue);

0
votes

So you are hardcoding both the serviceUrl and the ChannelID? Does the channel Id match what is being received by the bot when you @mention it? It should look something like this: "19:[email protected]" Also note: the teamsChannelId is being deprecated in the future, so you should should instead change to channelData.channel.id. I will update the sample code on MSDN.

Regardless, your code should work assuming the hardcoded values match for the channel you are in, and works in my test case.

You say you @mention the bot first and it works. Can you explain more on your test case?

0
votes

Try adding credentials to the ConnectorClient constructor:

string appId = ConfigurationManager.AppSettings["MicrosoftAppId"];
string appPassword = ConfigurationManager.AppSettings["MicrosoftAppPassword"];
var appCredentials = new MicrosoftAppCredentials(appId, appPassword);
var connector = new ConnectorClient(new Uri(ConfigurationManager.AppSettings["serviceUrl"]), appCredentials );