clientSecret не может иметь значение NULL при отправке проактивного сообщения разговора в Microsoft Teams - PullRequest
1 голос
/ 22 января 2020

Я отправлю уведомление проактивное сообщение когда что-то изменится ботом, связанным с 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, у меня нет проблем с ним.

1 Ответ

3 голосов
/ 22 января 2020

Итак, здесь есть несколько вещей, которые следует учитывать. Прежде всего, сохранение этого в памяти является проблемой, если ваше приложение по какой-либо причине перезагружается - вы, возможно, захотите хранить его более устойчиво (например, в базе данных). Кроме того, я бы посоветовал прочесть мой пост в блоге (новый движок блога, так что он сейчас немного редок) на Как на самом деле работают вызовы ботов , так как это поможет объяснить фрагменты, которые вы в данный момент упускаете.

По сути, если вы не отвечаете непосредственно на существующее сообщение и хотите отправить сообщение на еще позже от вашего бота, то это называется Активный обмен сообщениями ", и для этого вам нужно больше, чем просто ссылка на разговор, вам также понадобится еще немного информации. Я описал больше об этом со ссылками и примером кода, на Программно отправив сообщение боту в Microsoft Teams .

Надеюсь, что поможет

...