как сохранить пользовательские данные из одного компонента диалога в другой, используя каркас бота с C # - PullRequest
0 голосов
/ 10 июля 2019

Я только начал разработку чат-бота на C #. Я хочу разработать диалог, который использует 4 компонента, поэтому остальные 3 основаны на одном, и все эти компоненты вызываются из основного класса. Мой класс userInfo выглядит следующим образом

public class UserInfo
{
    public WillkommenInfo Willkommen { get; set; }

    public BeschwerdeInfo Beschwerde { get; set; }

    public TerminInfo Termin { get; set; }

    public FrageInfo Frage { get; set; }
}

public class WillkommenInfo
{
    public string Name { get; set; }
}

public class TerminInfo
{
    public string Ansprechpartner { get; set; }

    public string Location { get; set; }

    public string Date { get; set; }
}

public class FrageInfo
{
    public string Question { get; set; }
}

Извлечение основного класса, с помощью которого вызываются все методы, выглядит следующим образом

public MainDialog(UserState userState)
        : base(nameof(MainDialog))
{
        _userState = userState;

        _userInfoAccessor=userState.CreateProperty<UserInfo("UserInfo");

        AddDialog(new WillkommenDialog());
        AddDialog(new TopLevelDialog());
        AddDialog(new BeschwerdeDialog());
        AddDialog(new TerminDialog());

        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new 
     WaterfallStep[]
        {
            InitialStepAsync,
            MenuStepAsync,
            HandleChoiceAsync,
            LoopBackAsync,
        }));

        InitialDialogId = nameof(WaterfallDialog);
    }

    private static async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        return await stepContext.BeginDialogAsync(nameof(WillkommenDialog), null, cancellationToken);
    }

    private  async Task<DialogTurnResult> MenuStepAsync(
    WaterfallStepContext step,
    CancellationToken cancellationToken = default(CancellationToken))
    {
        List<string> choice = new List<string> {  "Frage", "Terminanfrage", "Beschwerde", "Beenden" };
        await step.Context.SendActivityAsync(
        MessageFactory.SuggestedActions(choice, $"Wie kann ich Ihnen behilflich sein?"),
        cancellationToken: cancellationToken);
        return Dialog.EndOfTurn;

    }

    private async Task<DialogTurnResult> HandleChoiceAsync(
    WaterfallStepContext stepContext,
    CancellationToken cancellationToken = default(CancellationToken))
    {
        UserInfo userInfo = await _userInfoAccessor.GetAsync(stepContext.Context, null, cancellationToken);
       string choice = (stepContext.Result as string)?.Trim()?.ToLowerInvariant();

        switch (choice)
        {
            case "frage":
                return await stepContext.BeginDialogAsync(nameof(TopLevelDialog), userInfo.Willkommen, cancellationToken);
            case "terminanfrage":
                return await stepContext.BeginDialogAsync(nameof(TerminDialog), userInfo.Willkommen, cancellationToken);
            case "beschwerde":
                return await stepContext.BeginDialogAsync(nameof(BeschwerdeDialog), userInfo.Willkommen, cancellationToken);
            case "beenden":
                await stepContext.Context.SendActivityAsync($"Danke sehr für Ihre Teilnahme\n" +
                    $"Auf wiedersehen!");
                await stepContext.Context.SendActivityAsync($"Vielen Dank für Ihre Teilnahme. Ich hoffe ich konnte Ihnen behilflich sein. Auf Wiedersehen!");
                return await stepContext.EndDialogAsync(null, cancellationToken);

            default:
                await stepContext.Context.SendActivityAsync(
                     MessageFactory.Text($"Tut mir leid, ich verstehe diesen Befehl nicht. Bitte wählen Sie eine Option aus der Liste aus."), cancellationToken);
                return await stepContext.ReplaceDialogAsync(nameof(MainDialog), null, cancellationToken);
        }
    }

метод OnTurnAsync бота выглядит следующим образом

