public async Task RegisterTeamRoster(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            var context = turnContext;
            // Fetch the members in the current conversation

            var connector = new ConnectorClient(new Uri(context.Activity.ServiceUrl), GetMSAppCredential());
            var members   = await connector.Conversations.GetConversationMembersAsync(context.Activity.Conversation.Id);

            TeamsChannelData channelData = turnContext.Activity.GetChannelData <TeamsChannelData>();

            if (channelData != null)
            {
                var teamId = channelData.Team.Id;
                var sb     = new StringBuilder();
                sb.Append("{");
                sb.Append("  \"teamId\": \"" + teamId + "\",");
                sb.Append("  \"members\": [");
                // Concatenate information about all members into a string


                foreach (var member in members)
                {
                    sb.Append($"{{\"id\": \"{member.Id}\", \"name\": \"{member.Name}\"}}");
                    sb.Append(",");
                }

                sb.Remove(sb.Length - 1, 1);
                sb.Append("]}");


                _logger.LogDebug("Calling Register Roster API >>>");
                _logger.LogDebug(sb.ToString());
                var result = await OpenHackAPIClient.SubmitRoster(sb);

                _logger.LogDebug("API Result >>>");
                _logger.LogDebug(result.ToString(Formatting.None));
            }
        }
        /// <summary>
        /// Every conversation turn for our Echo Bot will call this method.
        /// There are no dialogs used, since it's "single turn" processing, meaning a single
        /// request and response.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        /// <seealso cref="IMiddleware"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types

            /* if (turnContext.Activity.Type == ActivityTypes.Message)
             * {
             *   // Get the conversation state from the turn context.
             *   var state = await _accessors.CounterState.GetAsync(turnContext, () => new CounterState());
             *
             *   // Bump the turn count for this conversation.
             *   state.TurnCount++;
             *
             *   // Set the property using the accessor.
             *   await _accessors.CounterState.SetAsync(turnContext, state);
             *
             *   // Save the new turn count into the conversation state.
             *   await _accessors.ConversationState.SaveChangesAsync(turnContext);
             *
             *   // Echo back to the user whatever they typed.
             *   var responseMessage = $"Turn {state.TurnCount}: You sent '{turnContext.Activity.Text}'\n";
             *   await turnContext.SendActivityAsync(responseMessage);
             * }*/
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types

            /* if (turnContext.Activity.Type == ActivityTypes.Message)
             * {
             *   // Extract the text from the message activity the user sent.
             *   // Make this lowercase not accounting for culture in this case
             *   // so that there are fewer string variations which you will
             *   // have to account for in your bot.
             *   var text = turnContext.Activity.Text.ToLowerInvariant();
             *
             *   // Take the input from the user and create the appropriate response.
             *   var responseText = ProcessInput(text);
             *
             *   // Respond to the user.
             *   await turnContext.SendActivityAsync(responseText, cancellationToken: cancellationToken);
             *
             *   await SendSuggestedActionsAsync(turnContext, cancellationToken);
             * } */
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Run the DialogSet - let the framework identify the current state of the dialog from
                // the dialog stack and figure out what (if any) is the active dialog.
                var dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dialogContext.ContinueDialogAsync(cancellationToken);

                // If the DialogTurnStatus is Empty we should start a new dialog.
                if (results.Status == DialogTurnStatus.Empty)
                {
                    var Id = turnContext.Activity.From.AadObjectId;

                    var question = await OpenHackAPIClient.GetQuestion(Id);

                    //question.
                    var questionOptions = new List <Choice>();

                    foreach (var qo in question.questionOptions)
                    {
                        questionOptions.Add(new Choice
                        {
                            Value    = qo.text,
                            Synonyms = new List <string> {
                                qo.id.ToString()
                            }
                        });
                    }

                    var state = await _accessors.CounterState.GetAsync(turnContext, () => new QuestionState());

                    // Bump the turn count for this conversation.
                    state.CurrentQuestion = question;
                    // Set the property using the accessor.
                    await _accessors.CounterState.SetAsync(turnContext, state);

                    // Save the new turn count into the conversation state.
                    await _accessors.ConversationState.SaveChangesAsync(turnContext);

                    _logger.LogDebug("Questions>>" + JsonConvert.SerializeObject(question, Formatting.Indented));
                    // A prompt dialog can be started directly on the DialogContext. The prompt text is given in the PromptOptions.
                    await dialogContext.PromptAsync(
                        "choices",
                        new PromptOptions { Prompt = MessageFactory.Text(question.text), Choices = questionOptions },
                        cancellationToken);
                }

                // We had a dialog run (it was the prompt). Now it is Complete.
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    // Check for a result.
                    if (results.Result != null)
                    {
                        var Id    = turnContext.Activity.From.AadObjectId;
                        var state = await _accessors.CounterState.GetAsync(turnContext, () => new QuestionState());

                        var question = state.CurrentQuestion;

                        var choice = results.Result as FoundChoice;

                        var choice2 = question.questionOptions.Where(o => o.text == choice.Value).FirstOrDefault();

                        var answerResponse = await OpenHackAPIClient.SubmitAnswer(Id, question.id.ToString(), choice2.id.ToString());

                        _logger.LogDebug("Answer Response>>" + JsonConvert.SerializeObject(answerResponse, Formatting.Indented));
                        string answerStatus = answerResponse.correct ? "correct" : "incorrect";
                        // Finish by sending a message to the user. Next time ContinueAsync is called it will return DialogTurnStatus.Empty.
                        await turnContext.SendActivityAsync(MessageFactory.Text($"Thank you, your answer ({choice.Value})  was '{ answerStatus }'."));
                    }
                }
            }
            else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                var responseMessage = $"Conversation Update '{turnContext.Activity.Text}'\n";
                _logger.LogDebug(responseMessage);
                if (turnContext.Activity.MembersAdded != null)
                {
                    // Send a welcome message to the user and tell them what actions they may perform to use this bot
                    await SendWelcomeMessageAsync(turnContext, cancellationToken);


                    await RegisterTeamRoster(turnContext, cancellationToken);
                }
            }
            else if (turnContext.Activity.Type == ActivityTypes.InstallationUpdate)
            {
                var responseMessage = $"Installation Update '{turnContext.Activity.Text}'\n";

                _logger.LogDebug(responseMessage);
                //await turnContext.SendActivityAsync(responseMessage);

                await RegisterTeamRoster(turnContext, cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
            }

            // Save the new turn count into the conversation state.
            await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        }