Я отправлю уведомление проактивное сообщение когда что-то изменится ботом, связанным с Microsoft Teams. Демо использует (для простоты) только конечную точку API на веб-сайте бота.
После того, как я начал беседу, я сохраняю ее в беседе со свойством MemoryVariables.ConversationReferences
(тип ConcurrentDictionary<string, ConversationReference>
) .
Когда я перехожу к конечной точке API, то вижу, что сообщения не приходит, однако я получил ответ 200. При поиске ошибки я добавил точку останова на отмеченной строке.
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter
{
public AdapterWithErrorHandler(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger : base(configuration, logger)
{
OnTurnError = async (turnContext, exception) =>
{
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // <-- breakpoint added here
};
}
}
Там я вижу следующее исключение:
System.ArgumentNullException
: Значение не может быть нулевым. Имя параметра: clientSecret
Вот трассировка стека:
at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential..ctor(String clientId, String clientSecret)
at Microsoft.Bot.Connector.Authentication.MicrosoftAppCredentials.<BuildAuthenticator>b__14_0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Bot.Connector.Authentication.AppCredentials.GetTokenAsync(Boolean forceRefresh)
at Microsoft.Bot.Connector.Authentication.AppCredentials.ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Bot.Connector.Conversations.ReplyToActivityWithHttpMessagesAsync(String conversationId, String activityId, Activity activity, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Bot.Connector.ConversationsExtensions.ReplyToActivityAsync(IConversations operations, String conversationId, String activityId, Activity activity, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.BotFrameworkAdapter.SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.TurnContext.<>c__DisplayClass22_0.<<SendActivitiesAsync>g__SendActivitiesThroughAdapter|1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Bot.Builder.TurnContext.SendActivityAsync(IActivity activity, CancellationToken cancellationToken)
at MyDemoBot.Bot.Controllers.NotifyController.BotCallback(ITurnContext turnContext, CancellationToken cancellationToken) in C:\MyDemoBot\Savaco.KBESAVAC.NotificationBot.Bot\Controllers\NotifyController.cs:line 59
at Microsoft.Bot.Builder.BotFrameworkAdapter.TenantIdWorkaroundForTeamsMiddleware.OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.MiddlewareSet.ReceiveActivityWithStatusAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.BotAdapter.RunPipelineAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)
Ниже вы видите мой NotifyController
, где исключение выдается на отмеченной строке.
[Route("api/notify")]
[ApiController]
public class NotifyController : ControllerBase
{
public async Task<IActionResult> Get()
{
MemoryVariables memoryVariables = MemoryVariables.GetInstance();
List<Task> taskList = new List<Task>();
ICollection<ConversationReference> conversationReferences = memoryVariables.ConversationReferences.Values;
foreach (ConversationReference conversationReference in conversationReferences)
{
taskList.Add(memoryVariables.BotAdapter.ContinueConversationAsync(
conversationReference.Bot.Id,
conversationReference,
BotCallback,
new CancellationToken()
));
}
await Task.WhenAll(taskList); // <-- exceptions throws on this line code
return GetContentResult(new { messagesSend = conversationReferences.Count }, HttpStatusCode.OK);
}
private ContentResult GetContentResult(object content, HttpStatusCode httpStatusCode)
{
return new ContentResult()
{
Content = JsonConvert.SerializeObject(content),
ContentType = "application/json",
StatusCode = (int)httpStatusCode
};
}
private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync(
MessageFactory.SuggestedActions(
new string[] { "Create A", "Create B" },
"Hi, you've received a notification. Choose an action from below to continue."
),
cancellationToken
);
}
}
Я что-то пропустил в своем коде или есть какие-то особенности для команд Microsoft, которые я пропустил? Используя localhost и эмулятор Bot Framework, у меня нет проблем с ним.