Указанный ключ 'диалогов' не присутствовал в словаре при использовании ContinueDialogAsync - PullRequest
0 голосов
/ 15 февраля 2019

Я использую Bot Framework SDK v-4.Я создал пару диалогов, унаследованных от ComponentDialog, и переопределил методы: BeginDialogAsync и ContinueDialogAsync.Ниже приведена реализация IBot.

public class Bot : IBot
{
    private readonly BotAccessors _accessors;
    private readonly ILogger _logger;

    private DialogSet _dialogs = null;
    private string _botName = string.Empty;
    private IConfiguration _configuration = null;
    private UserDetail _userDetail = null;
    private ConversationData _conversationData = null;
    private IStatePropertyAccessor<TurnState> _turnStateAccessor = null;

    /// <summary>
    /// Initializes a new instance of the class.
    /// </summary>                        
    public Bot(BotAccessors accessors, ILoggerFactory loggerFactory, IConfiguration configuration)
    {
        _accessors = accessors ?? throw new System.ArgumentNullException(nameof(accessors));
        if (loggerFactory == null)
        {
            throw new System.ArgumentNullException(nameof(loggerFactory));
        }

        _configuration = configuration;
        _dialogs = new DialogSet(accessors.ConversationState.CreateProperty<DialogState>(nameof(DialogState)));
        _turnStateAccessor = accessors.TurnStateAccessor;
        _dialogs.Add(new GreetingDialog(_turnStateAccessor, loggerFactory, configuration));
        _dialogs.Add(new QnADialog(_turnStateAccessor, loggerFactory, configuration));
        _botName = configuration["BotName"];
        _logger = loggerFactory.CreateLogger<Bot>();
        _logger.LogTrace("Bot turn start.");
    }

    public override Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
    {
        _turnState = _turnStateAccessor.GetAsync(outerDc.Context).Result;
        outerDc.ContinueDialogAsync();
        return base.BeginDialogAsync(outerDc, options, cancellationToken);
    }

    public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
    {
        _turnState = _turnStateAccessor.GetAsync(outerDc.Context).Result;

        //some code
        _turnStateAccessor.SetAsync(outerDc.Context, _turnState).ConfigureAwait(false);
        return base.ContinueDialogAsync(outerDc, cancellationToken);
    }

}

. Я вызываю диалог из OnTurnAsync метода бота следующим образом: await dialogContext.BeginDialogAsync(nameof(GreetingDialog)).ConfigureAwait(false);.Он достигает метода BeginDialogAsync моего диалога и затем продолжает ContinueDialogAsync.Однако он работает нормально, при возврате (используя base.ContinueDialogAsync(outerDc, cancellationToken);) из метода я получаю исключение, которое я зафиксировал в инструменте диагностики Visual Studio.

enter image description here

Кроме того, я отправляю исключение в виде сообщения об активности клиенту (эмулятору платформы ботов), которое показано ниже.

Извините, похоже, что-то пошло не так.Исключение: System.ArgumentNullException: значение не может быть нулевым.Имя параметра: dialogId в Microsoft.Bot.Builder.Dialogs.DialogContext.BeginDialogAsync (Строка dialogId, Параметры объекта, CancellationToken cancellationToken) в D: \ a \ 1 \ s \ library \ Microsoft.Bot.Builder.Dialogs \ DialogContext.cs:строка 84 в Microsoft.Bot.Builder.Dialogs.ComponentDialog.BeginDialogAsync (DialogContext outerDc, Параметры объекта, CancellationToken cancellationToken) в D: \ a \ 1 \ s \ library \ Microsoft.Bot.Builder.Dialogs \ ComponentDialog.cs: строка 59в Microsoft.Bot.Builder.Dialogs.DialogContext.BeginDialogAsync (String dialogId, Параметры объекта, CancellationToken cancellationToken) в D: \ a \ 1 \ s \ library \ Microsoft.Bot.Builder.Dialogs \ DialogContext.cs: строка 84 в Chatbot.Bot.OnTurnAsync (ITurnContext turnContext, CancellationToken cancellationToken) в C: \ GIS \ ChatbotNew \ Chatbot \ Chatbot \ Bot.cs: строка 120 в Microsoft.Bot.Builder.MiddlewareSet.ReceiveActivityWithStatusAsync (обратный вызов обратной связи обратного вызова)D: \ а \ 1 \ S \ библиотеки \ Microsoft.Bot.Builder \ MiddlewareSet.cs: строка 55 в Microsoft.Bot.Builder.BotAdapter.RunPipelineAsync (ITurnContext turnContext, обратный вызов BotCallbackHandler, CancellationToken cancellationToken) в D: \ a \ 1 \ s \ library \ Microsoft.Bot.Builder \BotAdapter.cs: строка 167

