Я использую 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.

Кроме того, я отправляю исключение в виде сообщения об активности клиенту (эмулятору платформы ботов), которое показано ниже.
Извините, похоже, что-то пошло не так.Исключение: 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
.

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

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;
});
}
Любая помощь с этим, пожалуйста?