Nachrichten, die zwischen Benutzer und Bot ausgetauscht werden, können Medienanlagen enthalten, z.B. Bilder, Videos, Audio und Dateien. Das Bot Framework SDK unterstützt die Aufgabe zum Senden von umfassenden Nachrichten an den Benutzer. Um den Typ der umfassenden Nachrichten zu ermitteln, die von einem Kanal (Facebook, Slack usw.) unterstützt werden, können Sie in der Dokumentation zum jeweiligen Kanal nach Informationen zu Einschränkungen suchen.
Hinweis
Die JavaScript-, C#- und Python-SDKs für Bot Framework werden weiterhin unterstützt, das Java-SDK wird jedoch eingestellt und der langfristige Support endet im November 2023.
Bestehende Bots, die mit dem Java SDK erstellt wurden, werden weiterhin funktionieren.
Der gesamte in diesem Abschnitt gezeigte Quellcode basiert auf dem Beispiel der Handling Attachments (Behandeln von Anlagen).
Die Attachments-Eigenschaft des Activity-Objekts enthält ein Array von Attachment-Objekten, die die an die Nachricht angehängten Medienanlagen und Rich Cards darstellen. Um einer Nachricht eine Medienanlage hinzuzufügen, erstellen Sie ein Attachment-Objekt für die Aktivität reply, und legen Sie die Eigenschaften ContentType, ContentUrl und Name fest.
Definieren Sie den Text, und richten Sie dann die Anlagen ein, um die Antwortnachricht zu erstellen. Die Zuweisung der Anlagen zur Antwort ist für jeden Anlagentyp identisch, aber die verschiedenen Anlagen werden unterschiedlich eingerichtet und definiert. Dies ist in den folgenden Codeausschnitten zu sehen. Mit diesem Code wird die Antwort für eine Inline-Anlage eingerichtet:
Bots/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
Als Nächstes sehen wir uns die Arten von Anlagen an. Die erste Anlage ist eine Inline-Anlage:
Bots/AttachmentsBot.cs
{
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var imageData = Convert.ToBase64String(File.ReadAllBytes(imagePath));
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = $"data:image/png;base64,{imageData}",
};
}
Die nächste Möglichkeit ist eine hochgeladene Anlage:
Bots/AttachmentsBot.cs
{
if (string.IsNullOrWhiteSpace(serviceUrl))
{
throw new ArgumentNullException(nameof(serviceUrl));
}
if (string.IsNullOrWhiteSpace(conversationId))
{
throw new ArgumentNullException(nameof(conversationId));
}
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var connector = turnContext.TurnState.Get<IConnectorClient>() as ConnectorClient;
var attachments = new Attachments(connector);
var response = await attachments.Client.Conversations.UploadAttachmentAsync(
conversationId,
new AttachmentData
{
Name = @"Resources\architecture-resize.png",
OriginalBase64 = File.ReadAllBytes(imagePath),
Type = "image/png",
},
cancellationToken);
var attachmentUri = attachments.GetAttachmentUri(response.Id);
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = attachmentUri,
};
}
Die letzte Anlage ist eine Internetanlage:
Bots/AttachmentsBot.cs
{
// ContentUrl must be HTTPS.
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = "https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
};
}
}
Definieren Sie den Text, und richten Sie dann die Anlagen ein, um die Antwortnachricht zu erstellen. Die Zuweisung der Anlagen zur Antwort ist für jeden Anlagentyp identisch, aber die verschiedenen Anlagen werden unterschiedlich eingerichtet und definiert. Dies ist in den folgenden Codeausschnitten zu sehen. Mit diesem Code wird die Antwort für eine Inline-Anlage eingerichtet:
bots/attachmentsBot.js
*/
const firstChar = turnContext.activity.text[0];
if (firstChar === '1') {
Um einen einzelnen Inhalt, z. B. ein Bild oder ein Video, an den Benutzer zu senden, können Sie Medien auf unterschiedliche Arten senden. Die erste Möglichkeit ist eine Inline-Anlage:
Die letzte Möglichkeit ist eine Internetanlage in einer URL:
bots/attachmentsBot.js
* Returns an attachment to be sent to the user from a HTTPS URL.
*/
getInternetAttachment() {
// NOTE: The contentUrl must be HTTPS.
return {
name: 'architecture-resize.png',
contentType: 'image/png',
contentUrl: 'https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png'
Der in diesem Abschnitt gezeigte Quellcode basiert auf dem Beispiel der Handling Attachments (Behandeln von Anlagen).
Die getAttachments()-Methode des Activity-Objekts enthält ein Array von Attachment-Objekten, die die an die Nachricht angehängten Medienanlagen und Rich Cards darstellen. Um einer Nachricht eine Medienanlage hinzuzufügen, erstellen Sie ein Attachment-Objekt für die Aktivität reply, und legen Sie die Eigenschaften ContentType, ContentUrl und Name fest.
Definieren Sie den Text, und richten Sie dann die Anlagen ein, um die Antwortnachricht zu erstellen. Die Zuweisung der Anlagen zur Antwort ist für jeden Anlagentyp identisch, aber die verschiedenen Anlagen werden unterschiedlich eingerichtet und definiert. Dies ist in den folgenden Codeausschnitten zu sehen. Mit diesem Code wird die Antwort für eine Inline-Anlage eingerichtet:
AttachmentsBot.java
result = getInlineAttachment()
.thenApply(attachment -> {
Activity reply = MessageFactory.text("This is an inline attachment.");
reply.setAttachment(attachment);
return reply;
});
Als Nächstes sehen wir uns die Arten von Anlagen an. Die erste Anlage ist eine Inline-Anlage:
AttachmentsBot.java
// Creates an inline attachment sent from the bot to the user using a base64 string.
// Using a base64 string to send an attachment will not work on all channels.
// Additionally, some channels will only allow certain file types to be sent this way.
// For example a .png file may work but a .pdf file may not on some channels.
// Please consult the channel documentation for specifics.
private CompletableFuture<Attachment> getInlineAttachment() {
return getEncodedFileData("architecture-resize.png")
.thenApply(encodedFileData -> {
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("data:image/png;base64," + encodedFileData);
return attachment;
});
}
Die nächste Möglichkeit ist eine hochgeladene Anlage:
// Creates an Attachment to be sent from the bot to the user from a HTTP URL.
private static Attachment getInternetAttachment() {
// ContentUrl must be HTTPS.
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png");
return attachment;
}
Definieren Sie den Text, und richten Sie dann die Anlagen ein, um die Antwortnachricht zu erstellen. Die Zuweisung der Anlagen zur Antwort ist für jeden Anlagentyp identisch, aber die verschiedenen Anlagen werden unterschiedlich eingerichtet und definiert. Dies ist in den folgenden Codeausschnitten zu sehen.
Mit diesem Code wird die Antwort für eine Inline-Anlage eingerichtet:
bots/attachments_bot.py
reply.text = "This is an inline attachment."
reply.attachments = [self._get_inline_attachment()]
Um einen einzelnen Inhalt, z. B. ein Bild oder ein Video, an den Benutzer zu senden, können Sie Medien auf unterschiedliche Arten senden. Die erste Möglichkeit ist eine Inline-Anlage:
bots/attachments_bot.py
def _get_inline_attachment(self) -> Attachment:
"""
Creates an inline attachment sent from the bot to the user using a base64 string.
Using a base64 string to send an attachment will not work on all channels.
Additionally, some channels will only allow certain file types to be sent this way.
For example a .png file may work but a .pdf file may not on some channels.
Please consult the channel documentation for specifics.
:return: Attachment
"""
file_path = os.path.join(os.getcwd(), "resources/architecture-resize.png")
with open(file_path, "rb") as in_file:
base64_image = base64.b64encode(in_file.read()).decode()
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=f"data:image/png;base64,{base64_image}",
)
Die nächste Möglichkeit ist eine hochgeladene Anlage:
bots/attachments_bot.py
async def _get_upload_attachment(self, turn_context: TurnContext) -> Attachment:
"""
Creates an "Attachment" to be sent from the bot to the user from an uploaded file.
:param turn_context:
:return: Attachment
"""
with open(
os.path.join(os.getcwd(), "resources/architecture-resize.png"), "rb"
) as in_file:
image_data = in_file.read()
connector = await turn_context.adapter.create_connector_client(
turn_context.activity.service_url
)
conversation_id = turn_context.activity.conversation.id
response = await connector.conversations.upload_attachment(
conversation_id,
AttachmentData(
name="architecture-resize.png",
original_base64=image_data,
type="image/png",
),
)
base_uri: str = connector.config.base_url
attachment_uri = (
base_uri
+ ("" if base_uri.endswith("/") else "/")
+ f"v3/attachments/{response.id}/views/original"
)
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=attachment_uri,
)
Die letzte Möglichkeit ist eine Internetanlage in einer URL:
bots/attachments_bot.py
def _get_internet_attachment(self) -> Attachment:
"""
Creates an Attachment to be sent from the bot to the user from a HTTP URL.
:return: Attachment
"""
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url="https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
)
Wenn eine Anlage ein Bild, eine Audiodatei oder ein Video ist, übermittelt der Connector Anlagedaten an den Kanal so, dass der Kanal diese Anlage in der Unterhaltung rendert. Wenn es sich bei der Anlage um eine Datei handelt, wird die Datei-URL als Link in der Unterhaltung gerendert.
Senden einer Hero-Karte
Neben einfachen Bild- oder Videoanlagen können Sie auch eine Hero-Karte anhängen, mit der Sie Bilder und Schaltflächen in einem Objekt kombinieren und an Benutzer senden können. Markdown wird für die meisten Textfelder unterstützt, die Unterstützung hängt jedoch ggf. vom jeweiligen Kanal ab.
private static async Task DisplayOptionsAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
// Create a HeroCard with options for the user to interact with the bot.
var card = new HeroCard
{
Text = "You can upload an image or select one of the following choices",
Buttons = new List<CardAction>
{
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
new CardAction(ActionTypes.ImBack, title: "1. Inline Attachment", value: "1"),
new CardAction(ActionTypes.ImBack, title: "2. Internet Attachment", value: "2"),
new CardAction(ActionTypes.ImBack, title: "3. Uploaded Attachment", value: "3"),
},
};
var reply = MessageFactory.Attachment(card.ToAttachment());
await turnContext.SendActivityAsync(reply, cancellationToken);
Um eine Nachricht mit einer Hero-Karte und einer Schaltfläche zu verfassen, können Sie an eine Nachricht ein HeroCard-Objekt anfügen.
* @param {Object} turnContext
*/
async displayOptions(turnContext) {
const reply = { type: ActivityTypes.Message };
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
const buttons = [
{ type: ActionTypes.ImBack, title: '1. Inline Attachment', value: '1' },
{ type: ActionTypes.ImBack, title: '2. Internet Attachment', value: '2' },
{ type: ActionTypes.ImBack, title: '3. Uploaded Attachment', value: '3' }
];
const card = CardFactory.heroCard('', undefined,
buttons, { text: 'You can upload an image or select one of the following choices.' });
reply.attachments = [card];
Um eine Nachricht mit einer Hero-Karte und einer Schaltfläche zu verfassen, können Sie an eine Nachricht ein HeroCard-Objekt anfügen.
private static CompletableFuture<Void> displayOptions(TurnContext turnContext) {
// Create a HeroCard with options for the user to interact with the bot.
HeroCard card = new HeroCard();
card.setText("You can upload an image or select one of the following choices");
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
card.setButtons(
new CardAction(ActionTypes.IM_BACK, "1. Inline Attachment", "1"),
new CardAction(ActionTypes.IM_BACK, "2. Internet Attachment", "2"),
new CardAction(ActionTypes.IM_BACK, "3. Uploaded Attachment", "3")
);
Activity reply = MessageFactory.attachment(card.toAttachment());
return turnContext.sendActivity(reply).thenApply(resourceResponse -> null);
}
Um eine Nachricht mit einer Hero-Karte und einer Schaltfläche zu verfassen, können Sie an eine Nachricht ein HeroCard-Objekt anfügen.
async def _display_options(self, turn_context: TurnContext):
"""
Create a HeroCard with options for the user to interact with the bot.
:param turn_context:
:return:
"""
# Note that some channels require different values to be used in order to get buttons to display text.
# In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
# need to provide a value for other parameters like 'text' or 'displayText'.
card = HeroCard(
text="You can upload an image or select one of the following choices",
buttons=[
CardAction(
type=ActionTypes.im_back, title="1. Inline Attachment", value="1"
),
CardAction(
type=ActionTypes.im_back, title="2. Internet Attachment", value="2"
),
CardAction(
type=ActionTypes.im_back, title="3. Uploaded Attachment", value="3"
),
],
)
Verarbeiten von Ereignissen auf Rich Cards
Zum Verarbeiten von Ereignissen in Rich Cards verwenden Sie Objekte vom Typ Kartenaktion, um festzulegen, was passieren soll, wenn der Benutzer auf eine Schaltfläche klickt oder auf einen Abschnitt der Rich Card tippt. Jede Kartenaktion hat eine Typ- und Wert-Eigenschaft.
Weisen Sie für die korrekte Funktionsweise jedem anklickbaren Element auf einer Hero-Karte einen Aktionstyp zu. In der folgenden Tabelle werden die verfügbaren Aktionstypen aufgeführt und erläutert. Außerdem ist jeweils angegeben, was die zugeordnete Werteigenschaft enthalten muss.
Die messageBack-Kartenaktion hat eine allgemeinere Bedeutung als die anderen Kartenaktionen. Weitere Informationen zu den messageBack und anderen Kartenaktionstypen finden Sie im Abschnitt Kartenaktion des Aktivitätsschemas.
Typ
BESCHREIBUNG
Wert
call
Initiiert einen Telefonanruf.
Ziel für den Telefonanruf im folgenden Format: tel:123123123123.
downloadFile
Lädt eine Datei herunter.
Die URL der herunterzuladenden Bilds.
imBack
Sendet eine Nachricht an den Bot und veröffentlicht eine sichtbare Antwort im Chat.
Text der zu sendenden Nachricht.
messageBack
Stellt eine Textantwort dar, die über das Chatsystem gesendet wird.
Ein optionaler programmgesteuerter Wert, der in generierte Nachrichten eingeschlossen werden soll.
openUrl
Öffnet eine URL im integrierten Browser.
Die zu öffnende URL.
playAudio
Gibt Audio wieder.
Die URL des wiederzugebenden Audios.
playVideo
Gibt ein Video wieder.
Die URL des wiederzugebenden Videos.
postBack
Sendet eine Nachricht an den Bot und veröffentlicht ggf. keine sichtbare Antwort im Chat.
Text der zu sendenden Nachricht.
showImage
Zeigt ein Bild an.
Die URL des anzuzeigenden Bilds.
signin
Initiiert einen OAuth-Anmeldevorgang.
Die URL des zu initiierenden OAuth-Flusses.
Verwenden einer Hero-Karte mit verschiedenen Ereignistypen
Der folgende Code zeigt Beispiele für verschiedene Rich Card-Ereignisse.
Beispiele für alle verfügbaren Karten finden Sie im Abschnitt Karten verwenden.
Cards.cs
public static HeroCard GetHeroCard()
{
var heroCard = new HeroCard
{
Title = "BotFramework Hero Card",
Subtitle = "Microsoft Bot Framework",
Text = "Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.OpenUrl, "Get Started", value: "https://docs.microsoft.com/bot-framework") },
};
return heroCard;
}
Cards.cs
public static SigninCard GetSigninCard()
{
var signinCard = new SigninCard
{
Text = "BotFramework Sign-in Card",
Buttons = new List<CardAction> { new CardAction(ActionTypes.Signin, "Sign-in", value: "https://login.microsoftonline.com/") },
};
return signinCard;
}
Beispiele für alle verfügbaren Karten finden Sie im Abschnitt Karten verwenden.
createOAuthCard() {
return CardFactory.oauthCard(
'OAuth connection', // Replace with the name of your Azure AD connection
'Sign In',
'BotFramework OAuth Card'
);
}
Beispiele für alle verfügbaren Karten finden Sie im Abschnitt Karten verwenden.
Cards.java
public static HeroCard getHeroCard() {
HeroCard heroCard = new HeroCard();
heroCard.setTitle("BotFramework Hero Card");
heroCard.setSubtitle("Microsoft Bot Framework");
heroCard.setText("Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.");
heroCard.setImages(new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg"));
heroCard.setButtons(new CardAction(ActionTypes.OPEN_URL, "Get Started", "https://docs.microsoft.com/bot-framework"));
return heroCard;
}
Cards.java
public static SigninCard getSigninCard() {
SigninCard signinCard = new SigninCard();
signinCard.setText("BotFramework Sign-in Card");
signinCard.setButtons(new CardAction(ActionTypes.SIGNIN, "Sign-in", "https://login.microsoftonline.com/"));
return signinCard;
}
Beispiele für alle verfügbaren Karten finden Sie im Abschnitt Karten verwenden.
def create_oauth_card(self) -> Attachment:
card = OAuthCard(
text="BotFramework OAuth Card",
connection_name="OAuth connection", # Replace it with the name of your Azure AD connection.
buttons=[
CardAction(
type=ActionTypes.signin,
title="Sign in",
value="https://example.org/signin",
)
],
)
return CardFactory.oauth_card(card)
Senden adaptiver Karten
Sie können zwar die Nachrichten-Zuordnungsinstanz verwenden, um eine Nachricht zu erstellen, die eine Anlage (beliebiger Art) enthält, eine adaptive Karte ist jedoch ein bestimmter Anlagentyp. Nicht alle Kanäle unterstützen adaptive Karten, und einige Kanäle unterstützen adaptive Karten nur teilweise. Wenn Sie beispielsweise eine adaptive Karte in Facebook senden, funktionieren die Schaltflächen nicht, während die Texte und Bilder einwandfrei funktionieren. Die Nachrichten-Zuordnungsinstanz ist eine Helferklasse des Bot Framework SDKs, mit der die Erstellungsschritte für Sie automatisiert werden.
Adaptive Karten sind ein offenes Kartenaustauschformat, das es Entwicklern ermöglicht, UI-Inhalte auf gemeinsame und konsistente Weise auszutauschen. Allerdings unterstützen nicht alle Kanäle adaptive Karten.
Der Designer für adaptive Karten bietet eine umfassende, interaktive Entwurfszeitumgebung zum Erstellen von adaptiven Karten.
Hinweis
Sie sollten diese Funktion mit den Kanälen testen, die Ihr Bot verwenden wird, um festzustellen, ob diese Kanäle adaptive Karten unterstützen.
Nachrichten können auch mehrere Anlagen im Karusselllayout enthalten. Die Anlagen werden nebeneinander platziert und der Benutzer kann zwischen ihnen wechseln.
Der folgende Quellcode stammt aus dem Beispiel Karten verwenden.
Dialogs/MainDialog.cs
Erstellen Sie zunächst die Antwort, und definieren Sie dann die Anlagen als Liste.
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
var attachments = new List<Attachment>();
// Reply to the activity we received with an activity.
var reply = MessageFactory.Attachment(attachments);
Fügen Sie dann die Anlagen hinzu und legen Sie den Layouttyp auf Karussell fest.
Hier fügen wir sie einzeln hinzu, aber Sie können die Liste auch ändern, um die Karten wie gewünscht hinzuzufügen.
// Display a carousel of all the rich card types.
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment());
reply.Attachments.Add(Cards.GetAnimationCard().ToAttachment());
reply.Attachments.Add(Cards.GetAudioCard().ToAttachment());
reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
reply.Attachments.Add(Cards.GetOAuthCard().ToAttachment());
reply.Attachments.Add(Cards.GetReceiptCard().ToAttachment());
reply.Attachments.Add(Cards.GetSigninCard().ToAttachment());
reply.Attachments.Add(Cards.GetThumbnailCard().ToAttachment());
reply.Attachments.Add(Cards.GetVideoCard().ToAttachment());
Nachdem die Anlagen hinzugefügt wurden, können Sie die Antwort wie gewohnt senden.
// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
Der folgende Quellcode stammt aus dem Beispiel Karten verwenden.
dialogs/mainDialog.js
Fügen Sie die Anlagen hinzu und legen Sie den Layouttyp auf Karussell fest.
Nachdem die Anlagen hinzugefügt wurden, können Sie die Antwort wie gewohnt senden.
Der folgende Quellcode stammt aus dem Beispiel Karten verwenden.
MainDialog.java
Erstellen Sie zunächst die Antwort, und definieren Sie dann die Anlagen als Liste.
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
List<Attachment> attachments = new ArrayList<>();
// Reply to the activity we received with an activity.
Activity reply = MessageFactory.attachment(attachments);
Fügen Sie dann die Anlagen hinzu und legen Sie den Layouttyp auf Karussell fest.
Hier fügen wir sie einzeln hinzu, aber Sie können die Liste auch ändern, um die Karten wie gewünscht hinzuzufügen.
// Display a carousel of all the rich card types.
reply.setAttachmentLayout(AttachmentLayoutTypes.CAROUSEL);
reply.getAttachments().add(Cards.createAdaptiveCardAttachment());
reply.getAttachments().add(Cards.getAnimationCard().toAttachment());
reply.getAttachments().add(Cards.getAudioCard().toAttachment());
reply.getAttachments().add(Cards.getHeroCard().toAttachment());
reply.getAttachments().add(Cards.getOAuthCard().toAttachment());
reply.getAttachments().add(Cards.getReceiptCard().toAttachment());
reply.getAttachments().add(Cards.getSigninCard().toAttachment());
reply.getAttachments().add(Cards.getThumbnailCard().toAttachment());
reply.getAttachments().add(Cards.getVideoCard().toAttachment());
Nachdem die Anlagen hinzugefügt wurden, können Sie die Antwort wie gewohnt senden.
// Send the card(s) to the user as an attachment to the activity
return stepContext.getContext().sendActivity(reply)
Der hier gezeigte Quellcode basiert auf dem Beispiel unter Using cards (Verwenden von Karten).
dialogs/main_dialog.py
Erstellen Sie zunächst die Antwort, und definieren Sie dann die Anlagen als Liste.
reply = MessageFactory.list([])
Fügen Sie dann die Anlagen hinzu und legen Sie den Layouttyp auf Karussell fest.
Hier fügen wir sie einzeln hinzu, aber Sie können die Liste auch ändern, um die Karten wie gewünscht hinzuzufügen.
Nachdem die Anlagen hinzugefügt wurden, können Sie die Antwort wie gewohnt senden.
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
Codebeispiel für die Verarbeitung der Eingabe in adaptive Karten
Das folgende Beispiel zeigt eine Möglichkeit, Eingaben in adaptive Karten innerhalb einer Bot-Dialogklasse zu verwenden.
Es erweitert das Beispiel der Hero-Karten, indem es die im Textfeld vom antwortenden Client empfangenen Eingaben validiert.
Zunächst müssen Sie die Texteingabe- und Schaltflächenfunktionalität zur vorhandenen adaptiven Karte hinzufügen, indem Sie den folgenden Code direkt vor der letzten Klammer der Datei adaptiveCard.json im Ordner „resources“ hinzufügen:
Die ID des Texteingabefelds wird auf „Text“ festgelegt. Wenn der Benutzer OK auswählt, weist die von der adaptiven Karte generierte Nachricht eine Werteigenschaft auf, die eine Eigenschaft namens text enthält, die die Informationen enthält, die der Benutzer im Texteingabefeld der Karte eingegeben hat.
Unser Validierungssteuerelement verwendet Newtonsoft.json zum Konvertieren in ein JObject und anschließenden Erstellen einer abgeschnittenen Textzeichenfolge für den Vergleich. Fügen Sie also Folgendes hinzu:
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
zu MainDialog.cs, und installieren Sie das neueste stabile NuGet-Paket von Newtonsoft.Json.
Im Code des Validierungssteuerelement haben wir den Logikfluss den Codekommentaren hinzugefügt.
Diese ChoiceValidator-Methode wird in das Beispiel Karten verwenden direkt nach der geschlossenen Klammer nach „public“ zur Deklaration von MainDialog eingefügt:
private async Task ChoiceValidator(
PromptValidatorContext promptContext,
CancellationToken cancellationToken)
{
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text string.
var jobject = promptContext.Context.Activity.Value as JObject;
var jtoken = jobject?["text"];
var text = jtoken?.Value().Trim();
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.Recognized.Succeeded && text != null)
{
var choice = promptContext.Options.Choices.FirstOrDefault(
c => c.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase));
if (choice != null)
{
promptContext.Recognized.Value = new FoundChoice
{
Value = choice.Value,
};
return true;
}
}
return promptContext.Recognized.Succeeded;
}
Ändern Sie nun oben in der Deklaration von MainDialog Folgendes:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
in:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));
Dadurch wird Ihr Validierungssteuerelement so aufgerufen, dass es bei jeder Erstellung einer neuen ChoicePrompt nach Eingaben für die adaptive Karte sucht.
Öffnen Sie mainDialog.js und suchen Sie die Ausführungsmethode async run(turnContext, accessor). Diese Methode behandelt eingehende Aktivitäten.
Direkt nach dem Aufruf dialogSet.add(this); fügen Sie Folgendes hinzu:
// The following check looks for a non-existent text input
// plus Adaptive Card input in _activity.value.text
// If both conditions exist, the Activity Card text
// is copied into the text input field.
if(turnContext._activity.text == null
&& turnContext._activity.value.text != null) {
this.logger.log('replacing null text with Activity Card text input');
turnContext._activity.text = turnContext._activity.value.text;
}
Wenn diese Prüfung eine nicht vorhandene Texteingabe des Clients findet, wird geprüft, ob es eine von einer adaptiven Karte stammende Eingabe gibt.
Wenn eine Eingabe von der adaptiven Karte bei _activity.value.text vorhanden ist, wird diese in das normale Texteingabefeld kopiert.
Unser Validator verwendet das Serialisierungs-Hilfsprogramm von com.microsoft.bot.schema, um dieses zuerst in einen JsonNode zu konvertieren und dann eine getrimmte Textzeichenfolge für den Vergleich zu erstellen. Außerdem benötigen wir einige andere Importe, um dies abzuschließen. Fügen Sie daher Folgendes hinzu:
MainDialog.java.
Im Code des Validierungssteuerelement haben wir den Logikfluss den Codekommentaren hinzugefügt.
Dieser PromptValidator-Ausdruck wird in das Beispiel Karten verwenden direkt nach der geschlossenen Klammer nach „public“ zur Deklaration von MainDialog eingefügt:
PromptValidator<FoundChoice> validator = (promptContext) -> {
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text
// string.
JsonNode jsonNode = Serialization.getAs(promptContext.getContext().getActivity().getValue(), JsonNode.class);
JsonNode textNode = jsonNode != null ? jsonNode.get("text") : null;
String text = textNode != null ? textNode.textValue() : "";
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.getRecognized().getSucceeded() && text != null) {
Optional<Choice> choice = promptContext.getOptions()
.getChoices()
.stream()
.filter(c -> StringUtils.compareIgnoreCase(c.getValue(), text) == 0)
.findFirst();
if (choice.isPresent()) {
promptContext.getRecognized().setValue(new FoundChoice() {
{
setValue(choice.get().getValue());
}
});
return CompletableFuture.completedFuture(true);
}
}
return CompletableFuture.completedFuture(promptContext.getRecognized().getSucceeded());
};
Ändern Sie nun oben in der Deklaration von MainDialog Folgendes:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt"));
in:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt", validator, null));
Dadurch wird Ihr Validierungssteuerelement so aufgerufen, dass es bei jeder Erstellung einer neuen ChoicePrompt nach Eingaben für die adaptive Karte sucht.
Er erstellt eine Aktivität mit empfohlenen Aktionen und sendet sie an den Benutzer.
Diese choice_validator-Methode wird in das Beispiel Karten verwenden direkt nach der geschlossenen Klammer nach „public“ zur Deklaration von MainDialog eingefügt:
@staticmethod
async def choice_validator(prompt_context: PromptValidatorContext) -> bool:
if prompt_context.context.activity.value:
text = prompt_context.context.activity.value["text"].lower()
if not prompt_context.recognized.succeeded and text:
matching_choices = [choice for choice in prompt_context.options.choices if choice.value.lower() == text]
if matching_choices:
choice = matching_choices[0]
prompt_context.recognized.value = FoundChoice(
value=choice.value,
index=0,
score=1.0
)
return True
return prompt_context.recognized.succeeded
Ändern Sie nun oben in der Deklaration von MainDialog Folgendes:
Dadurch wird Ihr Validierungssteuerelement so aufgerufen, dass es bei jeder Erstellung einer neuen ChoicePrompt nach Eingaben für die adaptive Karte sucht.
Testen des Bots Karten verwenden
Führen Sie das Beispiel Karten verwenden lokal aus und öffnen Sie den Bot im Bot Framework Emulator.
Folgen Sie den Anweisungen im Bot, um einen Kartentyp anzuzeigen, z. B. eine adaptive Karte.