public override async Task OnTurnAsync(ITurnContext turnContext, 
CancellationToken cancellationToken = default(CancellationToken))
    {

        await base.OnTurnAsync(turnContext, cancellationToken);
        if (turnContext.Activity.Type is ActivityTypes.Message)
        {
            await UserState.LoadAsync(turnContext, false, cancellationToken);
            var userStateAccessors = UserState.CreateProperty<UserInfo>(nameof(UserInfo));
            var userInfo = await userStateAccessors.GetAsync(turnContext, () => new UserInfo());
            await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
    }

проблема в том, что я не могу сохранить имя пользователя, которое он вводит на первом шаге в диалоге WillkommenDialog, который должен быть основой для других 3 компонентов диалога. Компонент диалогового окна willkommen выглядит следующим образом

public WillkommenDialog()
    : base(nameof(WillkommenDialog))
    {
        AddDialog(new TextPrompt(NamePrompt, ValidateNameAsync));

        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {

            NameStepAsync,
            FinalStepAsync,

    }));

        InitialDialogId = nameof(WaterfallDialog);
    }

    private async Task<DialogTurnResult> NameStepAsync
        (WaterfallStepContext step,
         CancellationToken cancellationToken = default(CancellationToken))
    {
        step.Values[UserProfile] = new UserInfo();
        return await step.PromptAsync(
            NamePrompt,
            new PromptOptions
            {
                Prompt = MessageFactory.Text("Geben Sie bitte Ihren Namen 
ein."),
            },
            cancellationToken);
    }
    private async Task<DialogTurnResult> FinalStepAsync(
        WaterfallStepContext step,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        string name = step.Result as string;
        ((WillkommenInfo)step.Values[WillkommenKey]).Name = name;
        var reply = step.Context.Activity.CreateReply();
        var card = new HeroCard();
        card.Title = $"Willkommen **{name}**!";
        card.Subtitle = $"Erfahrung macht den Unterschied.";
        card.Images = new List<CardImage>() { new CardImage("https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-compositcontrol?view=azure-bot-service-4.0&tabs=csharp") };
        reply.Attachments = new List<Attachment>() { card.ToAttachment() };
        await step.Context.SendActivityAsync(reply, cancellationToken: cancellationToken);
        return await step.EndDialogAsync((WillkommenInfo)step.Values[WillkommenKey], cancellationToken);
    }

выдержка из компонента Termin, которую я хотел бы получить для имени пользователя перед запуском, выглядит следующим образом

public TerminDialog()
        : base(nameof(TerminDialog))
    {

        AddDialog(new TextPrompt("ansprechpartner", AnsprechpartnerValidateAsync));
        AddDialog(new ChoicePrompt("location"));
        AddDialog(new DateTimePrompt("reservationDate", DateValidatorAsync));

        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {
            AnsprechpartnerStepAsync,
            LocationStepAsync,
            ReservationDateStepAsync,
            FinalStepAsync,

    }));


        InitialDialogId = nameof(WaterfallDialog);
    }

    private static async Task<DialogTurnResult> AnsprechpartnerStepAsync(
        WaterfallStepContext step,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var userInfo = (UserInfo)step.Result;
        string greeting = $"Hallo **{userInfo.Willkommen}**";
        string prompt = $"{greeting}. Geben Sie bitte den Namen Ihres Ansprechpartners ein.";

        return await step.PromptAsync(
            "ansprechpartner",
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"{greeting} geben Sie bitte den Namen Ihres Ansprechpartners ein."),
                RetryPrompt = MessageFactory.Text($"{greeting} geben Sie bitte den Namen Ihres Ansprechpartners ein."),

            },
            cancellationToken);
    }

Может ли кто-нибудь помочь мне, рассказав, как получить 3 компонента (Frage, Termin и Beschwerde), чтобы получить все имена пользователей, которые они ввели в компонент диалога willkommen?

...