diff --git a/.github/workflows/build-complete-samples.yml b/.github/workflows/build-complete-samples.yml
index 9e357bec34..2357387e30 100644
--- a/.github/workflows/build-complete-samples.yml
+++ b/.github/workflows/build-complete-samples.yml
@@ -280,9 +280,9 @@ jobs:
name: 'bot-message-reaction'
version: '8.0.x'
- - project_path: 'samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActionsBot.csproj'
+ - project_path: 'samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActions.csproj'
name: 'bot-suggested-actions'
- version: '6.0.x'
+ version: '10.0.x'
- project_path: 'samples/bot-task-module/csharp/TeamsTaskModule.csproj'
name: 'bot-task-module'
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/.gitignore b/samples/bot-suggested-actions/csharp/M365Agent/.gitignore
new file mode 100644
index 0000000000..c5cae9258c
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/M365Agent/.gitignore
@@ -0,0 +1,10 @@
+# TeamsFx files
+build
+appPackage/build
+env/.env.*.user
+env/.env.local
+appsettings.Development.json
+.deployment
+
+# User-specific files
+*.user
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.atkproj b/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.atkproj
new file mode 100644
index 0000000000..124eb75046
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.atkproj
@@ -0,0 +1,9 @@
+
+
+
+ b069b3bd-f6bc-cc40-82ab-3fcc2ea50fdf
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.ttkproj b/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.ttkproj
deleted file mode 100644
index 5a6f0c5d4b..0000000000
--- a/samples/bot-suggested-actions/csharp/M365Agent/M365Agent.ttkproj
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- 45c5b04b-e16f-4eeb-b567-8de2a5fef1ed
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/aad.manifest.json b/samples/bot-suggested-actions/csharp/M365Agent/aad.manifest.json
index 6f1efa8862..030cd33b06 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/aad.manifest.json
+++ b/samples/bot-suggested-actions/csharp/M365Agent/aad.manifest.json
@@ -1,6 +1,6 @@
{
- "id": "${{AAD_APP_OBJECT_ID}}",
- "appId": "${{AAD_APP_CLIENT_ID}}",
+ "id": "${{BOT_OBJECT_ID}}",
+ "appId": "${{BOT_ID}}",
"name": "bot-suggested-actions-aad",
"accessTokenAcceptedVersion": 2,
"signInAudience": "AzureADMyOrg",
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/color.png b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/color.png
index b8cf81afbe..01aa37e347 100644
Binary files a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/color.png and b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/color.png differ
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/manifest.json b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/manifest.json
index 53d50f2176..267b1780ea 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/manifest.json
+++ b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/manifest.json
@@ -1,6 +1,6 @@
-{
- "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.21/MicrosoftTeams.schema.json",
- "manifestVersion": "1.21",
+{
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
+ "manifestVersion": "1.23",
"version": "1.0.0",
"id": "${{TEAMS_APP_ID}}",
"developer": {
@@ -26,13 +26,13 @@
"customEngineAgents": [
{
"type": "bot",
- "id": "${{AAD_APP_CLIENT_ID}}"
+ "id": "${{BOT_ID}}"
}
]
},
"bots": [
{
- "botId": "${{AAD_APP_CLIENT_ID}}",
+ "botId": "${{BOT_ID}}",
"scopes": [
"copilot",
"personal"
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/outline.png b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/outline.png
index 2c3bf6fa65..f7a4c86447 100644
Binary files a/samples/bot-suggested-actions/csharp/M365Agent/appPackage/outline.png and b/samples/bot-suggested-actions/csharp/M365Agent/appPackage/outline.png differ
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/env/.env.dev b/samples/bot-suggested-actions/csharp/M365Agent/env/.env.dev
new file mode 100644
index 0000000000..df4f9da508
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/M365Agent/env/.env.dev
@@ -0,0 +1,15 @@
+# This file includes environment variables that will be committed to git by default.
+
+# Built-in environment variables
+TEAMSFX_ENV=dev
+APP_NAME_SUFFIX=dev
+
+# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups.
+AZURE_SUBSCRIPTION_ID=
+AZURE_RESOURCE_GROUP_NAME=
+RESOURCE_SUFFIX=
+
+# Generated during provision, you can also add your own variables.
+BOT_ID=
+TEAMS_APP_ID=
+BOT_AZURE_APP_SERVICE_RESOURCE_ID=
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/env/.env.local b/samples/bot-suggested-actions/csharp/M365Agent/env/.env.local
index 76ee8a0ba6..5216a6cbb0 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/env/.env.local
+++ b/samples/bot-suggested-actions/csharp/M365Agent/env/.env.local
@@ -5,19 +5,11 @@ TEAMSFX_ENV=local
APP_NAME_SUFFIX=local
# Generated during provision, you can also add your own variables.
-BOT_ID=
+
TEAMS_APP_ID=
-RESOURCE_SUFFIX=
-AZURE_SUBSCRIPTION_ID=
-AZURE_RESOURCE_GROUP_NAME=
-AAD_APP_CLIENT_ID=
-AAD_APP_OBJECT_ID=
-AAD_APP_TENANT_ID=
-AAD_APP_OAUTH_AUTHORITY=
-AAD_APP_OAUTH_AUTHORITY_HOST=
TEAMS_APP_TENANT_ID=
-MICROSOFT_APP_TYPE=
-MICROSOFT_APP_TENANT_ID=
+BOT_ID=
+BOT_OBJECT_ID=
TEAMSFX_M365_USER_NAME=
BOT_ENDPOINT=
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.bicep b/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.bicep
index c3ce051b3d..658e412a21 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.bicep
+++ b/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.bicep
@@ -3,42 +3,84 @@
@description('Used to generate names for all resources in this file')
param resourceBaseName string
-@description('Required when create Azure Bot service')
-param botAadAppClientId string
-
-param botAppDomain string
+param webAppSKU string
@maxLength(42)
param botDisplayName string
-param botServiceName string = resourceBaseName
-param botServiceSku string = 'F0'
-param microsoftAppType string
-param microsoftAppTenantId string
+param serverfarmsName string = resourceBaseName
+param webAppName string = resourceBaseName
+param identityName string = resourceBaseName
+param location string = resourceGroup().location
-// Register your web service as a bot with the Bot Framework
-resource botService 'Microsoft.BotService/botServices@2021-03-01' = {
- kind: 'azurebot'
- location: 'global'
- name: botServiceName
- properties: {
- displayName: botDisplayName
- endpoint: 'https://${botAppDomain}/api/messages'
- msaAppId: botAadAppClientId
- msaAppType: microsoftAppType
- msaAppTenantId: microsoftAppType == 'SingleTenant' ? microsoftAppTenantId : ''
- }
+resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
+ location: location
+ name: identityName
+}
+
+// Compute resources for your Web App
+resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = {
+ kind: 'app'
+ location: location
+ name: serverfarmsName
sku: {
- name: botServiceSku
+ name: webAppSKU
}
}
-// Connect the bot service to Microsoft Teams
-resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
- parent: botService
- location: 'global'
- name: 'MsTeamsChannel'
+// Web App that hosts your bot
+resource webApp 'Microsoft.Web/sites@2021-02-01' = {
+ kind: 'app'
+ location: location
+ name: webAppName
properties: {
- channelName: 'MsTeamsChannel'
+ serverFarmId: serverfarm.id
+ httpsOnly: true
+ siteConfig: {
+ appSettings: [
+ {
+ name: 'WEBSITE_RUN_FROM_PACKAGE'
+ value: '1'
+ }
+ {
+ name: 'Teams__ClientId'
+ value: identity.properties.clientId
+ }
+ {
+ name: 'Teams__TenantId'
+ value: identity.properties.tenantId
+ }
+ {
+ name: 'Teams__BotType'
+ value: 'UserAssignedMsi'
+ }
+ ]
+ ftpsState: 'FtpsOnly'
+ }
+ }
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: {
+ '${identity.id}': {}
+ }
+ }
+}
+
+// Register your web service as a bot with the Bot Framework
+module azureBotRegistration './botRegistration/azurebot.bicep' = {
+ name: 'Azure-Bot-registration'
+ params: {
+ resourceBaseName: resourceBaseName
+ identityClientId: identity.properties.clientId
+ identityResourceId: identity.id
+ identityTenantId: identity.properties.tenantId
+ botAppDomain: webApp.properties.defaultHostName
+ botDisplayName: botDisplayName
}
}
+
+// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details.
+output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id
+output BOT_DOMAIN string = webApp.properties.defaultHostName
+output BOT_ID string = identity.properties.clientId
+output BOT_TENANT_ID string = identity.properties.tenantId
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.parameters.json b/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.parameters.json
index 0bf44f8d07..f78b989f5f 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.parameters.json
+++ b/samples/bot-suggested-actions/csharp/M365Agent/infra/azure.parameters.json
@@ -1,24 +1,15 @@
{
- "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
- "contentVersion": "1.0.0.0",
- "parameters": {
- "resourceBaseName": {
- "value": "bot${{RESOURCE_SUFFIX}}"
- },
- "botAadAppClientId": {
- "value": "${{AAD_APP_CLIENT_ID}}"
- },
- "botAppDomain": {
- "value": "${{BOT_DOMAIN}}"
- },
- "botDisplayName": {
- "value": "bot-suggested-actions"
- },
- "microsoftAppType": {
- "value": "${{MICROSOFT_APP_TYPE}}"
- },
- "microsoftAppTenantId": {
- "value": "${{MICROSOFT_APP_TENANT_ID}}"
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "resourceBaseName": {
+ "value": "bot${{RESOURCE_SUFFIX}}"
+ },
+ "webAppSKU": {
+ "value": "B1"
+ },
+ "botDisplayName": {
+ "value": "SuggestedActions"
+ }
}
- }
-}
\ No newline at end of file
+ }
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/azurebot.bicep b/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/azurebot.bicep
new file mode 100644
index 0000000000..a5a27b8fe4
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/azurebot.bicep
@@ -0,0 +1,42 @@
+@maxLength(20)
+@minLength(4)
+@description('Used to generate names for all resources in this file')
+param resourceBaseName string
+
+@maxLength(42)
+param botDisplayName string
+
+param botServiceName string = resourceBaseName
+param botServiceSku string = 'F0'
+param identityResourceId string
+param identityClientId string
+param identityTenantId string
+param botAppDomain string
+
+// Register your web service as a bot with the Bot Framework
+resource botService 'Microsoft.BotService/botServices@2021-03-01' = {
+ kind: 'azurebot'
+ location: 'global'
+ name: botServiceName
+ properties: {
+ displayName: botDisplayName
+ endpoint: 'https://${botAppDomain}/api/messages'
+ msaAppId: identityClientId
+ msaAppMSIResourceId: identityResourceId
+ msaAppTenantId:identityTenantId
+ msaAppType:'UserAssignedMSI'
+ }
+ sku: {
+ name: botServiceSku
+ }
+}
+
+// Connect the bot service to Microsoft Teams
+resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
+ parent: botService
+ location: 'global'
+ name: 'MsTeamsChannel'
+ properties: {
+ channelName: 'MsTeamsChannel'
+ }
+}
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/readme.md b/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/readme.md
new file mode 100644
index 0000000000..d5416243cd
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/M365Agent/infra/botRegistration/readme.md
@@ -0,0 +1 @@
+The `azurebot.bicep` module is provided to help you create Azure Bot service when you don't use Azure to host your app. If you use Azure as infrastrcture for your app, `azure.bicep` under infra folder already leverages this module to create Azure Bot service for you. You don't need to deploy `azurebot.bicep` again.
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/launchSettings.json b/samples/bot-suggested-actions/csharp/M365Agent/launchSettings.json
index d6491ef52c..2af8ce7a8a 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/launchSettings.json
+++ b/samples/bot-suggested-actions/csharp/M365Agent/launchSettings.json
@@ -1,15 +1,25 @@
{
- "profiles": {
- // Debug project within Teams
- "Microsoft Teams (browser)": {
- "commandName": "Project",
- "launchUrl": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}"
- },
- // Launch project within Teams without prepare app dependencies
- "Microsoft Teams (browser) (skip update app)": {
- "commandName": "Project",
- "environmentVariables": { "UPDATE_TEAMS_APP": "false" },
- "launchUrl": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}"
- }
- }
+ "profiles": {
+ // Launch project within Microsoft 365 Agents Playground
+ "Microsoft 365 Agents Playground (browser)": {
+ "commandName": "Project",
+ "environmentVariables": {
+ "UPDATE_TEAMS_APP": "false",
+ "M365_AGENTS_PLAYGROUND_TARGET_SDK": "teams-ai-v2-dotnet"
+ },
+ "launchTestTool": true,
+ "launchUrl": "http://localhost:56150",
+ },
+ // Launch project within Teams
+ "Microsoft Teams (browser)": {
+ "commandName": "Project",
+ "launchUrl": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}",
+ },
+ // Launch project within Teams without prepare app dependencies
+ "Microsoft Teams (browser) (skip update app)": {
+ "commandName": "Project",
+ "environmentVariables": { "UPDATE_TEAMS_APP": "false" },
+ "launchUrl": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}"
+ },
+ }
}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/m365agents.local.yml b/samples/bot-suggested-actions/csharp/M365Agent/m365agents.local.yml
index d9a9a96afa..8b6ab2261a 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/m365agents.local.yml
+++ b/samples/bot-suggested-actions/csharp/M365Agent/m365agents.local.yml
@@ -1,79 +1,75 @@
-# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.2/yaml.schema.json
+# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
# Visit https://aka.ms/teamsfx-actions for details on actions
-version: v1.2
-
-additionalMetadata:
- sampleTag: Microsoft-Teams-Samples:bot-suggested-actions-csharp
+version: v1.11
provision:
- - uses: aadApp/create # Creates a new Azure Active Directory (AAD) app to authenticate users if the environment variable that stores clientId is empty
- with:
- name: bot-suggested-actions-aad # Note: when you run aadApp/update, the AAD app name will be updated based on the definition in manifest. If you don't want to change the name, make sure the name in AAD manifest is the same with the name defined here.
- generateClientSecret: true # If the value is false, the action will not generate client secret for you
- signInAudience: "AzureADMultipleOrgs" # Multitenant
- writeToEnvironmentFile: # Write the information of created resources into environment file for the specified environment variable(s).
- clientId: AAD_APP_CLIENT_ID
- clientSecret: SECRET_AAD_APP_CLIENT_SECRET # Environment variable that starts with `SECRET_` will be stored to the .env.{envName}.user environment file
- objectId: AAD_APP_OBJECT_ID
- tenantId: AAD_APP_TENANT_ID
- authority: AAD_APP_OAUTH_AUTHORITY
- authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST
-
# Creates a Teams app
- uses: teamsApp/create
with:
# Teams app name
- name: bot-suggested-actions${{APP_NAME_SUFFIX}}
+ name: SuggestedActions${{APP_NAME_SUFFIX}}
# Write the information of created resources into environment file for
# the specified environment variable(s).
- writeToEnvironmentFile:
+ writeToEnvironmentFile:
teamsAppId: TEAMS_APP_ID
- - uses: script
+ # Create or reuse an existing Microsoft Entra application for bot.
+ - uses: aadApp/create
+ with:
+ # The Microsoft Entra application's display name
+ name: SuggestedActions${{APP_NAME_SUFFIX}}
+ generateClientSecret: true
+ generateServicePrincipal: true
+ signInAudience: AzureADMultipleOrgs
+ writeToEnvironmentFile:
+ # The Microsoft Entra application's client id created for bot.
+ clientId: BOT_ID
+ # The Microsoft Entra application's client secret created for bot.
+ clientSecret: SECRET_BOT_PASSWORD
+ # The Microsoft Entra application's object id created for bot.
+ objectId: BOT_OBJECT_ID
+
+ # Update the AAD app using the manifest file
+ - uses: aadApp/update
with:
- run:
- echo "::set-teamsfx-env MICROSOFT_APP_TYPE=SingleTenant";
- echo "::set-teamsfx-env MICROSOFT_APP_TENANT_ID=${{AAD_APP_TENANT_ID}}";
+ # Relative path to the AAD app manifest file
+ manifestPath: ./aad.manifest.json
+ # Output the final AAD manifest to env folder
+ outputFilePath: ./env/aad.manifest.${{TEAMSFX_ENV}}.json
# Generate runtime appsettings to JSON file
- uses: file/createOrUpdateJsonFile
with:
- target: ../SuggestedActions/appsettings.json
+ target: ../SuggestedActions/appsettings.Development.json
content:
- MicrosoftAppId: ${{AAD_APP_CLIENT_ID}}
- MicrosoftAppPassword: ${{SECRET_AAD_APP_CLIENT_SECRET}}
- MicrosoftAppType: ${{MICROSOFT_APP_TYPE}}
- MicrosoftAppTenantId: ${{MICROSOFT_APP_TENANT_ID}}
+ Teams:
+ ClientId: ${{BOT_ID}}
+ ClientSecret: ${{SECRET_BOT_PASSWORD}}
+ TenantId: ${{TEAMS_APP_TENANT_ID}}
- - uses: arm/deploy # Deploy given ARM templates parallelly.
+ # Create or update the bot registration on dev.botframework.com
+ - uses: botFramework/create
with:
- subscriptionId: ${{AZURE_SUBSCRIPTION_ID}} # The AZURE_SUBSCRIPTION_ID is a built-in environment variable. TeamsFx will ask you select one subscription if its value is empty. You're free to reference other environment varialbe here, but TeamsFx will not ask you to select subscription if it's empty in this case.
- resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}} # The AZURE_RESOURCE_GROUP_NAME is a built-in environment variable. TeamsFx will ask you to select or create one resource group if its value is empty. You're free to reference other environment varialbe here, but TeamsFx will not ask you to select or create resource grouop if it's empty in this case.
- templates:
- - path: ./infra/azure.bicep
- parameters: ./infra/azure.parameters.json
- deploymentName: Create-resources-for-bot
- bicepCliVersion: v0.9.1 # Microsoft 365 Agents Toolkit will download this bicep CLI version from github for you, will use bicep CLI in PATH if you remove this config.
-
- - uses: aadApp/update # Apply the AAD manifest to an existing AAD app. Will use the object id in manifest file to determine which AAD app to update.
- with:
- manifestPath: ./aad.manifest.json # Relative path to teamsfx folder. Environment variables in manifest will be replaced before apply to AAD app
- outputFilePath: ./build/aad.manifest.${{TEAMSFX_ENV}}.json
+ botId: ${{BOT_ID}}
+ name: SuggestedActions
+ messagingEndpoint: ${{BOT_ENDPOINT}}/api/messages
+ description: ""
+ channels:
+ - name: msteams
# Validate using manifest schema
- uses: teamsApp/validateManifest
with:
# Path to manifest template
manifestPath: ./appPackage/manifest.json
-
# Build Teams app package with latest env value
- uses: teamsApp/zipAppPackage
with:
# Path to manifest template
manifestPath: ./appPackage/manifest.json
outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
- outputJsonPath: ./appPackage/build/manifest.${{TEAMSFX_ENV}}.json
+ outputFolder: ./appPackage/build
# Validate app package using validation rules
- uses: teamsApp/validateAppPackage
with:
@@ -86,4 +82,4 @@ provision:
- uses: teamsApp/update
with:
# Relative path to this file. This is the path for built zip file.
- appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
\ No newline at end of file
+ appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
diff --git a/samples/bot-suggested-actions/csharp/M365Agent/m365agents.yml b/samples/bot-suggested-actions/csharp/M365Agent/m365agents.yml
index ffd6fb1753..62e1a8cc1d 100644
--- a/samples/bot-suggested-actions/csharp/M365Agent/m365agents.yml
+++ b/samples/bot-suggested-actions/csharp/M365Agent/m365agents.yml
@@ -1,9 +1,88 @@
-# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.2/yaml.schema.json
+# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.9/yaml.schema.json
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
# Visit https://aka.ms/teamsfx-actions for details on actions
-version: v1.2
+version: v1.9
-additionalMetadata:
- sampleTag: Microsoft-Teams-Samples:bot-suggested-actions-csharp
+environmentFolderPath: ./env
-environmentFolderPath: ./env
\ No newline at end of file
+# Triggered when 'teamsapp provision' is executed
+provision:
+ # Creates a Teams app
+ - uses: teamsApp/create
+ with:
+ # Teams app name
+ name: SuggestedActions${{APP_NAME_SUFFIX}}
+ # Write the information of created resources into environment file for
+ # the specified environment variable(s).
+ writeToEnvironmentFile:
+ teamsAppId: TEAMS_APP_ID
+
+ - uses: arm/deploy # Deploy given ARM templates parallelly.
+ with:
+ # AZURE_SUBSCRIPTION_ID is a built-in environment variable,
+ # if its value is empty, TeamsFx will prompt you to select a subscription.
+ # Referencing other environment variables with empty values
+ # will skip the subscription selection prompt.
+ subscriptionId: ${{AZURE_SUBSCRIPTION_ID}}
+ # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable,
+ # if its value is empty, TeamsFx will prompt you to select or create one
+ # resource group.
+ # Referencing other environment variables with empty values
+ # will skip the resource group selection prompt.
+ resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}}
+ templates:
+ - path: ./infra/azure.bicep # Relative path to this file
+ # Relative path to this yaml file.
+ # Placeholders will be replaced with corresponding environment
+ # variable before ARM deployment.
+ parameters: ./infra/azure.parameters.json
+ # Required when deploying ARM template
+ deploymentName: Create-resources-for-bot
+ # Microsoft 365 Agents Toolkit will download this bicep CLI version from github for you,
+ # will use bicep CLI in PATH if you remove this config.
+ bicepCliVersion: v0.9.1
+
+ # Validate using manifest schema
+ - uses: teamsApp/validateManifest
+ with:
+ # Path to manifest template
+ manifestPath: ./appPackage/manifest.json
+ # Build Teams app package with latest env value
+ - uses: teamsApp/zipAppPackage
+ with:
+ # Path to manifest template
+ manifestPath: ./appPackage/manifest.json
+ outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
+ outputFolder: ./appPackage/build
+ # Validate app package using validation rules
+ - uses: teamsApp/validateAppPackage
+ with:
+ # Relative path to this file. This is the path for built zip file.
+ appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
+ # Apply the Teams app manifest to an existing Teams app in
+ # Developer Portal.
+ # Will use the app id in manifest file to determine which Teams app to update.
+ - uses: teamsApp/update
+ with:
+ # Relative path to this file. This is the path for built zip file.
+ appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
+
+# Triggered when 'teamsapp deploy' is executed
+deploy:
+ - uses: cli/runDotnetCommand
+ with:
+ args: publish --configuration Release --runtime win-x86 --self-contained
+ SuggestedActions.csproj
+ workingDirectory: ../SuggestedActions
+ # Deploy your application to Azure App Service using the zip deploy feature.
+ # For additional details, refer to https://aka.ms/zip-deploy-to-app-services.
+ - uses: azureAppService/zipDeploy
+ with:
+ # Deploy base folder
+ artifactFolder: bin/Release/net10.0/win-x86/publish
+ # The resource id of the cloud resource to be deployed to.
+ # This key will be generated by arm/deploy action automatically.
+ # You can replace it with your existing Azure Resource id
+ # or add it to your environment variable file.
+ resourceId: ${{BOT_AZURE_APP_SERVICE_RESOURCE_ID}}
+ workingDirectory: ../SuggestedActions
diff --git a/samples/bot-suggested-actions/csharp/README.md b/samples/bot-suggested-actions/csharp/README.md
index b527232c0a..c9a6d9f9e6 100644
--- a/samples/bot-suggested-actions/csharp/README.md
+++ b/samples/bot-suggested-actions/csharp/README.md
@@ -62,7 +62,7 @@ The simplest way to run this sample in Teams is to use Microsoft 365 Agents Tool
* Choose the **supported account types** (any account type will work)
* Leave **Redirect URI** empty.
* Choose **Register**.
- 3. On the overview page, copy and save the **Application (client) ID, Directory (tenant) ID**. You'll need those later when updating your Teams application manifest and in the appsettings.json.
+ 3. On the overview page, copy and save the **Application (client) ID, Directory (tenant) ID**. You'll need those later when updating your Teams application manifest and in the appsettings.Development.json.
4. Navigate to **API Permissions**, and make sure to add the follow permissions:
Select Add a permission
* Select Add a permission
@@ -78,17 +78,18 @@ The simplest way to run this sample in Teams is to use Microsoft 365 Agents Tool
> NOTE: When you create your app registration, you will create an App ID and App password - make sure you keep these for later.
-3. Setup NGROK
- - Run ngrok - point to port 3978
+3. Setup dev tunnel - point to port 3978
+
+ Please follow [Create and host a dev tunnel](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started?tabs=windows) and host the tunnel with anonymous user access command as shown below:
```bash
- ngrok http 3978 --host-header="localhost:3978"
- ```
+ devtunnel host -p 3978 --allow-anonymous
+ ```
- Alternatively, you can also use the `dev tunnels`. Please follow [Create and host a dev tunnel](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started?tabs=windows) and host the tunnel with anonymous user access command as shown below:
+ Alternatively, you can also use ngrok:
```bash
- devtunnel host -p 3978 --allow-anonymous
+ ngrok http 3978 --host-header="localhost:3978"
```
4. Setup for code
@@ -97,9 +98,10 @@ The simplest way to run this sample in Teams is to use Microsoft 365 Agents Tool
```bash
git clone https://github.com/OfficeDev/Microsoft-Teams-Samples.git
```
- - Modify the `/appsettings.json` and fill in the following details:
- - `{{MicrosoftAppId}}` - Generated from Step 1 is the application app id
- - `{{MicrosoftAppPassword}}` - Generated from Step 1, also referred to as Client secret
+ - Modify the `SuggestedActions/appsettings.Development.json` and fill in the following details:
+ - `{{Teams:ClientId}}` - Generated from Step 1.3, the Application (client) ID
+ - `{{Teams:ClientSecret}}` - Generated from Step 2, also referred to as Client secret/App password
+ - `{{Teams:TenantId}}` - Generated from Step 1.3, the Directory (tenant) ID
- In a terminal, navigate to `samples/bot-suggested-actions/csharp`
@@ -122,7 +124,7 @@ The simplest way to run this sample in Teams is to use Microsoft 365 Agents Tool
5. Setup Manifest for Teams
- __*This step is specific to Teams.*__
- - **Edit** the `manifest.json` contained in the ./appPackage folder to replace your Microsoft App Id (that was created when you registered your app registration earlier) *everywhere* you see the place holder string `{{Microsoft-App-Id}}` (depending on the scenario the Microsoft App Id may occur multiple times in the `manifest.json`)
+ - **Edit** the `manifest.json` contained in the ./appPackage folder to replace your Microsoft App Id (that was created when you registered your app registration earlier) *everywhere* you see the place holder string `{{BOT_ID}}` (depending on the scenario the Microsoft App Id may occur multiple times in the `manifest.json`)
- **Edit** the `manifest.json` for `validDomains` and replace `{{domain-name}}` with base Url of your domain. E.g. if you are using ngrok it would be `https://1234.ngrok-free.app` then your domain-name will be `1234.ngrok-free.app` and if you are using dev tunnels then your domain will be like: `12345.devtunnels.ms`.
- **Zip** up the contents of the `appPackage` folder to create a `manifest.zip` (Make sure that zip file does not contains any subfolder otherwise you will get error while uploading your .zip package)
@@ -132,7 +134,6 @@ The simplest way to run this sample in Teams is to use Microsoft 365 Agents Tool
- Go to your project directory, the ./appPackage folder, select the zip folder, and choose Open.
- Select Add in the pop-up dialog box. Your app is uploaded to Teams.
-**Note**: If you are facing any issue in your app, please uncomment [this](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-suggested-actions/csharp/SuggestedActions/AdapterWithErrorHandler.cs#L28) line and put your debugger for local debug.
## Running the sample
@@ -164,7 +165,7 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
## Further reading
- [Send suggested actions](https://learn.microsoft.com/microsoftteams/platform/bots/how-to/conversations/conversation-messages?tabs=dotnet#send-suggested-actions)
-- [Bot Framework Documentation](https://docs.botframework.com)
+- [Teams Bot Service Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions.sln b/samples/bot-suggested-actions/csharp/SuggestedActions.sln
deleted file mode 100644
index 8442b7cb6f..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions.sln
+++ /dev/null
@@ -1,37 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.10.34814.14
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuggestedActionsBot", "SuggestedActions\SuggestedActionsBot.csproj", "{BFDF6B3D-BB62-42DD-88EF-528FFE9FCBAD}"
-EndProject
-Project("{A9E3F50B-275E-4AF7-ADCE-8BE12D41E305}") = "M365Agent", "M365Agent\M365Agent.ttkproj", "{45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9A2118D2-216C-448F-AC6C-62C33F0537AB}"
- ProjectSection(SolutionItems) = preProject
- SuggestedActions.slnLaunch.user = SuggestedActions.slnLaunch.user
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {BFDF6B3D-BB62-42DD-88EF-528FFE9FCBAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BFDF6B3D-BB62-42DD-88EF-528FFE9FCBAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BFDF6B3D-BB62-42DD-88EF-528FFE9FCBAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BFDF6B3D-BB62-42DD-88EF-528FFE9FCBAD}.Release|Any CPU.Build.0 = Release|Any CPU
- {45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {45C5B04B-E16F-4EEB-B567-8DE2A5FEF1ED}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {8F7F570D-74C3-4CF3-AACD-361A3D3F8E37}
- EndGlobalSection
-EndGlobal
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions.slnLaunch.user b/samples/bot-suggested-actions/csharp/SuggestedActions.slnLaunch.user
index 9ac6c6961a..f52c3c0861 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions.slnLaunch.user
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions.slnLaunch.user
@@ -1,31 +1,52 @@
[
{
- "Name": "Microsoft Teams (browser)",
+ "Name": "Microsoft 365 Agents Playground (browser)",
"Projects": [
{
- "Path": "SuggestedActions\\SuggestedActionsBot.csproj",
- "Action": "Start",
- "DebugTarget": "Start Project"
+ "Path": "M365Agent\\M365Agent.atkproj",
+ "Name": "M365Agent\\M365Agent.atkproj",
+ "Action": "StartWithoutDebugging",
+ "DebugTarget": "Microsoft 365 Agents Playground (browser)"
},
{
- "Path": "M365Agent\\M365Agent.ttkproj",
- "Action": "StartWithoutDebugging",
- "DebugTarget": "Microsoft Teams (browser)"
+ "Path": "SuggestedActions\\SuggestedActions.csproj",
+ "Name": "SuggestedActions\\SuggestedActions.csproj",
+ "Action": "Start",
+ "DebugTarget": "Microsoft 365 Agents Playground"
}
]
},
{
- "Name": "Microsoft Teams (browser) (skip update app)",
+ "Name": "Microsoft Teams (browser)",
"Projects": [
{
- "Path": "SuggestedActions\\SuggestedActionsBot.csproj",
+ "Path": "M365Agent\\M365Agent.atkproj",
+ "Name": "M365Agent\\M365Agent.atkproj",
+ "Action": "StartWithoutDebugging",
+ "DebugTarget": "Microsoft Teams (browser)"
+ },
+ {
+ "Path": "SuggestedActions\\SuggestedActions.csproj",
+ "Name": "SuggestedActions\\SuggestedActions.csproj",
"Action": "Start",
"DebugTarget": "Start Project"
- },
+ }
+ ]
+ },
+ {
+ "Name": "Microsoft Teams (browser) (skip update app)",
+ "Projects": [
{
- "Path": "M365Agent\\M365Agent.ttkproj",
+ "Path": "M365Agent\\M365Agent.atkproj",
+ "Name": "M365Agent\\M365Agent.atkproj",
"Action": "StartWithoutDebugging",
"DebugTarget": "Microsoft Teams (browser) (skip update app)"
+ },
+ {
+ "Path": "SuggestedActions\\SuggestedActions.csproj",
+ "Name": "SuggestedActions\\SuggestedActions.csproj",
+ "Action": "Start",
+ "DebugTarget": "Start Project"
}
]
}
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions.slnx b/samples/bot-suggested-actions/csharp/SuggestedActions.slnx
new file mode 100644
index 0000000000..157c82c46c
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions.slnx
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/.gitignore b/samples/bot-suggested-actions/csharp/SuggestedActions/.gitignore
index 7466c01f9c..89b80db704 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/.gitignore
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/.gitignore
@@ -22,4 +22,8 @@ bld/
[Ll]og/
# Notification local store
-.notification.localstore.json
\ No newline at end of file
+.notification.localstore.json
+.notification.playgroundstore.json
+
+# devTools
+devTools/
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/AdapterWithErrorHandler.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/AdapterWithErrorHandler.cs
deleted file mode 100644
index 95bb27d622..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/AdapterWithErrorHandler.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using System;
-using System.Net.Http;
-using Microsoft.Bot.Builder;
-using Microsoft.Bot.Builder.Integration.AspNet.Core;
-using Microsoft.Bot.Builder.TraceExtensions;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.BotBuilderSamples
-{
- public class AdapterWithErrorHandler : CloudAdapter
- {
- public AdapterWithErrorHandler(IConfiguration configuration, IHttpClientFactory httpClientFactory, ILogger logger, ConversationState conversationState = default)
- : base(configuration, httpClientFactory, logger)
- {
- OnTurnError = async (turnContext, exception) =>
- {
- // Log any leaked exception from the application.
- // NOTE: In production environment, you should consider logging this to
- // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
- // to add telemetry capture to your bot.
- logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
-
- // Uncomment below commented line for local debugging.
- // await turnContext.SendActivityAsync($"Sorry, it looks like something went wrong. Exception Caught: {exception.Message}");
-
- if (conversationState != null)
- {
- try
- {
- // Delete the conversationState for the current conversation to prevent the
- // bot from getting stuck in a error-loop caused by being in a bad state.
- // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
- await conversationState.DeleteAsync(turnContext);
- }
- catch (Exception e)
- {
- logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
- }
- }
-
- // Send a trace activity, which will be displayed in the Bot Framework Emulator
- await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
- };
- }
- }
-}
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Bots/SuggestedActionsBot.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Bots/SuggestedActionsBot.cs
deleted file mode 100644
index 5c3564e772..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/Bots/SuggestedActionsBot.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using Microsoft.Bot.Builder;
-using Microsoft.Bot.Schema;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.BotBuilderSamples
-{
- ///
- /// This bot will respond to the user's input with suggested actions.
- /// Suggested actions enable your bot to present buttons that the user
- /// can tap to provide input.
- ///
- public class SuggestedActionsBot : ActivityHandler
- {
- private readonly IConfiguration _configuration;
-
- public SuggestedActionsBot(IConfiguration config)
- {
- _configuration = config;
- }
-
- ///
- /// Invoked when members are added to the conversation.
- /// Sends a welcome message to the user and tells them what actions they may perform to use this bot.
- ///
- /// List of members added to the conversation.
- /// Context object containing information for a single turn of conversation with a user.
- /// Cancellation token.
- protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken)
- {
- await SendWelcomeMessageAsync(turnContext, cancellationToken);
- }
-
- ///
- /// Invoked when a message activity is received from the user.
- /// Processes the user's input and responds with the appropriate message and suggested actions.
- ///
- /// Context object containing information for a single turn of conversation with a user.
- /// Cancellation token.
- protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken)
- {
- var text = turnContext.Activity.Text.ToLowerInvariant();
- var responseText = ProcessInput(text);
-
- await turnContext.SendActivityAsync(responseText, cancellationToken: cancellationToken);
- await SendSuggestedActionsAsync(turnContext, cancellationToken);
- }
-
- ///
- /// Sends a welcome message to the user and tells them what actions they may perform to use this bot.
- ///
- /// Context object containing information for a single turn of conversation with a user.
- /// Cancellation token.
- private async Task SendWelcomeMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
- {
- foreach (var member in turnContext.Activity.MembersAdded)
- {
- if (member.Id != turnContext.Activity.Recipient.Id)
- {
- await turnContext.SendActivityAsync(
- "Welcome to the suggested actions bot. This bot will introduce you to suggested actions. Please answer the question:",
- cancellationToken: cancellationToken);
- await SendSuggestedActionsAsync(turnContext, cancellationToken);
- }
- }
- }
-
- ///
- /// Processes the user's input and returns the appropriate response text.
- ///
- /// The user's input text.
- /// The response text based on the user's input.
- private static string ProcessInput(string text)
- {
- const string colorText = "How can I assist you today?";
- return text switch
- {
- "hello" => $"Hello, {colorText}",
- "welcome" => $"Welcome, {colorText}",
- _ => "Please select one action",
- };
- }
-
- ///
- /// Creates and sends an activity with suggested actions to the user.
- /// When the user clicks one of the buttons, the text value from the "CardAction" will be
- /// displayed in the channel just as if the user entered the text.
- ///
- /// Context object containing information for a single turn of conversation with a user.
- /// Cancellation token.
- private async Task SendSuggestedActionsAsync(ITurnContext turnContext, CancellationToken cancellationToken)
- {
- var reply = MessageFactory.Text("Choose one of the action from the suggested action?");
-
- var payload = new
- {
- type = "Teams.chatMessage",
- data = new
- {
- body = new
- {
- additionalData = new { },
- backingStore = new
- {
- returnOnlyChangedValues = false,
- initializationCompleted = true
- },
- content = "SuggestedActionsBot"
- },
- mentions = new[]
- {
- new
- {
- additionalData = new { },
- backingStore = new
- {
- returnOnlyChangedValues = false,
- initializationCompleted = false
- },
- id = 0,
- mentioned = new
- {
- additionalData = new { },
- backingStore = new
- {
- returnOnlyChangedValues = false,
- initializationCompleted = false
- },
- odataType = "#microsoft.graph.chatMessageMentionedIdentitySet",
- user = new
- {
- additionalData = new { },
- backingStore = new
- {
- returnOnlyChangedValues = false,
- initializationCompleted = false
- },
- displayName = "Suggested Actions Bot",
- id = "28:" + _configuration["MicrosoftAppId"],
- }
- },
- mentionText = "Suggested Actions Bot"
- }
- },
- additionalData = new { },
- backingStore = new
- {
- returnOnlyChangedValues = false,
- initializationCompleted = true
- }
- }
- };
-
- reply.SuggestedActions = new SuggestedActions()
- {
- Actions = new List()
- {
- new CardAction() { Title = "Hello", Type = ActionTypes.ImBack, Value = "Hello" },
- new CardAction() { Title = "Welcome", Type = ActionTypes.ImBack, Value = "Welcome" },
- new CardAction() { Title = "@SuggestedActionsBot", Type = "Action.Compose", Value = payload }
- }
- };
-
- await turnContext.SendActivityAsync(reply, cancellationToken);
- }
- }
-}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Config.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Config.cs
new file mode 100644
index 0000000000..93dd16a38f
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/Config.cs
@@ -0,0 +1,14 @@
+namespace SuggestedActions
+{
+ public class ConfigOptions
+ {
+ public TeamsConfigOptions Teams { get; set; }
+ }
+
+ public class TeamsConfigOptions
+ {
+ public string ClientId { get; set; }
+ public string ClientSecret { get; set; }
+ public string TenantId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/BotController.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/BotController.cs
deleted file mode 100644
index fa4ea81324..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/BotController.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Bot.Builder;
-using Microsoft.Bot.Builder.Integration.AspNet.Core;
-
-namespace Microsoft.BotBuilderSamples
-{
- // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
- // implementation at runtime. Multiple different IBot implementations running at different endpoints can be
- // achieved by specifying a more specific type for the bot constructor argument.
- [Route("api/messages")]
- [ApiController]
- public class BotController : ControllerBase
- {
- private readonly IBotFrameworkHttpAdapter _adapter;
- private readonly IBot _bot;
-
- public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
- {
- _adapter = adapter;
- _bot = bot;
- }
-
- [HttpPost]
- public async Task PostAsync()
- {
- // Delegate the processing of the HTTP POST to the adapter.
- // The adapter will invoke the bot.
- await _adapter.ProcessAsync(Request, Response, _bot);
- }
- }
-}
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/Controller.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/Controller.cs
new file mode 100644
index 0000000000..6305552205
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/Controllers/Controller.cs
@@ -0,0 +1,101 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Teams.Api.Activities;
+using Microsoft.Teams.Apps;
+using Microsoft.Teams.Apps.Activities;
+using Microsoft.Teams.Apps.Annotations;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Teams.Api;
+using Microsoft.Teams.Api.Cards;
+
+namespace SuggestedActions.Controllers
+{
+ [TeamsController]
+ public class Controller
+ {
+ private readonly IConfiguration _configuration;
+
+ public Controller(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ [Message]
+ public async Task OnMessage([Context] MessageActivity activity, [Context] IContext.Client client, [Context] Microsoft.Teams.Common.Logging.ILogger log)
+ {
+ log.Info("Message received");
+
+ var text = activity.Text?.ToLowerInvariant() ?? string.Empty;
+ var responseText = ProcessInput(text);
+
+ await client.Typing();
+ await client.Send(responseText);
+ await SendSuggestedActionsCardAsync(client, log);
+ }
+
+ [Microsoft.Teams.Apps.Activities.Conversation.MembersAdded]
+ public async Task OnMembersAdded([Context] ConversationUpdateActivity activity, [Context] IContext.Client client, [Context] Microsoft.Teams.Common.Logging.ILogger log)
+ {
+ foreach (var member in activity.MembersAdded)
+ {
+ if (member.Id != activity.Recipient.Id)
+ {
+ await client.Send("Welcome to the suggested actions bot. This bot will introduce you to suggested actions. Please answer the question:");
+ await SendSuggestedActionsCardAsync(client, log);
+ }
+ }
+ }
+
+ ///
+ /// Processes the user's input and returns the appropriate response text.
+ ///
+ /// The user's input text.
+ /// The response text based on the user's input.
+ private static string ProcessInput(string text)
+ {
+ const string colorText = "How can I assist you today?";
+ return text switch
+ {
+ "hello" => $"Hello, {colorText}",
+ "welcome" => $"Welcome, {colorText}",
+ _ => "Please select one action",
+ };
+ }
+
+ ///
+ /// Creates and sends a message with suggested actions to the user.
+ /// Uses native Teams SDK SuggestedActions with IMBack action type.
+ /// When the user clicks a button, the text value will be displayed in the channel as if the user typed it,
+ /// and will automatically trigger the OnMessage handler.
+ ///
+ private async Task SendSuggestedActionsCardAsync(IContext.Client client, Microsoft.Teams.Common.Logging.ILogger? log)
+ {
+ log?.Info("Sending suggested actions");
+
+ // Create MessageActivity with SuggestedActions using native Teams SDK
+ var message = new MessageActivity()
+ {
+ Text = "Choose one of the action from the suggested action?",
+ SuggestedActions = new Microsoft.Teams.Api.SuggestedActions()
+ .AddAction(new Microsoft.Teams.Api.Cards.Action(ActionType.IMBack)
+ {
+ Title = "Hello",
+ Value = "Hello"
+ })
+ .AddAction(new Microsoft.Teams.Api.Cards.Action(ActionType.IMBack)
+ {
+ Title = "Welcome",
+ Value = "Welcome"
+ })
+ .AddAction(new Microsoft.Teams.Api.Cards.Action(ActionType.IMBack)
+ {
+ Title = "@SuggestedActionsBot",
+ Value = "@SuggestedActionsBot"
+ })
+ };
+
+ await client.Send(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Program.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Program.cs
index 8c73eec6fc..e87b4bf433 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/Program.cs
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/Program.cs
@@ -1,41 +1,28 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
+using SuggestedActions;
+using SuggestedActions.Controllers;
+using Azure.Core;
+using Azure.Identity;
+using Microsoft.Teams.Api.Auth;
+using Microsoft.Teams.Apps;
+using Microsoft.Teams.Apps.Extensions;
+using Microsoft.Teams.Common.Http;
+using Microsoft.Teams.Plugins.AspNetCore.Extensions;
-namespace Microsoft.BotBuilderSamples
-{
- ///
- /// The main entry point for the application.
- ///
- public class Program
- {
- ///
- /// The main method which is the entry point of the application.
- ///
- /// The command-line arguments.
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
+// Create web application builder and load configuration
+var builder = WebApplication.CreateBuilder(args);
+var config = builder.Configuration.Get();
- ///
- /// Creates and configures the host builder.
- ///
- /// The command-line arguments.
- /// An initialized instance.
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.ConfigureLogging(logging =>
- {
- logging.AddDebug();
- logging.AddConsole();
- });
- webBuilder.UseStartup();
- });
- }
-}
+// Create Teams app builder
+var appBuilder = App.Builder();
+
+// Register controller and configure Teams services
+builder.Services.AddSingleton();
+builder.AddTeams(appBuilder);
+
+// Build and run the application
+var app = builder.Build();
+app.UseTeams();
+app.Run();
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Properties/launchSettings.json b/samples/bot-suggested-actions/csharp/SuggestedActions/Properties/launchSettings.json
index ff9d8fe153..921e10d3e8 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/Properties/launchSettings.json
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/Properties/launchSettings.json
@@ -1,13 +1,26 @@
-{
+{
"profiles": {
+ // Debug project within Microsoft 365 Agents Playground
+ "Microsoft 365 Agents Playground": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "applicationUrl": "http://localhost:3978",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Playground",
+ "TEAMSFX_NOTIFICATION_STORE_FILENAME": ".notification.playgroundstore.json",
+ "UPDATE_TEAMS_APP": "false"
+ },
+ "hotReloadProfile": "aspnetcore"
+ },
+ // Debug project within Teams
"Start Project": {
"commandName": "Project",
"dotnetRunMessages": true,
- "applicationUrl": "https://localhost:7130;http://localhost:5130",
+ "applicationUrl": "http://localhost:3978",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"hotReloadProfile": "aspnetcore"
- }
+ },
}
}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/Startup.cs b/samples/bot-suggested-actions/csharp/SuggestedActions/Startup.cs
deleted file mode 100644
index d2da0c62b3..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/Startup.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Bot.Builder;
-using Microsoft.Bot.Builder.Integration.AspNet.Core;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-
-namespace Microsoft.BotBuilderSamples
-{
- ///
- /// Configures services and the app's request pipeline.
- ///
- public class Startup
- {
- ///
- /// Adds services to the container.
- ///
- /// The service collection to add services to.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddHttpClient()
- .AddControllers()
- .AddNewtonsoftJson();
-
- // Create the Bot Framework Adapter with error handling enabled.
- services.AddSingleton();
-
- // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
- services.AddTransient();
- }
-
- ///
- /// Configures the HTTP request pipeline.
- ///
- /// The application builder.
- /// The web host environment.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseDefaultFiles()
- .UseStaticFiles()
- .UseRouting()
- .UseAuthorization()
- .UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
- }
-}
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActions.csproj b/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActions.csproj
new file mode 100644
index 0000000000..81958d0257
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActions.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+ None
+
+
+
+ PreserveNewest
+ None
+
+
+
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActionsBot.csproj b/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActionsBot.csproj
deleted file mode 100644
index 0e4ef5d761..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/SuggestedActionsBot.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- net6.0
- latest
-
-
-
-
-
-
-
-
-
- Always
-
-
-
-
-
-
-
-
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Development.json b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Development.json
index e203e9407e..8dadbe2c24 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Development.json
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Development.json
@@ -1,9 +1,18 @@
{
- "Logging": {
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information"
- }
- }
-}
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ },
+ "Microsoft.Teams": {
+ "Enable": "*",
+ "Level": "debug"
+ }
+ },
+ "AllowedHosts": "*",
+ "Teams": {
+ "ClientId": "",
+ "ClientSecret": "",
+ "TenantId": ""
+ }
+}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Playground.json b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Playground.json
new file mode 100644
index 0000000000..5981a18df5
--- /dev/null
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.Playground.json
@@ -0,0 +1,18 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ },
+ "Microsoft.Teams": {
+ "Enable": "*",
+ "Level": "debug"
+ }
+ },
+ "AllowedHosts": "*",
+ "Teams": {
+ "ClientId": "",
+ "ClientSecret": "",
+ "TenantId": ""
+ }
+}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.json b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.json
index 97dff81a1b..ed78418678 100644
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.json
+++ b/samples/bot-suggested-actions/csharp/SuggestedActions/appsettings.json
@@ -1,4 +1,18 @@
{
- "MicrosoftAppId": "",
- "MicrosoftAppPassword": ""
-}
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ },
+ "Microsoft.Teams": {
+ "Enable": "*",
+ "Level": "debug"
+ }
+ },
+ "AllowedHosts": "*",
+ "Teams": {
+ "ClientId": "",
+ "ClientSecret": "",
+ "TenantId": ""
+ }
+}
\ No newline at end of file
diff --git a/samples/bot-suggested-actions/csharp/SuggestedActions/wwwroot/default.htm b/samples/bot-suggested-actions/csharp/SuggestedActions/wwwroot/default.htm
deleted file mode 100644
index 88c7538a0b..0000000000
--- a/samples/bot-suggested-actions/csharp/SuggestedActions/wwwroot/default.htm
+++ /dev/null
@@ -1,417 +0,0 @@
-
-
-
-
-
-
- Suggested Actions Sample
-
-
-
-
-
-
-
-
-
Suggested Actions Sample
-
-
-
-
-
Your bot is ready!
-
You can test your bot in the Bot Framework Emulator
- by connecting to http://localhost:3978/api/messages.