У меня есть чат Bot, разработанный для веб-канала с использованием MS Bot Framework SDK V4 на C #, в котором есть несколько диалоговых классов, каждый из которых выполняет определенные задачи. В главном корневом диалоге у меня есть набор параметров, отображаемых Вариант 1,2,3,4 ... 6. Теперь, когда я выбираю опцию 5, я перенаправляюсь в новый класс диалога, где
У меня есть адаптивная карта, которую я спроектировал с 3 наборами контейнеров, один принимает входной текст через текстовые поля, а второй контейнер имеет несколько флажков длябыть выбранным и третий контейнер содержит 2 кнопки отправки и отмены. Для этих кнопок я поставил данные как Cancel = 0 и 1 соответственно. В этом диалоге опций 5 я управляю на основе данных отмены-0 или 1, если это 1, я делаю диалог завершения и показываю опции отображения по умолчанию 1,2,3,4 ... 6. Теперь я нажал на кнопку «Отправить», введя правильные значения, и процесс был успешно завершен, в результате текущий диалог завершился, и снова отображается основной набор параметров.
Здесь я провел какое-то отрицательное тестированиегде я прокрутил вверх и нажал кнопку отмены, которая отображалась выше. В результате первая опция (опция 1), отображаемая в наборе опций от 1 до 6, была выбрана по умолчанию, и операции с опциями выполнялись автоматически, даже если я выбрал отмену, а не первую опцию. Но этого не происходит, когда я выбираю кнопку отправки, отображаемую в адаптивной карточке, после прокрутки вверх отображается запрос на повторную попытку, чтобы выбрать любую из следующих опций, где, например, когда я нажимаю кнопку «Отмена», она по умолчанию переходит к 1-й опции.
Ниже приведены данные, относящиеся к диалогу и адаптивной карте:
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "Request For Model/License",
"horizontalAlignment": "Center",
"color": "Accent",
"id": "RequestforModel/License",
"spacing": "None",
"wrap": true
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Requester Name* : ",
"id": "RequesterNameLabel",
"weight": "Bolder",
"wrap": true,
"spacing": "None"
},
{
"type": "Input.Text",
"placeholder": "Enter Requester Name",
"id": "RequesterName",
"spacing": "None"
},
{
"type": "TextBlock",
"text": "Requester Email* : ",
"id": "RequesterEmailLabel",
"weight": "Bolder",
"wrap": true,
"spacing": "Small"
},
{
"type": "Input.Text",
"placeholder": "Enter Requester Email",
"id": "RequesterEmail",
"style": "Email",
"spacing": "None"
},
{
"type": "TextBlock",
"text": "Customer Name* : ",
"id": "CustomerNameLabel",
"weight": "Bolder",
"wrap": true,
"spacing": "Small"
},
{
"type": "Input.Text",
"placeholder": "Enter Customer Name",
"id": "CustomerName",
"spacing": "None"
},
{
"type": "TextBlock",
"text": "Select Request Type : ",
"id": "RequestTypeText",
"horizontalAlignment": "Left",
"wrap": true,
"weight": "Bolder",
"size": "Medium",
"spacing": "Small"
},
{
"type": "Input.ChoiceSet",
"placeholder": "--Select--",
"choices": [
{
"title": "Both",
"value": "Both"
},
{
"title": "1",
"value": "1"
},
{
"title": "2",
"value": "2"
}
],
"id": "RequestType",
"value": "Both",
"spacing": "None"
}
],
"horizontalAlignment": "Left",
"style": "default",
"bleed": true,
"id": "Requesterdata"
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Select Asset* :",
"id": "Assetheader",
"horizontalAlignment": "Left",
"wrap": true,
"weight": "Bolder",
"size": "Medium",
"spacing": "Small"
},
{
"type": "Input.ChoiceSet",
"placeholder": "",
"choices": [
{
"title": "chekcbox1",
"value": "chekcbox1"
},
{
"title": "chekcbox2",
"value": "chekcbox2"
},
{
"title": "chekcbox3",
"value": "chekcbox3"
},
{
"title": "chekcbox4",
"value": "chekcbox4"
},
{
"title": "chekcbox5",
"value": "chekcbox5"
}
],
"isMultiSelect": true,
"id": "AssetsList",
"wrap": true,
"spacing": "None"
}
],
"id": "Assetdata",
"style": "default",
"horizontalAlignment": "Left",
"bleed": true
},
{
"type": "Container",
"items": [
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Cancel",
"id": "CanclBtn",
"style": "positive",
"data": {
"Cancel": 1
}
},
{
"type": "Action.Submit",
"title": "Submit",
"id": "SubmitBtn",
"style": "positive",
"data": {
"Cancel": 0
}
}
],
"id": "Action1",
"horizontalAlignment": "Center",
"spacing": "Small",
"separator": true
}
]
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0",
"id": "ModelLicenseRequestForm",
"lang": "Eng"
}
Код ниже основного корневого диалога:
AddStep(async (stepContext, cancellationToken) =>
{
return await stepContext.PromptAsync(
"choicePrompt",
new PromptOptions
{
Prompt = stepContext.Context.Activity.CreateReply("Based on the access privileges assigned to you by your admin, below are the options you can avail. Please click/choose any one from the following: "),
Choices = new[] { new Choice { Value = "option1" }, new Choice { Value = "option2" }, new Choice { Value = "option3" }, new Choice { Value = "option4" }, new Choice { Value = "option5" }, new Choice { Value = "option6" } }.ToList(),
RetryPrompt = stepContext.Context.Activity.CreateReply("Sorry, I did not understand that. Please choose any one from the options displayed below: "),
});
});
AddStep(async (stepContext, cancellationToken) =>
{
if (response == "option1")
{
doing something
}
if (response == "option2")
{
return await stepContext.BeginDialogAsync(option2.Id, cancellationToken: cancellationToken);
}
if (response == "option3")
{
return await stepContext.BeginDialogAsync(option3.Id, cancellationToken: cancellationToken);
}
if (response == "option4")
{
return await stepContext.BeginDialogAsync(option4.Id, cancellationToken: cancellationToken);
}
if (response == "option5")
{
return await stepContext.BeginDialogAsync(option5.Id, cancellationToken: cancellationToken);
}
if (response == "option6")
{
return await stepContext.BeginDialogAsync(option6.Id, cancellationToken: cancellationToken);
}
return await stepContext.NextAsync();
});
опция5 код класса диалога:
AddStep(async (stepContext, cancellationToken) =>
{
var cardAttachment = CreateAdaptiveCardAttachment("Adaptivecard.json");
var reply = stepContext.Context.Activity.CreateReply();
reply.Attachments = new List<Microsoft.Bot.Schema.Attachment>() { cardAttachment };
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
var opts = new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
// You can comment this out if you don't want to display any text. Still works.
}
};
// Display a Text Prompt and wait for input
return await stepContext.PromptAsync(nameof(TextPrompt), opts);
});
AddStep(async (stepContext, cancellationToken) =>
{
var res = stepContext.Result.ToString();
dynamic modelrequestdata = JsonConvert.DeserializeObject(res);
string canceloptionvalidaiton = modelrequestdata.Cancel;
if (canceloptionvalidaiton == "0")
{
// ...perform operation
return await stepContext.EndDialogAsync();
}
else
{
return await stepContext.EndDialogAsync();
}
});
Обратите внимание, я специально не предоставил весь код для простоты понимания и других целей.
Основная идея для меня, чтобы отменитьКнопка предназначена для отмены текущей операции, чтобы пользователь мог перейти к основным параметрам диалогового окна, выбрать любую другую задачу для выполнения
Запрос:
- Как включить кнопку отмены в адаптивной карте, еслимоя логика выше неверна?
- можем ли мы иметь кнопку отмены в адаптивной карте? или это неверное предположение, и у нас не может быть опции отмены?
Обновлено 8 ноября 2009 г.
Данное обновление предназначено для ясного и лучшего пониманиямой запрос:
1) При запуске BOT через веб-канал запускается главный корень диалога, который содержит все диалоги и все, что добавлено в стек:
Ниже находится основной коренькод класса диалога:
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Choices;
using Microsoft.Bot.Schema;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace EchoBot.Dialogs
{
public class MainRootDialog : ComponentDialog
{
public MainRootDialog(UserState userState)
: base("root")
{
_userStateAccessor = userState.CreateProperty<JObject>("result");
AddDialog(DisplayOptionsDialog.Instance);
AddDialog(Option1.Instance);
AddDialog(Option2.Instance);
AddDialog(Option3.Instance);
AddDialog(Option4.Instance);
AddDialog(Option5.Instance);
AddDialog(Option6.Instance);
AddDialog(new ChoicePrompt("choicePrompt"));
InitialDialogId = DisplayOptionsDialog.Id;
}
}
}
2) Так как в диалоговом окне отображается исходный диалог для пользователя, в результате отображается начальный диалог параметров:
Option1 Option2 Option3 Option4 Option5 Option6
Этого я добился с помощью следующего кода, который я написал в классе с именем DisplayOptionsDialog:
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Choices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace EchoBot.Dialogs
{
public class DisplayOptionsDialog : WaterfallDialog
{
public DisplayOptionsDialog(string dialogId, IEnumerable<WaterfallStep> steps = null)
: base(dialogId, steps)
{
AddStep(async (stepContext, cancellationToken) =>
{
return await stepContext.PromptAsync(
"choicePrompt",
new PromptOptions
{
Prompt = stepContext.Context.Activity.CreateReply("Below are the options you can avail. Please click/choose any one from the following: "),
Choices = new[] { new Choice { Value = "Option1" }, new Choice { Value = "Option2" }, new Choice { Value = "Option3" }, new Choice { Value = "Option4" }, new Choice { Value = "Option5" }, new Choice { Value = "Option6" }}.ToList(),
RetryPrompt = stepContext.Context.Activity.CreateReply("Sorry, I did not understand that. Please choose any one from the options displayed below: "),
});
});
AddStep(async (stepContext, cancellationToken) =>
{
var response = (stepContext.Result as FoundChoice)?.Value;
if (response == "Option1")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Otpion 1 selected")); //Here there is lot of actual data printing that i am doing but due //to some sensitive inoformation i have kept a simple statment that gets //displayed but in actual code it is just printing back or responding back few //statements which again printing only
}
if (response == "Option2")
{
return await stepContext.BeginDialogAsync(Option2.Id, cancellationToken: cancellationToken);
}
if (response == "Option3")
{
return await stepContext.BeginDialogAsync(Option3.Id, cancellationToken: cancellationToken);
}
if (response == "Option4")
{
return await stepContext.BeginDialogAsync(Option4.Id, cancellationToken: cancellationToken);
}
if (response == "Option5")
{
return await stepContext.BeginDialogAsync(Option5.Id, cancellationToken: cancellationToken);
}
if (response == "Option6")
{
return await stepContext.BeginDialogAsync(Option6.Id, cancellationToken: cancellationToken);
}
return await stepContext.NextAsync();
});
AddStep(async (stepContext, cancellationToken) =>
{
return await stepContext.ReplaceDialogAsync(Id);
});
}
public static new string Id => "DisplayOptionsDialog";
public static DisplayOptionsDialog Instance { get; } = new DisplayOptionsDialog(Id);
}
}
3) С тех пор, как пользователь выбрал Option5, я сразу перейду к коду класса диалога option5:
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace EchoBot.Dialogs
{
public class Option5Dialog : WaterfallDialog
{
public const string cards = @"./ModelAdaptivecard.json";
public Option5Dialog(string dialogId, IEnumerable<WaterfallStep> steps = null)
: base(dialogId, steps)
{
AddStep(async (stepContext, cancellationToken) =>
{
var cardAttachment = CreateAdaptiveCardAttachment(cards);
var reply = stepContext.Context.Activity.CreateReply();
reply.Attachments = new List<Microsoft.Bot.Schema.Attachment>() { cardAttachment };
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
var opts = new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
// You can comment this out if you don't want to display any text. Still works.
}
};
// Display a Text Prompt and wait for input
return await stepContext.PromptAsync(nameof(TextPrompt), opts);
});
AddStep(async (stepContext, cancellationToken) =>
{
var activityTextformat = stepContext.Context.Activity.TextFormat;
if (activityTextformat == "plain")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Sorry, i did not understand that please enter proper details in below displayed form and click on submit button for processing your request"));
return await stepContext.ReplaceDialogAsync(Id, cancellationToken: cancellationToken);
}
else
{
var res = stepContext.Result.ToString();
dynamic modelrequestdata = JsonConvert.DeserializeObject(res);
string canceloptionvalidaiton = modelrequestdata.Cancel;
if (canceloptionvalidaiton == "0")
{
string ServiceRequesterName = modelrequestdata.RequesterName;
string ServiceRequesterEmail = modelrequestdata.RequesterEmail;
string ServiceRequestCustomerName = modelrequestdata.CustomerName;
string ServiceRequestType = modelrequestdata.RequestType;
string ServiceRequestAssetNames = modelrequestdata.AssetsList;
//checking wehther data is provided or not
if (string.IsNullOrWhiteSpace(ServiceRequesterName) || string.IsNullOrWhiteSpace(ServiceRequesterEmail) || string.IsNullOrWhiteSpace(ServiceRequestCustomerName) || string.IsNullOrWhiteSpace(ServiceRequestAssetNames))
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Mandatory fields such as Requester name,Requester Email,Cusomter Name or Asset details are not selected are not provided"));
return await stepContext.ReplaceDialogAsync(Id, cancellationToken: cancellationToken);
}
else
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Data recorded successfully"));
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Thank You!.Looking forward to see you again."));
return await stepContext.EndDialogAsync();
}
}
else
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Looks like you have cancelled the Model/License request"));
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Thank You!.Looking forward to see you again."));
return await stepContext.EndDialogAsync();
}
}
});
}
public static new string Id => "Option5Dialog";
public static Option5Dialog Instance { get; } = new Option5Dialog(Id);
public static Microsoft.Bot.Schema.Attachment CreateAdaptiveCardAttachment(string filePath)
{
var adaptiveCardJson = File.ReadAllText(filePath);
var adaptiveCardAttachment = new Microsoft.Bot.Schema.Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(adaptiveCardJson),
};
return adaptiveCardAttachment;
}
}
}
Вот что произошло или наблюдалось во время этого процесса варианта 5 и других вещей как в положительном, так и в отрицательном тестировании:
Данные, предоставленные пользователем на адаптивной карточке, отображаются как часть Option5 и нажимаются на кнопку отправки. Пользователь получает идентификатор запроса сообщения и т. Д., Как показано в приведенном выше коде, в то же время диалоговое окно заканчивается и те же параметры по умолчаниюпараметров с 1 по 6 отображаются как часть класса диалога defaultDisplayoptions
Теперь пользователь снова прокручивает вверх и нажимает кнопку отправки, но, как мы видим, пользователь находится в диалоговом окне настроек по умолчанию, как в коде, так и в соответствии сотображаемые параметры
отображается пользователь: Извините, я не понял этого. Пожалуйста, выберите любой из вариантов, показанных ниже:
Опция1 Опция2 Опция3 Опция4 Опция5 Опция6
Это работает по мере необходимости и, как ожидается, здесь никаких проблем.
Это тот же самый случай, сколько раз я нажимал на кнопку «Отправить»
Теперь я поднялся и нажал кнопку «Отмена», на этот раз элемент управления перешел к Displayoptions-> Option1 и оператор, присутствующий в этом блоке, напечатан
Когда я отлажен, я замечаю, что stepcontext в диалоге displayoptions имеет текстовое значение или выбор, предварительно заполненный или предварительно выбранный как Option1 безЯ выбираю эту опцию, в результате она печатает операторы под ней.
Не уверен, как он это делает и почему он это делает. Так что я подумал, что могу включить кнопку отмены таким образом (как я это сделал) неправильно, может быть, есть другой способ, и я задал вопрос, как добиться функциональности кнопки отмены в адаптивной карте в этом посте.
Однако, если то, что я сделал, является правильным способом, скажите, пожалуйста, почему проблема заключается только в кнопке отмены, когда, когда управление переходит в диалоговое окно DiaplayOptions, вариант 1 каким-то образом выбирается заранее, где все работает нормально с кнопкой отправки(в этом случае никаких проблем вообще нет).
Не могли бы вы помочь мне в решении этой проблемы, учитывая мою обновленную информацию и запрос?