Update-1

Основываясь на ответе Дрю, я удалил outerDc.ContinueDialogAsync();, но я получаю некоторую ошибку (показано ниже) во время шагачерез функцию return base.BeginDialogAsync(outerDc, options, cancellationToken); in BeginDialogAsync.

enter image description here

Кроме того, при переходе через функцию OnTurnAsync при попытке получить сообщение об ошибкеBotState, как показано ниже.

enter image description here

TurnState Реализация:

public class TurnState
{
    public int TurnCount { get; set; } = 0;
    public string BotType { get; set; } = string.Empty;
    public string ConversationLanguage { get; set; } = string.Empty;
    //other properties...
}

Аналогичная ошибка при попытке создатьDialogContext также.

ConfigureServices в Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddBot<Bot>(options =>
   {
       var secretKey = Configuration.GetSection("botFileSecret")?.Value;

        // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
        var botConfig = BotConfiguration.Load(@".\Chatbot.bot", secretKey);
       services.AddSingleton(sp => botConfig);

        // Retrieve current endpoint.
        var service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
       if (!(service is EndpointService endpointService))
       {
           throw new InvalidOperationException($"The .bot file does not contain a development endpoint.");
       }

       //options.CredentialProvider = new SimpleCredentialProvider(Configuration[MicrosoftAppCredentials.MicrosoftAppIdKey], Configuration[MicrosoftAppCredentials.MicrosoftAppPasswordKey]);
       options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);


       // Creates a logger for the application
       ILogger logger = _loggerFactory.CreateLogger<Bot>();

        // Catches any errors that occur during a conversation turn and logs them.
        options.OnTurnError = async (context, exception) =>
       {
           await context.SendActivityAsync("Sorry, it looks like something went wrong. Exception: " + exception);
       };

       // The Memory Storage used here is for local bot debugging only. When the bot
       // is restarted, everything stored in memory will be gone.
       IStorage dataStore = new MemoryStorage();

       var conversationState = new ConversationState(dataStore);

       options.State.Add(conversationState);

   });

    // Create and register state accesssors.
    // Acessors created here are passed into the IBot-derived class on every turn.
    services.AddSingleton<BotAccessors>(sp =>
    {
        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
        if (options == null)
        {
            throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors");
        }

        var conversationState = options.State.OfType<ConversationState>().FirstOrDefault();
        if (conversationState == null)
        {
            throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
        }

        // Create the custom state accessor.
        // State accessors enable other components to read and write individual properties of state.
        var accessors = new BotAccessors(conversationState)
        {
            TurnStateAccessor = conversationState.CreateProperty<TurnState>(BotAccessors.TurnStateName),
        };

        return accessors;
    });
}

Любая помощь с этим, пожалуйста?

1 Ответ

0 голосов
/ 17 февраля 2019

Я пытаюсь обернуть голову вокруг того, что вы ожидаете здесь:

public override Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
    _turnState = _turnStateAccessor.GetAsync(outerDc.Context).Result;
    outerDc.ContinueDialogAsync();
    return base.BeginDialogAsync(outerDc, options, cancellationToken);
}

В частности, почему вы звоните outerDc.ContinueDialogAsync() здесь?Это в основном связывает стек диалога в узел.Если вы удалили эту строку, все остальное, что вы показываете здесь, должно работать отлично.

Если вы обновите свой вопрос с более подробной информацией о том, что именно вы пытались сделать, позвонив, я с радостью обновлю свой ответ, чтобы попытаться инаправит вас на правильный путь для достижения чего бы то ни было.

...