Updates from: 06/26/2021 03:18:59
Service Microsoft Docs article Related commit history on GitHub Change details
platform Create Apps For Teams Meetings https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/apps-in-teams-meetings/create-apps-for-teams-meetings.md
The following table provides a list of these APIs:
### GetUserContext API
-To identify and retrieve contextual information for your tab content, see [get context for your Teams tab](../tabs/how-to/access-teams-context.md#getting-context-by-using-the-microsoft-teams-javascript-library). `meetingId` is used by a tab when running in the meeting context and is added for the response payload.
+To identify and retrieve contextual information for your tab content, see [get context for your Teams tab](../tabs/how-to/access-teams-context.md#get-context-by-using-the-microsoft-teams-javascript-library). `meetingId` is used by a tab when running in the meeting context and is added for the response payload.
### GetParticipant API
platform Enable And Configure Your App For Teams Meetings https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings.md
The in-meeting dialog box can be used to engage participants during the meeting
In-meeting dialog must not use task module. Task module is not invoked in a meeting chat. An external resource URL is used to display content bubble in a meeting. You can use the `submitTask` method to submit data in a meeting chat. > [!NOTE]
-> * You must invoke the [submitTask()](../task-modules-and-cards/task-modules/task-modules-bots.md#submitting-the-result-of-a-task-module) function to dismiss automatically after a user takes an action in the web view. This is a requirement for app submission. For more information, see [Teams SDK task module](/javascript/api/@microsoft/teams-js/microsoftteams.tasks?view=msteams-client-js-latest#submittask-stringobject--stringstring&preserve-view=true).
+> * You must invoke the [submitTask()](../task-modules-and-cards/task-modules/task-modules-bots.md#submit-the-result-of-a-task-module) function to dismiss automatically after a user takes an action in the web view. This is a requirement for app submission. For more information, see [Teams SDK task module](/javascript/api/@microsoft/teams-js/microsoftteams.tasks?view=msteams-client-js-latest#submittask-stringobject--stringstring&preserve-view=true).
> * If you want your app to support anonymous users, your initial invoke request payload must rely on the `from.id` request metadata in the `from` object, not the `from.aadObjectId` request metadata. `from.id` is the user ID and `from.aadObjectId` is the Azure Active Directory (AAD) ID of the user. For more information, see [using task modules in tabs](../task-modules-and-cards/task-modules/task-modules-tabs.md) and [create and send the task module](../messaging-extensions/how-to/action-commands/create-task-module.md?tabs=dotnet#the-initial-invoke-request). #### Shared meeting stage
platform Send Proactive Messages https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/bots/how-to/conversations/send-proactive-messages.md
localization_priority: Normal Keywords: send a message get user ID channel ID conversation ID
-# Send proactive messages
+# Proactive messages
[!INCLUDE [v4 to v3 pointer](~/includes/v4-to-v3-pointer-bots.md)]
platform Authentication https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/concepts/authentication/authentication.md
provides Bot authentication v3 SDK sample.
## Configure the identity provider
-Regardless of the app's authentication flow, configure the identity provider to communicate with the Teams app. Most samples and walkthroughs primarily deal with using AAD as the identity provider. The concepts, however, apply regardless of the identity provider.
+Regardless of the app's authentication flow, configure the identity provider to communicate with the Teams app. Most samples and walkthroughs primarily deal with using AAD as the identity provider. The concepts however, apply regardless of the identity provider.
For more information, see [configuring an identity provider](~/concepts/authentication/configure-identity-provider.md).
platform Apps Localization https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/concepts/build-and-test/apps-localization.md
Title: Localization for your app
+ Title: Localize your app
description: Describes considerations for localizing your Microsoft Teams app. localization_priority: Normal keywords: teams publish store office publishing AppSource localization language Last updated 05/15/2018
-# Localization for Microsoft Teams apps
+# Localize your app
-When localizing your Microsoft Teams app, you must consider the following:
+You must consider the following factors to localize your Microsoft Teams app:
-1. Your Teams store listing (if applicable).
-1. The end-user facing strings in your app manifest. For example bot commands.
-1. Responding to localized text submitted from your users.
+1. [Localize your AppSource listing](#localize-your-appsource-listing).
+1. [Localize strings in your app manifest](#localize-strings-in-your-app-manifest).
+1. [Handle localized text submissions from your users](#handle-localized-text-submissions-from-your-users).
-## Localizing your AppSource listing
+## Localize your AppSource listing
-If you're publishing to the store, you need to be aware that localizing your AppSource listing is not yet supported. However, in preparation for support for localized listings in the app store you can add additional languages to your listing. Currently only the default (English) language information you provide in [Partner Center](/office/dev/store/submit-to-appsource-via-partner-center) for your listing will appear in the [AppSource website](https://appsource.microsoft.com/marketplace/apps?product=office%3Bteams&page=1) listing for your app.
+If you are publishing the app to the store, you must be aware that localizing your AppSource listing is not yet supported. To support localized listings in the app store, you can add additional languages to your listing. The default language information you provide in [Partner Center](/office/dev/store/submit-to-appsource-via-partner-center) for your listing appears in the [AppSource website](https://appsource.microsoft.com/marketplace/apps?product=office%3Bteams&page=1) listing for your app. Currently, the default language is English.
-### Example of configuring localization
+### Configure localization
-To configure an additional language for your app, in [Partner Center](/office/dev/store/submit-to-appsource-via-partner-center), select both English and the additional language of the app. French is used in this example:
+To configure an additional language for your app, in [Partner Center](/office/dev/store/submit-to-appsource-via-partner-center), select both English and the additional language of the app. French is used as an additional language in the following example:
1. Add English language
- * Fill in the app name.
- * Fill in a short description of the app in English.
- * Fill in the long description of the app in English.
- * In the long description, please also add the line ΓÇ£This app is available in ΓÇ£FrenchΓÇ¥.
+ * Enter the app name.
+ * Enter a short description of the app in English.
+ * Enter the long description of the app in English.
+ * In the long description, enter: **This app is available in French**.
* Upload the images of your app UI (in English). 2. Add French language
- * Fill in the app name.
- * Fill in a short description of the app in French.
- * Fill in the long description of the app in French.
+ * Enter the app name.
+ * Enter a short description of the app in French.
+ * Enter the long description of the app in French.
* Upload the images of your app UI (in French).
-The images you upload with the English language will be the ones used in AppSource.
+The images that you upload with the English language are used in AppSource.
-## Localizing the strings in your app manifest
+## Localize strings in your app manifest
-You must use the Microsoft Teams app schema v1.5+ to properly localize your app. You can do this by setting the `$schema` attribute in your manifest.json file to 'https://developer.microsoft.com/en-us/json-schemas/teams/v1.8/MicrosoftTeams.Localization.schema.json' and updating the 'manifestVersion' property to '1.7'.
+You must use the Microsoft Teams app schema `v1.5` and later to localize your app. You can do this by setting the `$schema` attribute in your manifest.json file to **https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json** or higher and updating the `manifestVersion` property to `$schema` version (`1.5` in this case).
+
+You must add the `localizationInfo` property with the default language that your application supports. The default language is used as the final fallback language if the user's client settings do not match with any of your additional languages.
### Example manifest.json change
+The following manifest.json helps to add the `localizationInfo` property with the default language that your application supports along with `additionalLanguages`:
+ ```json {
- "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.8/MicrosoftTeams.Localization.schema.json",
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
"manifestVersion": "1.5",
+ "localizationInfo": {
+ "defaultLanguageTag": "en",
+ "additionalLanguages": [
+ {
+ "languageTag": "es-mx",
+ "file": "es-mx.json"
+ }
+ ]
+ }
... } ```
-You will then want to add the 'localizationInfo' property with the default language that your application supports. The default language is used as the final fallback language if the user's client settings do not match any of your additional languages.
+### Example localization .json change
-### Example manifest.json change
+Following is an example for localization .json:
```json {
- ...
- "localizationInfo": {
- "defaultLanguageTag": "en"
- }
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.Localization.schema.json",
+ "manifestVersion": "1.5",
+ "name.short": "Localizaci├│n",
+ "name.full": "Aplicaci├│n de localizaci├│n",
... } ```
-You can provide additional .json files with translations of all the user facing strings in your manifest. These files must adhere to the [Localization file JSON schema](../../resources/schem) and they must be added to the 'localizationInfo' property of your manifest. Each file correlates to a language tag which the Teams client uses to choose the appropriate strings. The language tag takes the form of <language>-<region> but it is recommended to omit the <region> portion to target all regions that support the desired language.
-The Teams client will apply the strings in this order: default language strings -> user's language only strings -> user's language + user's region strings.
+You can provide additional .json files with translations of all the user facing strings in your manifest. These files must adhere to the [Localization file JSON schema](../../resources/schem) and they must be added to the `localizationInfo` property of your manifest. Each file correlates to a language tag, which the Teams client uses to select the appropriate strings. The language tag takes the form of `<language>-<region>` but you can omit the `<region>` portion to target all regions that support the desired language.
+
+The Teams client applies the strings in the following order:
+default language strings -> user's language only strings -> user's language + user's region strings.
-For example, you provide a default language of 'fr' (French, all regions), and additional language files for 'en' (English, all regions) and 'en-gb' (English, Great Britain). If the user's language is set to 'en-gb':
+For example, you provide a default language of 'fr' (French, all regions), and additional language files for 'en' (English, all regions) and 'en-gb' (English, Great Britain), the user's language is set to 'en-gb'. The following changes take place based on the language selection:
-1. The Teams client will take the 'fr' strings overwrite them with the 'en' strings.
-2. Overwrite those with the 'en-gb' strings.
+1. The Teams client takes the 'fr' strings and overwrite them with the 'en' strings.
+1. Overwrite the 'en' strings with the 'en-gb' strings.
-If the user's language is set to 'en-ca':
+If the user's language is set to 'en-ca', the following changes take place based on the language selection:
-1. The Teams client will take the 'fr' strings overwrite them with the 'en' strings.
-2. Since no 'en-ca' localization is supplied, the 'en' localizations will be used.
+1. The Teams client takes the 'fr' strings and overwrite them with the 'en' strings.
+1. Since no 'en-ca' localization is supplied, the 'en` localizations are used.
-If the user's language is set to 'es-es', the Teams client will take the 'fr' strings and will not override them with any of the language files.
+If the user's language is set to 'es-es', the Teams client takes the 'fr' strings. The Teams client does not override the strings with any of the language files as no 'es' or 'es-es' translation is provided.
-Therefore, it is strongly recommended to provide top-level, language-only translations in your manifest ('en' instead of 'en-us') and only provide region-level overrides for the few strings that need them.
+Therefore, you must provide top level, language only translations in your manifest. For example, 'en' instead of 'en-us'. You must provide region level overrides only for the few strings that need them.
### Example manifest.json change
+The manifest.json change is shown in the following example:
+ ```json { ...
Therefore, it is strongly recommended to provide top-level, language-only transl
### Example localization .json file
+ The localization.json change is shown in the following example:
+ ```json { "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.8/MicrosoftTeams.Localization.schema.json",
Therefore, it is strongly recommended to provide top-level, language-only transl
} ```
-## Handling localized text submissions from your users
+## Handle localized text submissions from your users
-If your provide localized versions of your application it is very likely that your users will respond with the same language. Teams does not translate the user submissions back to the default language, so your app will need to handle that. For example, if you provide a localized `commandList`, the responses to your bot will be the localized text of the command, not the default language. Your app will need to respond appropriately.
+If your provide localized versions of your application, the users respond with the same language. As Teams does not translate the user submissions back to the default language, your app must handle the localized language responses. For example, if you provide a localized `commandList`, the responses to your bot are the localized text of the command, not the default language. Your app must respond appropriately.
## Code sample
If your provide localized versions of your application it is very likely that yo
|-|-||| | App Localization | Microsoft Teams app localization using bot and tab. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-localization/csharp) |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-localization/nodejs) | -
platform App Structure https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/concepts/design/app-structure.md
When building your app, it's important to know what you can and can't customize
The following wireframes show you:
-* The surfaces you can customize in each Teams app capability (outlined in blue).
+* The surfaces you can customize in each Teams app capability (outlined in pink).
* The scopes each capability supports.
-> [!NOTE]
+> [!TIP]
> **What does scope mean?** A scope is an area in Teams where people can use your app. Apps can have one or many scopes, including personal, channels, chats, and meetings. ## Personal apps
-Personal apps provide a large canvas to host your app content for individual users. The canvas is an iframe so you can completely customize the experience.
+Personal apps provide a large canvas to host your app content for individual users.
***Supported scopes**: Personal*
+# [Desktop](#tab/desktop)
+
+The canvas is an iframe so you can completely customize the experience.
++
+# [Mobile](#tab/mobile)
+
+The canvas is a webview so you can completely customize the experience.
+++ ## Tabs
-Tabs provide a large canvas to host your app content for a group of users. You can include tabs in shared spaces such as channels, chats, and meeting invites. The canvas is an iframe so you can completely customize the experience.
+Tabs provide a large canvas to host your app content for a group of users. You can include tabs in shared spaces such as channels, chats, and meeting invites.
***Supported scopes**: Channels, Chats, Meetings*
+# [Desktop](#tab/desktop)
+
+The canvas is an iframe so you can completely customize the experience.
++
+# [Mobile](#tab/mobile)
+
+The canvas is a webview so you can completely customize the experience.
+++ ## Bots
Bots are conversational apps that integrate with Teams native messaging features
***Supported scopes**: Personal, Channels, Chats, Meetings*
+# [Desktop](#tab/desktop)
++
+# [Mobile](#tab/mobile)
+++ ## Messaging extensions
Messaging extensions are shortcuts for inserting app content or acting on a mess
***Supported scopes**: Personal, Channels, Chats, Meetings*
+# [Desktop](#tab/desktop)
++
+# [Mobile](#tab/mobile)
+++ ## Meeting extensions
-Meeting extensions are apps to enhance live meetings. You can host your app content in several scenarios, including before, during, and after meetings. The surface is an iframe, allowing you to customize the experience, but keep in mind that these apps are dark themed and narrow during meetings.
+Meeting extensions are apps to enhance live meetings. You can host your app content in several scenarios, including before, during, and after meetings.
***Supported scopes**: Meetings, Chats*
+# [Desktop](#tab/desktop)
+
+The surface is an iframe, allowing you to customize the experience, but keep in mind that during meetings these apps use dark theme and are narrow.
++
+# [Mobile](#tab/mobile)
+
+The surface is a webview, allowing you to customize the experience, but keep in mind that during meetings these apps use dark theme.
+++
platform Import External Messages To Teams https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/graph-api/import-messages/import-external-messages-to-teams.md
keywords: teams import messages api graph microsoft migrate migration post
With Microsoft Graph, you can migrate users' existing message history and data from an external system into a Teams channel. By enabling the recreation of a third-party platform messaging hierarchy inside Teams, users can continue their communications in a seamless manner and proceed without interruption.
-> [!NOTE]
+> [!NOTE]
> In the future, Microsoft may require you or your customers to pay additional fees based on the amount of data imported. ## Import overview At a high level, the import process consists of the following:
-1. [Create a team with a back-in-time timestamp](#step-one-create-a-team)
-1. [Create a channel with a back-in-time timestamp](#step-two-create-a-channel)
-1. [Import external back-in-time dated messages](#step-three-import-messages)
-1. [Complete the team and channel migration process](#step-four-complete-migration-mode)
-1. [Add team members](#step-five-add-team-members)
+1. [Create a team with a back-in-time timestamp](#step-1-create-a-team).
+1. [Create a channel with a back-in-time timestamp](#step-2-create-a-channel).
+1. [Import external back-in-time dated messages](#step-3-import-messages).
+1. [Complete the team and channel migration process](#step-4-complete-migration-mode).
+1. [Add team members](#step-five-add-team-members).
-## Necessary requirements
+## Prerequisites
### Analyze and prepare message data
-Γ£ö Review the third-party data to decide what will be migrated.
-Γ£ö Extract the selected data from the third-party chat system.
-Γ£ö Map the third-party chat structure to the Teams structure.
-Γ£ö Convert import data into format needed for migration.
+* Review the third-party data to decide what will be migrated.
+* Extract the selected data from the third-party chat system.
+* Map the third-party chat structure to the Teams structure.
+* Convert import data into format needed for migration.
### Set up your Office 365 tenant
-Γ£ö Ensure that an Office 365 tenant exists for the import data. For more information on setting up an Office 365 tenancy for Teams, see [Prepare your Office 365 tenant](../../concepts/build-and-test/prepare-your-o365-tenant.md).
-Γ£ö Make sure that team members are in Azure Active Directory (AAD). For more information, see [Add a new user](/azure/active-directory/fundamentals/add-users-azure-active-directory) to Azure Active Directory.
+* Ensure that an Office 365 tenant exists for the import data. For more information on setting up an Office 365 tenancy for Teams, see [prepare your Office 365 tenant](../../concepts/build-and-test/prepare-your-o365-tenant.md).
+* Make sure that team members are in Azure Active Directory (AAD). For more information, see [add a new user](/azure/active-directory/fundamentals/add-users-azure-active-directory) to AAD.
-## Step One: Create a team
+## Step 1: Create a team
-Since existing data is being migrated, maintaining the original message timestamps and preventing messaging activity during the migration process are key to recreating the user's existing message flow in Teams. This is achieved as follows:
+Since you are migrating existing data, maintaining the original message timestamps and preventing messaging activity during the migration process are key to recreating the user's existing message flow in Teams. This is achieved as follows:
-> [Create a new team](/graph/api/team-post?view=graph-rest-beta&tabs=http&preserve-view=true) with a back-in-time timestamp using the team resource `createdDateTime` property. Place the new team in `migration mode`, a special state that bars users from most activities within the team until the migration process is complete. Include the `teamCreationMode` instance attribute with the `migration` value in the POST request to explicitly identify the new team as being created for migration.
+> [Create a new team](/graph/api/team-post?view=graph-rest-beta&tabs=http&preserve-view=true) with a back-in-time timestamp using the team resource `createdDateTime` property. Place the new team in `migration mode`, a special state that restricts users from most activities within the team until the migration process is complete. Include the `teamCreationMode` instance attribute with the `migration` value in the POST request to explicitly identify the new team as being created for migration.
-> [!Note]
+> [!NOTE]
> The `createdDateTime` field will only be populated for instances of a team or channel that have been migrated. <!-- markdownlint-disable MD001 -->
-#### Permissions
+#### Permission
|ScopeName|DisplayName|Description|Type|Admin Consent?|Entities/APIs covered| |-|-|-|-|-|-|
-|`Teamwork.Migrate.All`|Manage migration to Microsoft Teams|Creating, managing resources for migration to Microsoft Teams.|**Application-only**|**Yes**|`POST /teams`|
+|`Teamwork.Migrate.All`|Manage migration to Microsoft Teams|Creating and managing resources for migration to Microsoft Teams.|**Application-only**|**Yes**|`POST /teams`|
#### Request (create a team in migration state)
Location: /teams/{team-id}/operations/{operation-id}
Content-Location: /teams/{team-id} ```
-#### Error messages
+#### Error message
```http 400 Bad Request ```
-* `createdDateTime` set for future.
-* `createdDateTime` correctly specified, but `teamCreationMode` instance attribute is missing or set to invalid value.
+You can receive the error message in the following scenarios:
+
+* If `createdDateTime` is set for future.
+* If `createdDateTime` is correctly specified, but `teamCreationMode` instance attribute is missing or set to invalid value.
-## Step Two: Create a channel
+## Step 2: Create a channel
Creating a channel for the imported messages is similar to the create team scenario:
-> [Create a new channel](/graph/api/channel-post?view=graph-rest-v1.0&tabs=http&preserve-view=true) with a back-in-time timestamp using the channel resource `createdDateTime` property. Place the new channel in `migration mode`, a special state that bars users from most chat activities within the channel until the migration process is complete. Include the `channelCreationMode` instance attribute with the `migration` value in the POST request to explicitly identify the new team as being created for migration.
+> [Create a new channel](/graph/api/channel-post?view=graph-rest-v1.0&tabs=http&preserve-view=true) with a back-in-time timestamp using the channel resource `createdDateTime` property. Place the new channel in `migration mode`, a special state that restricts users from most chat activities within the channel until the migration process is complete. Include the `channelCreationMode` instance attribute with the `migration` value in the POST request to explicitly identify the new team as being created for migration.
<!-- markdownlint-disable MD024 -->
-#### Permissions
+#### Permission
|ScopeName|DisplayName|Description|Type|Admin Consent?|Entities/APIs covered| |-|-|-|-|-|-|
-|`Teamwork.Migrate.All`|Manage migration to Microsoft Teams|Creating, managing resources for migration to Microsoft Teams.|**Application-only**|**Yes**|`POST /teams`|
+|`Teamwork.Migrate.All`|Manage migration to Microsoft Teams|Creating and managing resources for migration to Microsoft Teams.|**Application-only**|**Yes**|`POST /teams`|
#### Request (create a channel in migration state)
HTTP/1.1 202 Accepted
```http 400 Bad Request ```
+You can receive the error message in the following scenarios:
-* `createdDateTime` set for future.
-* `createdDateTime` correctly specified but `channelCreationMode` instance attribute is missing or set to invalid value.
+* If `createdDateTime` is set for future.
+* If `createdDateTime` is correctly specified but `channelCreationMode` instance attribute is missing or set to invalid value.
-## Step Three: Import messages
+## Step 3: Import messages
-After the team and channel have been created, you can begin sending back-in-time messages using the `createdDateTime` and `from` keys in the request body. **NOTE**: messages imported with `createdDateTime` earlier than the message thread `createdDateTime` is not supported.
+After the team and channel have been created, you can begin sending back-in-time messages using the `createdDateTime` and `from` keys in the request body.
> [!NOTE]
+> * Messages imported with `createdDateTime` earlier than the message thread `createdDateTime` is not supported.
> * `createdDateTime` must be unique across messages in the same thread. > * `createdDateTime` supports timestamps with milliseconds precision. For example, if the incoming request message has the value of `createdDateTime` set as *2020-09-16T05:50:31.0025302Z*, then it would be converted to *2020-09-16T05:50:31.002Z* when the message is ingested.
HTTP/1.1 200 OK
} ```
-#### Error messages
+#### Error message
```http 400 Bad Request
HTTP/1.1 200 OK
#### Request (POST a message with inline image)
-> [!Note]
-> There are no special permission scopes in this scenario since the request is part of chatMessage; scopes for chatMessage apply here as well.
+> [!NOTE]
+> * There are no special permission scopes in this scenario since the request is part of `chatMessage`.
+> * The scopes for `chatMessage` apply here.
```http POST https://graph.microsoft.com/v1.0/teams/team-id/channels/channel-id/messages
HTTP/1.1 200 OK
} ```
-## Step Four: Complete migration mode
+## Step 4: Complete migration mode
-Once the message migration process has completed, both the team and channel are taken out of migration mode using the `completeMigration` method. This step opens the team and channel resources for general use by team members. The action is bound to the `team` instance. All channels must be completed out of migration mode before the team can be completed.
+After the message migration process has completed, both the team and channel are taken out of migration mode using the `completeMigration` method. This step opens the team and channel resources for general use by team members. The action is bound to the `team` instance. Before the team completes, all channels must be completed out of migration mode.
#### Request (end channel migration mode)
POST https://graph.microsoft.com/v1.0/teams/team-id/completeMigration
HTTP/1.1 204 NoContent ```
-* Action called on a `team` or `channel` that is not in `migrationMode`.
+Action called on a `team` or `channel` that is not in `migrationMode`.
-## Step Five: Add team members
+## Step five: Add team members
-You can add a member to a team [using the Teams UI](https://support.microsoft.com/office/add-members-to-a-team-in-teams-aff2249d-b456-4bc3-81e7-52327b6b38e9) or Microsoft Graph [Add member](/graph/api/group-post-members?view=graph-rest-beta&tabs=http&preserve-view=true) API:
+You can add a member to a team [using the Teams UI](https://support.microsoft.com/office/add-members-to-a-team-in-teams-aff2249d-b456-4bc3-81e7-52327b6b38e9) or Microsoft Graph [add member](/graph/api/group-post-members?view=graph-rest-beta&tabs=http&preserve-view=true) API:
#### Request (add member)
HTTP/1.1 204 No Content
<!-- markdownlint-disable MD001 --> <!-- markdownlint-disable MD026 -->
-* Once the `completeMigration` request is made, you cannot import further messages into the team.
+* After the `completeMigration` request is made, you cannot import further messages into the team.
-* Team members can only be added to the new team after the `completeMigration` request has returned a successful response.
+* You can only add team members to the new team after the `completeMigration` request has returned a successful response.
-* Throttling: Messages import at 5 RPS per channel.
+* Throttling: Messages import at five RPS per channel.
-* If you need to make a correction to the migration results, you need to delete the team and repeat the steps to create the team and channel and re-migrate the messages.
+* If you need to make a correction to the migration results, you must delete the team and repeat the steps to create the team and channel and re-migrate the messages.
> [!NOTE] > Currently, inline images are the only type of media supported by the import message API schema. ##### Import content scope
+The following table provides the content scope:
+ |In-scope | Currently out-of-scope| |-|--| |Team and channel messages|1:1 and group chat messages| |Created time of the original message|Private channels| |Inline images as part of the message|At mentions|
-|Links to existing files in SPO/OneDrive|Reactions|
+|Links to existing files in SPO or OneDrive|Reactions|
|Messages with rich text|Videos| |Message reply chain|Announcements| |High throughput processing|Code snippets|
HTTP/1.1 204 No Content
## See also
-[Learn more about Microsoft Graph and Teams integration](/graph/teams-concept-overview)
+[Microsoft Graph and Teams integration](/graph/teams-concept-overview)
platform Dotnet Ngrok Intro https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/dotnet-ngrok-intro.md
## Establish a secure tunnel to your tab
-Microsoft Teams is an entirely cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams doesn't allow local hosting. You'll need to either publish your tab to a public URL, or use a proxy that will expose your local port to an internet-facing URL.
+Microsoft Teams is a cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams does not allow local hosting. You must either publish your tab to a public URL, or use a proxy that exposes your local port to an internet-facing URL.
-To test your tab you'll use [ngrok](https://ngrok.com/docs). Your server's web endpoints will be available while ngrok is running on your local machine. If you close ngrok, the URLs will be different the next time you start it.
+To test your tab, use [ngrok](https://ngrok.com/docs). Your server's web endpoints are available while ngrok is running on your computer. In the free version of ngrok, if you close ngrok, the URLs are different the next time you start it.
platform Dotnet Personal Use Appstudio https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/dotnet-personal-use-appstudio.md
-## Upload your tab to Teams with App Studio
+## Upload your tab with App Studio
>[!NOTE]
-> We use App Studio to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit **manifest.json** if you prefer. If you do, be sure to build the solution again to create the **Tab.zip** file to upload.
+> We use **App Studio** to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit **manifest.json**. If you do, ensure that you build the solution again to create the **Tab.zip** file to upload.
-- Open the Microsoft Teams client. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+**To upload your tab with App Studio**
-- Open App studio and select the **Manifest editor** tab.
+1. Go to Microsoft Teams. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
-- Select the **Import an existing app** tile in the Manifest editor to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It should be found here:
+1. Go to **App Studio** and select the **Manifest editor** tab.
+
+1. Select **Import an existing app** in the **Manifest editor** to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It is available from the following path:
```bash
- /bin/Debug/netcoreapp2.2/Tab.zip
+ /bin/Debug/netcoreapp2.2/tab.zip
``` -- Upload **Tab.zip** to App Studio.
+1. Upload **tab.zip** to **App Studio**.
### Update your app package with Manifest editor
-Once you've uploaded your app package into App Studio, you'll need to finish configuring it.
+After you have uploaded your app package into App Studio, you must configure it.
-- Select the tile for your newly imported tab in the right panel of the Manifest editor welcome page.
+Select the tile for your newly imported tab in the right panel of the Manifest editor welcome page.
-There's a list of steps in the left-hand side of the Manifest editor, and on the right, a list of properties that need to have values for each of those steps. Much of the information has been provided by your *manifest.json* but there are a few fields that you'll need to update:
+There is a list of steps in the left-hand side of the Manifest editor, and on the right, a list of properties that must have values for each of those steps. Much of the information has been provided by your **manifest.json** but there are fields that you must update.
#### Details: App details In the **App details** section: -- Under **Identification** select **Generate** to generate a new App Id for your app.
+1. Under **Identification**, select **Generate** to generate a new App Id for your app.
-- Under **Developer information** update the **Website URL** with your **ngrok** HTTPS URL.
+1. Under **Developer information**, update the **Website** with your **ngrok** HTTPS URL.
-- Under **App URLs** update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
+1. Under **App URLs**, update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
#### Capabilities: Tabs
-In the *Tabs* section:
+In the **Tabs** section:
-- Under **Add a personal tab** select **Add**. You will be presented with a pop-up dialogue window.
+1. Under **Add a personal tab**, select **Add**. A pop-up dialog box appears.
-- Complete the **Name** field.
+1. Enter a name for the personal tab in **Name**.
-- Complete the **Entity Id** field.
+1. Enter the **Entity ID**.
-- Update the **Content URL** field with to `https://<yourngrokurl>/personalTab`.
+1. Update **Content URL** with `https://<yourngrokurl>/personalTab`.
-- Leave the **Website URL** field blank.
+ Leave the **Website URL** field blank.
-- Select **Save**.
+1. Select **Save**.
#### Finish: Domains and permissions
-In the **Domains and permissions** section, the **Domains from your tabs** field should contain your ngrok URL without the HTTPS prefix - `<yourngrokurl>.ngrok.io/`.
+In the **Domains and permissions** section, the **Domains from your tabs** field must contain your ngrok URL without the HTTPS prefix `<yourngrokurl>.ngrok.io/`.
##### Finish: Test and distribute >[!IMPORTANT]
->In the **Description** field on the right you'll see the following warning:
+> On the right, in **Description**, you see the following warning:
>
->&#9888; "**The 'validDomains' array cannot contain a tunneling site...**"
+> &#9888; **The 'validDomains' array cannot contain a tunneling site...**
> >This warning can be ignored while testing your tab.
-In the **Test and distribute** section:
--- Select **Install**.--- In the pop-up window make sure that **Add for you** is set to **Yes** and **Add to a team or chat** is set to **No**.
+1. In the **Test and Distribute** section, select **Install**.
-- Select **Install**.
+1. In the pop-up dialog box, select **Add** and your tab is displayed with two options.
-- In the next pop-up window select **Open** and your tab will be displayed.
+1. From the options in the tab, choose either **Select Gray** or **Select Red**. The tab is displayed according to the color you selected.
+
+ ![Personal tab ASPNETMVC uploaded](../../assets/images/tab-images/personaltabaspnetmvcuploaded.png)
## View your personal tab -- In the navigation bar located at the far-left of the Teams App, select the `...` menu. You'll be presented with a list of personal apps.
+1. In the navigation bar located at the far left of the Teams app, select the ellipses &#x25CF;&#x25CF;&#x25CF;. A list of personal apps is shown.
-- Select your tab from the list to view.
+1. Select your tab from the list to view it.
platform Dotnet Update Chan Grp App https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/dotnet-update-chan-grp-app.md
For your tab to display in Teams, you must include the **Microsoft Teams JavaScript client SDK** and include a call to `microsoftTeams.initialize()` after your page loads. This is how your tab and the Teams client communicate: -- Navigate to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tag:
+Go to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tag:
- ```html
- <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
- <script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>
- ```
+```html
+<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
+<script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>
+```
>[!IMPORTANT]
->Don't copy/paste the `<script src="...">` URLs from this page, as they may not represent the latest version. To get the latest version of the SDK, always go to: [Microsoft Teams JavaScript API](https://www.npmjs.com/package/@microsoft/teams-js).
+> Do not copy and paste the `<script src="...">` URLs from this page, as they may not represent the latest version. To get the latest version of the SDK, always go to [Microsoft Teams JavaScript API](https://www.npmjs.com/package/@microsoft/teams-js).
### Tab.cshtml
-Open **Tab.cshtml** and update the embedded `<script>` as follows:
+**To update the embedded script**
-- At the top of the script, call `microsoftTeams.initialize()`.
+1. In Visual Studio, open **Tab.cshtml** to update the embedded `<script>`.
-- Update the `websiteUrl` and `contentUrl` values in each function with the HTTPS ngrok URL to your tab.
+1. At the top of the script, call `microsoftTeams.initialize()`.
-Your code should now look like the following with **y8rCgT2b** replaced with your ngrok URL:
+1. Update the `websiteUrl` and `contentUrl` values in each function with the HTTPS ngrok URL to your tab.
-```javascript
- microsoftTeams.initialize();
+ Your code should now look like the following with **y8rCgT2b** replaced with your ngrok URL:
- let saveGray = () => {
- microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
- microsoftTeams.settings.setSettings({
- websiteUrl: `https://y8rCgT2b.ngrok.io`,
- contentUrl: `https://y8rCgT2b.ngrok.io/gray/`,
- entityId: "grayIconTab",
- suggestedDisplayName: "MyNewTab"
+ ```javascript
+ microsoftTeams.initialize();
+
+ let saveGray = () => {
+ microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
+ microsoftTeams.settings.setSettings({
+ websiteUrl: `https://y8rCgT2b.ngrok.io`,
+ contentUrl: `https://y8rCgT2b.ngrok.io/gray/`,
+ entityId: "grayIconTab",
+ suggestedDisplayName: "MyNewTab"
+ });
+ saveEvent.notifySuccess();
});
- saveEvent.notifySuccess();
- });
- }
-
- let saveRed = () => {
- microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
- microsoftTeams.settings.setSettings({
- websiteUrl: `https://y8rCgT2b.ngrok.io`,
- contentUrl: `https://y8rCgT2b.ngrok.io/red/`,
- entityId: "redIconTab",
- suggestedDisplayName: "MyNewTab"
+ }
+
+ let saveRed = () => {
+ microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
+ microsoftTeams.settings.setSettings({
+ websiteUrl: `https://y8rCgT2b.ngrok.io`,
+ contentUrl: `https://y8rCgT2b.ngrok.io/red/`,
+ entityId: "redIconTab",
+ suggestedDisplayName: "MyNewTab"
+ });
+ saveEvent.notifySuccess();
});
- saveEvent.notifySuccess();
- });
- }
-```
+ }
+ ```
-Make sure to save the updated **Tab.cshtml**.
+1. Make sure to save the updated **Tab.cshtml**.
## Build and run your application -- In Visual Studio press **F5**, or choose **Start Debugging** from the **Debug** menu. Verify that **ngrok** is running and working properly by opening your browser and going to your content page via the ngrok HTTPS URL that was provided in your command prompt window.
+In Visual Studio, press **F5** or choose **Start Debugging** from the **Debug** menu. Verify that **ngrok** is running and working properly by opening your browser and going to your content page via the ngrok HTTPS URL that was provided in your command prompt window.
->[!TIP]
->You need to have both your application in Visual Studio and ngrok running to complete this quickstart. If you need to stop running your application in Visual Studio to work on it **keep ngrok running**. It will continue to listen and will resume routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service it will return a new URL and you'll have to update your application with the new URL.
+> [!TIP]
+> You need to have both your application in Visual Studio and ngrok running. If you need to stop running your application in Visual Studio to work on it **keep ngrok running**. It will continue to listen and will resume routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service, it will return a new URL and you will have to update your application with the new URL.
-## Upload your tab to Teams
+## Upload your tab
>[!Note]
-> We use App Studio to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit the **manifest.json** file if you prefer. If you do, be sure to build the solution again to create the **tab.zip** file to upload.
+> App Studio can be used to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit the **manifest.json** file if you prefer. If you do, be sure to build the solution again to create the **tab.zip** file to upload.
-- Open the Microsoft Teams client. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+**To upload your tab**
-- Open App studio and select the **Manifest editor** tab.
+1. Go to Microsoft Teams. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
-- Select the **Import an existing app** tile in the Manifest editor to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It should be found here:
+1. Go to **App Studio** and select the **Manifest editor** tab.
+
+1. Select **Import an existing app** in the Manifest editor to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It is available here:
```bash /bin/Debug/netcoreapp2.2/tab.zip ``` -- Upload **tab.zip** to App Studio.
+1. Upload **tab.zip** to App Studio.
### Update your app package with Manifest editor
-Once you've uploaded your app package into App Studio, you'll need to finish configuring it.
+After you have uploaded your app package into App Studio, you must finish configuring it.
-- Select the tile for your newly imported tab in the right panel of the Manifest editor welcome page.
+Select the tile for your newly imported tab in the right panel of the Manifest editor welcome page.
-There's a list of steps in the left-hand side of the Manifest editor, and on the right, a list of properties that need to have values for each of those steps. Much of the information has been provided by your *manifest.json* but there are a few fields that you'll need to update:
+There is a list of steps in the left-hand side of the Manifest editor, and on the right, a list of properties that must have values for each of those steps. Much of the information has been provided by your **manifest.json** but there are a few fields that you must update:
#### Details: App details
-In the *App details* section:
+In the **App details** section:
-- *Identification*: select **Generate** to replace the placeholder id with the required GUID for your tab.
+1. Under **Identification**, select **Generate** to replace the placeholder ID with the required GUID for your tab.
-- *Developer information*: update the **Website URL** field with your *ngrok* HTTPS URL.
+1. Under **Developer information**, update **Website** with your **ngrok** HTTPS URL.
-- *App URLs*: update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
+1. Under **App URLs**, update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
#### Capabilities: Tabs
-In the *Tabs* section:
+In the **Tabs** section:
-- *Team Tab*: select **Add**.
+1. Under **Team tab**, select **Add**.
-- In the Team tab pop-up window update the *Configuration URL* to `https://<yourngrokurl>/tab`.
+1. In the **Team tab** pop-up window, update the **Configuration URL** to `https://<yourngrokurl>/tab`.
-- Finally, make sure the *can update configuration? Team*, and *Group chat* boxes are checked and select **Save**.
+1. Ensure the **Can update configuration?**, **Team**, and **Group chat** checkboxes are selected and select **Save**.
#### Finish: Domains and permissions
-In the *Domains and permissions* section:
--- The *Domains from your tabs* field should contain your ngrok URL without the HTTPS prefix - `<yourngrokurl>.ngrok.io/`.
+In the **Domains and permissions** section, **Domains from your tabs** must contain your ngrok URL without the HTTPS prefix `<yourngrokurl>.ngrok.io/`.
#### Finish: Test and distribute >[!IMPORTANT]
->In the **Description** field on the right you'll see the following warning:
+> On the right, in **Description**, you see the following warning:
>
->&#9888; "**The 'validDomains' array cannot contain a tunneling site...**"
+> &#9888; "**The 'validDomains' array cannot contain a tunneling site...**"
>
->This warning can be ignored while testing your tab.
+> This warning can be ignored while testing your tab.
+
+1. In the **Test and Distribute** section, select **Install**.
-In the *Test and distribute* section:
+1. In the pop-up dialog box, select **Add to a team** or from the drop-down, select **Add to a chat**.
-- Select **Install**.
+1. Choose the team or chat where you want the tab to be displayed and select **Set up a tab**.
-- In the pop-up window's *Add to a team or chat* field enter your team and select **Install**.
+1. In the next pop-up dialog box, choose either **Select Gray** or **Select Red**, and select **Save**.
-- In the next pop-up window choose the team channel where you would like the tab displayed and select **Set up**.
+1. To view your tab, go to the team where you installed the tab, and select it from the tab bar. The page that you chose during configuration is displayed.
-- In the final pop-up window select a value for the tab page (either a red or gray icon) and select **Save**.
+ ![Channel tab ASPNETMVC uploaded](../../assets/images/tab-images/channeltabaspnetmvcuploaded.png)
-To view your tab, navigate to the team you installed it on, and select it from the tab bar. The page that you chose during configuration should be displayed.
platform Dotnet Update Personal App https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/dotnet-update-personal-app.md
For your tab to display in Teams, you must include the **Microsoft Teams JavaScript client SDK** and include a call to `microsoftTeams.initialize()` after your page loads. This is how your tab and the Teams app communicate: -- Navigate to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tags section:
+Go to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tags section:
- ```html
- `<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>`
- `<script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>`
- ```
+```html
+<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
+<script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>
+```
### PersonalTab.cshtml Open **PersonalTab.cshtml** and update the embedded `<script>` tags by calling `microsoftTeams.initialize()`.
-Make sure to save your updated **PersonalTab.cshtml**.
+Ensure you save your updated **PersonalTab.cshtml** file.
platform Node Js Yeoman Gulp Tasks https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/node-js-yeoman-gulp-tasks.md
-## Create the app package
+#### Create the app package
-You'll need an app package to test your tab in Teams. It's a zip folder that contains the following required files:
+You must have an app package to test your tab in Teams. It is a zip folder that contains the following required files:
- A **full color icon** measuring 192 x 192 pixels. - A **transparent outline icon** measuring 32 x 32 pixels. - A **manifest.json** file that specifies the attributes of your app.
-The package is created via a gulp task that validates the manifest.json file and generates the zip folder in the `./package directory`. In the command prompt enter:
+The package is created through a gulp task that validates the manifest.json file and generates the zip folder in the **./package directory**. In the command prompt, enter the following command:
```bash gulp manifest ```
-## Build your application
+#### Build your application
-The build command transpiles your solution into the *./dist* folder. Next,enter:
+The build command transpiles your solution into the **./dist** folder. Enter the following command in the command prompt:
```bash gulp build ```
-## Run your application in localhost
+#### Run your application in localhost
-Start a local web server by entering the following:
+1. Start a local web server by entering the following in the command prompt:
-```bash
-gulp serve
-```
+ ```bash
+ gulp serve
+ ```
-Enter `http://localhost:3007/<yourDefaultAppNameTab>/` in your browser and view your application's home page:
+1. Enter `http://localhost:3007/<yourDefaultAppNameTab>/` in your browser, replace **<yourDefaultAppNameTab>** with your tab name, and view your application's home page as shown in the following image:
-![home page screenshot](~/assets/images/tab-images/homePage.png)
+ ![home page screenshot](~/assets/images/tab-images/homePage.png)
platform Node Js Yeoman Prereq https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/includes/tabs/node-js-yeoman-prereq.md
-## Prerequisites
+## Prerequisites for apps
-- To complete this quickstart you will need an Office 365 tenant and a team configured with *Allow uploading custom apps* enabled. To learn more, see [Prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+You must have an understanding of the following prerequisites:
- - If you don't currently have an Office 365 account, you can sign up for a free subscription through the Office 365 Developer Program. The subscription will remain active as long as you're using it for ongoing development. See [Welcome to the Office 365 Developer Program](/office/developer-program/microsoft-365-developer-program).
+- You must have an Office 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ - If you do not currently have an Office 365 account, you can sign up for a free subscription through the Office 365 Developer Program. The subscription remains active as long as you are using it for ongoing development. See [welcome to the Office 365 Developer Program](/office/developer-program/microsoft-365-developer-program).
In addition, this project requires that you have the following installed in your development environment: - Any text editor or IDE. You can install and use [Visual Studio Code](https://code.visualstudio.com/download) for free. -- [Node.js/npm](https://nodejs.org/en/). You should use the latest LTS version. The Node Package Manager (npm) will install into your system with the installation of Node.js.
+- [Node.js/npm](https://nodejs.org/en/). Use the latest LTS version. The Node Package Manager (npm) installs in your system with the installation of Node.js.
-- After you've successfully installed Node.js, install the [Yeoman](https://yeoman.io/) and [gulp-cli](https://www.npmjs.com/package/gulp-cli) packages by typing the following in your command prompt:
+- After you have successfully installed Node.js, install the [Yeoman](https://yeoman.io/) and [gulp-cli](https://www.npmjs.com/package/gulp-cli) packages by typing the following in your command prompt:
```bash npm install yo gulp-cli --global
In addition, this project requires that you have the following installed in your
## Generate your project -- Open a command prompt and create a new directory for your tab project.
+**To generate your project**
+
+1. Open a command prompt and create a new directory for your tab project.
-- To start the generator, navigate to your new directory and type the following command:
+1. To start the generator, navigate to your new directory and type the following command:
```bash yo teams ``` -- Next, you'll provide a series of values that will be used in your application's **manifest.json** file:
+1. Next, provide a series of values that are used in your application's **manifest.json** file:
![generator opening screenshot](/microsoftteams/platform/assets/images/tab-images/teamsTabScreenshot.PNG)
In addition, this project requires that you have the following installed in your
By default the generator suggests an Azure Web Sites URL. You'll only be testing your app locally, therefore, a valid URL is not necessary to complete this quickstart.
+ **Would you like show a loading indicator when your app/tab loads?**
+
+ Choose **not** to include a loading indicator when your app or tab loads. The default is no, enter **n**.
+
+ **Would you like personal apps to be rendered without a tab header-bar?**
+
+ Choose **not** to include personal apps to be rendered without a tab header-bar. Default is no, enter **n**.
+ **Would you like to include Test framework and initial tests? (y/N)** Choose **not** to include a test framework for this project. The default is yes; enter **n**.
In addition, this project requires that you have the following installed in your
**Default Tab Name (max 16 characters)?**
- Name your tab. This tab name will be used throughout your project as a file/URL path component.
+ Name your tab. This tab name will be used throughout your project as a file or URL path component.
+
platform Create Extensions https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/resources/messaging-extension-v3/create-extensions.md
When a user chooses a command with static parameters, Teams will generate a form
In this method, your service can define a custom adaptive card to collect the end user input. For this approach, set the `fetchTask` parameter to `true` in the manifest. Note that if you set `fetchTask` to `true` any static parameters defined for the command will be ignored.
-In this method your service will receive a `composeExtension/fetchTask` event and needs to respond with an adaptive card based [task module response](~/task-modules-and-cards/what-are-task-modules.md#the-taskinfo-object). Following is a sample response with an adaptive card:
+In this method your service receives a `composeExtension/fetchTask` event and responds with an adaptive card based [task module response](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object). Following is a sample response with an adaptive card:
```json {
The bot can also respond with an auth/config response if the user needs to authe
In this method your service can show an `<iframe>` based widget to show any custom UI and collect user input. For this approach, set the `fetchTask` parameter to `true` in the manifest.
-Just like in the adaptive card flow your service will be send a `fetchTask` event and needs to respond with a URL based [task module response](~/task-modules-and-cards/what-are-task-modules.md#the-taskinfo-object). Following is a sample response with an Adaptive card:
+Just like in the adaptive card flow your service sends a `fetchTask` event and responds with a URL based [task module response](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object). Following is a sample response with an Adaptive card:
```json {
platform Removing Tab Margins https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/resources/removing-tab-margins.md
No, you must provide your own padding or margins to the left and right of all ap
> * All tabs have their margins removed: personal tabs, (group) chat tabs, meeting tabs, and channel tabs. > * There is no way to opt-in or opt-out of this change. It will apply to all tabs. > * This change can affect tabs that rely on Microsoft Teams to provide margins surrounding their UI.+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
platform Samesite Cookie Update https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/resources/samesite-cookie-update.md
Title: Microsoft Teams and the SameSite cookie attribute (2020 update)-
+ Title: SameSite cookie attribute
+ description: describes the attributes of SameSite cookie keywords: cookie attributes samesite
localization_priority: Normal
-# Microsoft Teams and the SameSite cookie attribute (2020 update)
+# SameSite cookie attribute
-## Cookies in brief
+Cookies are text strings, sent from websites, and stored on a computer by the web browser. They are used for authentication and personalization. For example, cookies are used to recall stateful information, preserve user settings, record browsing activity, and display relevant ads. Cookies are always linked to a particular domain and are installed by various parties.
- Cookies are text strings, sent from websites, and stored on a computer by the web browser. They're typically used for authentication and personalization, For example, recalling stateful information, preserving user settings, recording browsing activity, and displaying relevant ads. Cookies are always linked to a particular domain and can be installed by various parties. They are categorized as follows:
+## Types of cookies
- |Cookie|Scope|
- | | |
- |**First-party cookie**|A first-party cookie is created by websites that a user visits and is used to save data such as shopping cart items, login credentials. For example, authentication cookies, and other analytics.|
- |**Second-party cookie**|A second-party cookies is technically the same as a first-party cookie. The difference is that data is shared with a second party via a data partnership agreement. For example, [Microsoft Teams analytics and reporting](/microsoftteams/teams-analytics-and-reports/teams-reporting-reference). |
- |**Third-party cookie**|A third-party cookie is installed by a domain other than the one the user explicitly visited and is mainly used for tracking. For example, "Like" buttons, ad serving, and live chats.|
+The cookie types and their corresponding scopes are as follows:
-### Cookies and HTTP requests
+|Cookie|Scope|
+| | |
+|First party cookie|A first party cookie is created by websites that a user visits. It is used to save data, such as shopping cart items, sign in credentials. For example, authentication cookies, and other analytics.|
+|Second party cookie|A second party cookie is technically the same as a first party cookie. The difference is that data is shared with a second party through a data partnership agreement. For example, [Microsoft Teams analytics and reporting](/microsoftteams/teams-analytics-and-reports/teams-reporting-reference). |
+|Third party cookie|A third party cookie is installed by a domain other than the one the user explicitly visited and is mainly used for tracking. For example, **Like** buttons, ad serving, and live chats.|
-Before the introduction of SameSite restrictions, when cookies were stored on the browser, they were attached to *every* HTTP web request and sent to the server by the Set-Cookie HTTP response header. Predictably, that performance had the potential to introduce security vulnerabilities such as Cross-Site Request Forgery (CSRF) attacks. *See* [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies). The SameSite component mitigated that exposure through its implementation and management in the SetCookie header.
+## Cookies and HTTP requests
-### SameSite attribute: initial release
+Before the introduction of SameSite restrictions, the cookies were stored on the browser. They were attached to every HTTP web request and sent to the server by the `Set Cookie` HTTP response header. This method introduced security vulnerabilities, such as Cross Site Request Forgery, called CSRF attacks. The SameSite component reduced the exposure through its implementation and management in the SetCookie header.
-Google Chrome version 51 introduced the SetCookie SameSite specification as an *optional* attribute. Starting with Build 17672, Windows 10 introduced SameSite cookie support for the [Microsoft Edge browser](https://blogs.windows.com/msedgedev/2018/05/17/samesite-cookies-microsoft-edge-internet-explorer/).
+## SameSite cookie attribute: initial release
-Developers could opt out of adding the SameSite cookie attribute to the SetCookie header or they could add it with one of two settings, *Lax* and *Strict*. An unimplemented SameSite attribute was considered the default state.
+Google Chrome version 51 introduced the `SetCookie SameSite` specification as an optional attribute. Starting with Build 17672, Windows 10 introduced SameSite cookie support for the [Microsoft Edge browser](https://blogs.windows.com/msedgedev/2018/05/17/samesite-cookies-microsoft-edge-internet-explorer/).
+
+You can opt out of adding the SameSite cookie attribute to the `SetCookie` header or add it with one of two settings, **Lax** and **Strict**. An unimplemented SameSite attribute was considered the default state.
## SameSite cookie attribute: 2020 release
-Chrome 80, scheduled for release in February 2020, introduces new cookie values and imposes cookie policies by default. Three values can be passed into the updated SameSite attribute: *Strict*, *Lax*, or *None*. Cookies that don't specify the SameSite attribute will default to `SameSite=Lax`.
+Chrome 80, released in February 2020, introduces new cookie values and imposes cookie policies by default. Three values are passed into the updated SameSite attribute: **Strict**, **Lax**, or **None**. If not specified, cookies SameSite attribute takes the value `SameSite=Lax` by default.
+
+SameSite cookie attributes are as follows:
|Setting | Enforcement | Value |Attribute Specification | | -- | -- | --|--|
-| **Lax** | Cookies will be sent automatically only in a *first-party* context and with HTTP GET requests. SameSite cookies will be withheld on cross-site sub-requests, such as calls to load images or iframes, but will be sent when a user navigates to the URL from an external site, for example, by following a link.| **Default** |`Set-Cookie: key=value; SameSite=Lax`|
-| **Strict** |The browser will only send cookies for first-party context requests (requests originating from the site that set the cookie). If the request originated from a different URL than that of the current location, none of the cookies tagged with the `Strict` attribute will be sent.| Optional |`Set-Cookie: key=value; SameSite=Strict`|
-| **None** | Cookies will be sent in both first-party context and cross-origin requests; however, the value must be explicitly set to **`None`** and all browser requests **must follow the HTTPS protocol** and include the **`Secure`** attribute which requires an encrypted connection. Cookies that don't adhere to that requirement will be **rejected**. <br/>**Both attributes are required together**. If just **`None`** is specified without **`Secure`** or if the HTTPS protocol is not used, the third-party cookie will be rejected.| Optional, but, if set, the HTTPS protocol is required. |`Set-Cookie: key=value; SameSite=None; Secure` |
+| **Lax** | Cookies are sent automatically only in a **first party** context and with HTTP GET requests. SameSite cookies are withheld on cross site sub requests, such as calls to load images or iframes. They sent when a user navigates to the URL from an external site, for example, by following a link.| **Default** |`Set-Cookie: key=value; SameSite=Lax`|
+| **Strict** |The browser only sends cookies for first party context requests. These are requests originating from the site that set the cookie. If the request originated from a different URL than that of the current location, none of the cookies tagged with the `Strict` attribute are sent.| Optional |`Set-Cookie: key=value; SameSite=Strict`|
+| **None** | Cookies are sent in both first party context and cross origin requests; however, the value must be explicitly set to **`None`** and all browser requests **must follow the HTTPS protocol** and include the **`Secure`** attribute which requires an encrypted connection. Cookies that do not adhere to that requirement are **rejected**. <br/>**Both attributes are required together**. If **`None`** is specified without **`Secure`** or if the HTTPS protocol is not used, then the third party cookies are rejected.| Optional, but, if set, the HTTPS protocol is required. |`Set-Cookie: key=value; SameSite=None; Secure` |
## Teams implications and adjustments 1. Enable the relevant SameSite setting for your cookies and validate that your apps and extensions continue to work in Teams. 1. If your apps or extensions fail, make the necessary fixes prior to the Chrome 80 release.
-1. Microsoft internal partners can join the following team if they need more information or help with this issue: <https://teams.microsoft.com/l/team/19%3A08b594cd465e4c0491fb751e823802e2%40thread.skype/conversations?groupId=4d6d04cd-dbf0-43c8-a2ff-f80dd38be034&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47>.
+1. Microsoft internal partners can join the following team for more information or help with this issue: <https://teams.microsoft.com/l/team/19%3A08b594cd465e4c0491fb751e823802e2%40thread.skype/conversations?groupId=4d6d04cd-dbf0-43c8-a2ff-f80dd38be034&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47>.
> [!NOTE]
-> For best practice, it is recommended that you always set SameSite attributes to reflect the intended use for your cookies. Do not rely on default browser behavior. For more information, see [Developers: Get Ready for New SameSite=None; Secure Cookie Settings](https://blog.chromium.org/2019/10/developers-get-ready-for-new.html).
+> You must set SameSite attributes to reflect the intended use for your cookies. Do not rely on default browser behavior. For more information, see [Developers: Get Ready for New SameSite=None; Secure Cookie Settings](https://blog.chromium.org/2019/10/developers-get-ready-for-new.html).
-### Tabs, task modules, and message extensions
+### Tabs, task modules, and messaging extensions
-* Teams tabs use `<iframes>` to embed content that is viewed in a top-level or first-party context.
+* Teams tabs use `<iframes>` to embed content that is viewed in a top level or first party context.
* Task modules allow you to create modal popup experiences in your Teams application. Similar to a tab, a modal window opens inside the current page.
-* Message extensions allow you to insert enriched content into chat message from external resources.
+* Messaging extensions allow you to insert enriched content into a chat message from external resources.
-Any cookies used by embedded content will be considered third-party when the site is displayed in an `<iframe>`. In addition, if any remote resources on a page rely on cookies being sent with a request `<img>` and `<script>` tags, external fonts, and personalized content, you must ensure those are marked for cross-site usage, such as `SameSite=None; Secure` or ensure that a fallback is in place.
+Any cookies used by embedded content are considered as third party when the site is displayed in an `<iframe>`. In addition, if any remote resources on a page rely on cookies being sent with a request `<img>` and `<script>` tags, external fonts, and personalized content, you must ensure those are marked for cross site usage, such as `SameSite=None; Secure` or ensure that a fallback is in place.
### Authentication
-* If you require authentication for embedded content pages in tabs, you'll need to use the web-based authentication flow.
-* A web-based authentication flow can also be used for a configuration page, task module, or messaging extension.
-* You can use a web-based authentication flow for a conversational bot you'll need to use a task module.
+You must use the web based authentication flow for the following:
+
+* Embedded content pages in tabs.
+* Configuration page, task module, and messaging extension.
+* Conversational bot with a task module.
-Pursuant to the updated SameSite restrictions, a browser will not add a cookie to an already authenticated web site if the link derives from an external site. You'll need to ensure your authentication cookies are marked for cross-site usage ΓÇö `SameSite=None; Secure` ΓÇö or ensure that a fallback is in place.
+According to the updated SameSite restrictions, a browser does not add a cookie to an already authenticated web site if the link derives from an external site. You must ensure your authentication cookies are marked for cross site usage `SameSite=None; Secure` or ensure that a fallback is in place.
-### Android System WebView
+## Android System WebView
-Android WebView is a Chrome system component that allows Android apps to display web content. While the new restrictions will become the default, starting with Chrome 80, they will not be immediately enforced on WebViews. They will be applied in the future. To prepare, Android allows native apps to set cookies directly via the [CookeManager API](https://developer.android.com/reference/android/webkit/CookieManager):
+Android WebView is a Chrome system component that allows Android apps to display the web content. While the new restrictions are default, starting with Chrome 80, they are not immediately enforced on WebViews. They will be applied in the future. To prepare, Android allows native apps to set cookies directly through the [CookieManager API](https://developer.android.com/reference/android/webkit/CookieManager).
-* For cookies that are only needed in a first-party context, you should declare them as `SameSite=Lax` or `SameSite=Strict`, as appropriate.
-* For cookies needed in a third-party context, you should ensure that they are declared as `SameSite=None; Secure`.
+> [!NOTE]
+> * You must declare first party cookies as `SameSite=Lax` or `SameSite=Strict`, as appropriate.
+> * You must declare third party cookies as `SameSite=None; Secure`.
## See also
Android WebView is a Chrome system component that allows Android apps to display
* [SameSite cookie recipes](https://web.dev/samesite-cookie-recipes/) * [Known Incompatible Clients]( https://www.chromium.org/updates/same-site/incompatible-clients) * [Developers: Get Ready for New SameSite=None; Secure Cookie Settings](https://blog.chromium.org/2019/10/developers-get-ready-for-new.html)-
-**OpenId Connect impact**<br>
-[Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core](https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/)
+* [Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core](https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/)
+* [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies)
platform Localization Schema https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/resources/schema/localization-schema.md
Title: Localization file JSON schema reference
+ Title: Localize JSON schema reference
description: Describes the localization schema supported by the localization file for Microsoft Teams localization_priority: Normal
keywords: teams manifest schema localization
Last updated 05/20/2019
-# Reference: Localization file JSON schema
+# Localize JSON schema reference
-The Microsoft Teams localization file describes language translations that will be served based on the client language settings. Your file must conform to the schema hosted at [`https://developer.microsoft.com/en-us/json-schemas/teams/v1.8/MicrosoftTeams.Localization.schema.json`](https://developer.microsoft.com/en-us/json-schemas/teams/v1.8/MicrosoftTeams.Localization.schema.json). For additional information see [app localization](~/concepts/build-and-test/apps-localization.md).
+The Microsoft Teams localization file describes language translations that are served based on the client language settings. Your file must conform to the schema hosted at [`https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.Localization.schema.json`](https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.Localization.schema.json).
-## Sample
+> [!TIP]
+> Specify the schema at the beginning of your manifest to enable `IntelliSense` or similar support from your code editor: `"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",`
+
+## Example
+
+Example of localization JSON schema is as follows:
```json {
- "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.8/MicrosoftTeams.schema.json",
+ "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
"name.short": "Le App Studio", "name.full": "App Studio pour Microsoft Teams", "description.short": "Créez d'excellentes applications pour Microsoft Teams avec App Studio.",
The Microsoft Teams localization file describes language translations that will
The schema defines the following properties:
-## $schema
-
-**URI**
-
-The https:// URL referencing the JSON Schema for the manifest.
-
-> [!TIP]
-> Specify the schema at the beginning of your manifest to enable IntelliSense or similar support from your code editor: `"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.8/MicrosoftTeams.schema.json",`
-
-## name.short
-
-**String, Max Length 30**
-
-Replaces the corresponding string from the app manifest with the value provided here.
-
-## name.full
-
-**String, Max Length 100**
-
-Replaces the corresponding string from the app manifest with the value provided here.
-
-## description.short
-
-**String, Max Length 80**
-
-Replaces the corresponding string from the app manifest with the value provided here.
-
-## description.full
-
-**String, Max Length 4000**
-
-Replaces the corresponding string from the app manifest with the value provided here.
-
-## staticTabs\\[([0-9]|1[0-5])\\]\\.name
-
-**String, Max Length 128**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## bots\\[0\\]\\.commandLists\\[[0-2]\\]\\.commands\\[[0-9]\\]\\.title
-
-**String, Max Length 32**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## bots\\[0\\]\\.commandLists\\[[0-2]\\]\\.commands\\[[0-9]\\]\\.description
-
-**String, Max Length 128**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.title
-
-**String, Max Length 32**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.description
-
-**String, Max Length 128**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.title
-
-**String, Max Length 32**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.description
-
-**String, Max Length 128**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.value
-
-**String, Max Length 512**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.choices\\[[0-9]\\]\\.title
-
-**String, Max Length 128**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
-
-## composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.taskInfo\\.title
-
-**String, Max Length 64**
-
-Replaces the corresponding string(s) from the app manifest with the value provided here.
+|Property|Type|Maximum length|Description|
+||--|||
+|`$schema`|URI|NA|The https:// URL referencing the JSON Schema for the manifest.|
+|`name.short`|String|30|Replaces the corresponding string from the app manifest with the value provided here.|
+|`name.full`|String|100|Replaces the corresponding string from the app manifest with the value provided here.|
+|`description.short`|String|80|Replaces the corresponding string from the app manifest with the value provided here.|
+|`description.full`|String|4000|Replaces the corresponding string from the app manifest with the value provided here.|
+|`staticTabs\\[([0-9]|1[0-5])\\]\\.name`|String|128|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`bots\\[0\\]\\.commandLists\\[[0-2]\\]\\.commands\\[[0-9]\\]\\.title`|String|32|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`## bots\\[0\\]\\.commandLists\\[[0-2]\\]\\.commands\\[[0-9]\\]\\.description`|String|128|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.title`|String|32|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.description`|String|128|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.title`|String|32|Replaces the corresponding string from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.description`|String|128|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.value`|String|512|Replaces the corresponding string from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.parameters\\[[0-4]\\]\\.choices\\[[0-9]\\]\\.title`|String|128|Replaces the corresponding strings from the app manifest with the value provided here.|
+|`composeExtensions\\[0\\]\\.commands\\[[0-9]\\]\\.taskInfo\\.title`|String|64|Replaces the corresponding strings from the app manifest with the value provided here.|
+
+## See also
+
+> [Localize your app](~/concepts/build-and-test/apps-localization.md)
platform Teams Contributor Reference https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/resources/teams-contributor-reference.md
Title: Contributing to Microsoft Teams documentation
+ Title: Contribute to Teams documentation
description: steps for creating and publishing Teams documentation
localization_priority: Normal
-# Contributing to Microsoft Teams documentation
+# Contribute to Teams documentation
-[Teams documentation](/microsoftteams/platform/overview) is part of the [Microsoft Docs](https://docs.microsoft.com) technical documentation library. The content is organized into groups called docsets, each representing a group of related documents managed as a single entity. Articles in the same docset have the same URL path extension after *docs<span></span>.microsoft.com*. For example, `/docs.microsoft.com/microsoftteams/...` is the beginning of the Teams docset file path. Teams articles are written in [MarkDown](#markdown-reference) syntax and hosted on [GitHub](https://github.com/MicrosoftDocs/msteams-docs/tree/master/msteams-platform).
+Teams documentation is part of the **Microsoft Docs** technical documentation library. The content is organized into groups called docsets, each representing a group of related documents managed as a single entity. Articles in the same docset have the same URL path extension after **docs.microsoft.com**. For example, `/docs.microsoft.com/microsoftteams/...` is the beginning of the Teams docset file path. Teams articles are written in Markdown syntax and hosted on GitHub.
## Set up your workspace
> [!div class="checklist"] >
-> * Install from within VS Code:
+> * Install within VS Code:
- 1. Select the **Extensions icon** on the side activity bar or use the **View => Extensions** command (Ctrl+Shift+X) and search for the *Docs Authoring Pack* (Microsoft).
- 1. Select the **Install** button.
- 1. Once installation is complete, the **Install** button will change to the **Manage** gear button.
+ 1. Select the **Extensions icon** on the side activity bar or use the **View => Extensions** command or Ctrl+Shift+X and, search for **Microsoft Docs Authoring Pack**.
+ 1. Select **Install**.
+ 1. After installation, the **Install** changes to the **Manage** gear button.
## Review the Microsoft Docs Contributors Guide
-The [contributors guide](/contribute) offers direction for creating, publishing, and updating technical content on the Microsoft Docs platform.
+The contributors guide provides direction to create, publish, and update technical content on the **Microsoft Docs** platform.
## Microsoft Writing, Style, and Content Guides
-* **[Microsoft Writing Style Guide](/style-guide/welcome)**. Consider adding this online guide to your browser's **Favorites** menu. It is a comprehensive resource for today's technical writing and reflects Microsoft's modern approach to voice and style.
+* **[Microsoft Writing Style Guide](/style-guide/welcome)**: Microsoft Writing Style Guide is a comprehensive resource for technical writing and reflects Microsoft's modern approach to voice and style. For easy reference, add this online guide to your browser's **Favorites** menu.
-* **[Writing developer content](/style-guide/developer-content/)**. Teams-specific content is aimed at a developer audience with a fundamental understanding of programming concepts and processes. It is important that you provide clear, technically-accurate information in a compelling manner while maintaining Microsoft's tone and style.
+* **[Writing developer content](/style-guide/developer-content/)**: Teams specific content is aimed at a developer audience with a fundamental understanding of programming concepts and processes. It is important that you must provide clear, technically accurate information in a compelling manner while maintaining Microsoft's tone and style.
-* **[Writing step-by-step instructions](/style-guide/procedures-instructions/writing-step-by-step-instructions)**. Applied and interactive experiences are a great way for developers to learn about Microsoft products and technologies. Presenting complex or simple procedures in a progressive format is natural and user-friendly.
+* **[Writing step-by-step instructions](/style-guide/procedures-instructions/writing-step-by-step-instructions)**: Applied and interactive experiences are a great way for developers to learn about Microsoft products and technologies. Presenting complex or simple procedures in a progressive format is natural and user friendly.
## MarkDown reference
- Microsoft Docs pages are written in MarkDown syntax and parsed through a [Markdig](https://github.com/lunet-io/markdig) engine. Please *see* [Docs Markdown reference](/contribute/markdown-reference) for specific tags and formatting conventions.
+**Microsoft Docs** pages are written in **MarkDown** syntax and parsed through a [Markdig](https://github.com/lunet-io/markdig) engine. For more information on specific tags and formatting conventions, see [Docs Markdown reference](/contribute/markdown-reference).
## File Paths
-Setting a valid file path for hyperlinks in your documentation can be a challenge, especially when using relative paths and creating links to other docsets. Your build won't succeed on GitHub if the file path is incorrect or invalid.
+When using relative paths and creating links to other docsets, it is important to set a valid file path for hyperlinks in your documentation. Your build succeeds on GitHub only if the file path is correct or valid.
+
+For more information on hyperlinks and file paths, see [use links in documentation](/contribute/how-to-write-links).
-For more information on hyperlinks and file paths, see [Use links in documentation](/contribute/how-to-write-links).
-
->[!IMPORTANT]
-> To reference an article that is *part of* the Teams platform docset:<br>
+> [!IMPORTANT]
+> To reference an article that is **part of** the Teams platform docset:<br>
> &emsp;&#x2714; Use a relative path without a leading forward slash.<br> > &emsp;&#x2714; Include the Markdown file extension.<br>
->Ex: **parent directory/directory/path-to-article.md** ΓÇö> `[Building an app for Microsoft Teams](../concepts/building-an-app.md)` <br><br>
-> To reference a Microsoft Docs library article that *is not part of* the Teams platform docset:<br>
+>Ex: **parent directory/directory/path-to-article.md** ΓÇö> [Building an app for Microsoft Teams](../concepts/building-an-app.md) <br><br>
+> To reference a Microsoft Docs library article that **is not part of** the Teams platform docset:<br>
> &emsp;&#x2714; Use a relative path that begins with a forward slash.<br>
-> &emsp;&#x2714; Don't include the file extension. <br>
-> Ex: **/docset/address-to-file-location** ΓÇö> `[Use the Microsoft Graph API to work with Microsoft Teams](/graph/api/resources/teams-api-overview)`<br><br>
+> &emsp;&#x2714; Do not include the file extension. <br>
+> Ex: **/docset/address-to-file-location** ΓÇö> [Use the Microsoft Graph API to work with Microsoft Teams](/graph/api/resources/teams-api-overview)<br><br>
> To reference a page outside of the Microsoft Docs library, such as GitHub, use the full `https` file path.<br> ## Code Samples and Snippets
-Code samples play an important role in helping developers successfully use APIs and SDKs. Well-presented code samples can communicate how things work more clearly than descriptive text and instructional information alone. Your code samples should be accurate, concise, well-documented, and, most importantly, reader-friendly. Code that is easy-to-read is also easy to understand, test, debug, maintain, modify, and extend. For more information, see [How to include code in docs](/contribute/code-in-docs).
+Code samples play an important role to use APIs and SDKs effectively. Well presented code samples can communicate how things work more clearly than descriptive text and instructional information alone. Your code samples must be accurate, concise, well documented, and reader friendly. Code that is easy to read must be easy to understand, test, debug, maintain, modify, and extend. For more information, see [how to include code in docs](/contribute/code-in-docs).
## See also
+* [Microsoft Docs](/)
+* [contributors guide](/contribute)
* [Docs style and voice quick start](/contribute/style-quick-start)
-* [Cutting Edge : Source Code Readability Tips](/archive/msdn-magazine/2014/october/cutting-edge-source-code-readability-tips).
+* [Cutting Edge : Source Code Readability Tips](/archive/msdn-magazine/2014/october/cutting-edge-source-code-readability-tips)
+* [Teams documentation](/microsoftteams/platform/overview)
+* [GitHub](https://github.com/MicrosoftDocs/msteams-docs/tree/master/msteams-platform)
++
+## Next step
> [!div class="nextstepaction"] > [Get Microsoft Docs updates and the latest announcements](/teamblog)
platform Tabs Mobile https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/design/tabs-mobile.md
description: Describes developer considerations for implementing tabs on Microso
localization_priority: Normal + # Tabs on mobile
-When you're building a Microsoft Teams app that includes a tab, you must consider (and test) how your tab will function on both the Android and iOS Microsoft Teams clients. The sections below outline some of the key scenarios you need to consider.
+When you are building a Microsoft Teams app that includes a tab, you must test how your tab functions on both the Android and iOS Microsoft Teams clients. This article outlines some of the key scenarios you must consider.
+
+If you choose to have your channel or group tab appear on Teams mobile clients, the `setSettings()` configuration must have a value for the `websiteUrl` property. To ensure optimal user experience, you must follow the guidance for tabs on mobile in this article when creating your tabs.
+
+Apps [distributed through the Teams store](~/concepts/deploy-and-publish/appsource/publish.md) have a separate approval process for mobile clients. The default behavior of such apps is as follows:
+
+| **App capability** | **Behavior if app is approved** | **Behavior if app is not approved** |
+| | | |
+| **Personal tabs** | App appears in the bottom bar of the mobile clients. Tabs open in the Teams client. | App does not appear in the bottom bar of the mobile clients. |
+| **Channel and group tabs** | The tab opens in the Teams client using `contentUrl`. | The tab opens in a browser outside the Teams client using `websiteUrl`. |
+
+> [!NOTE]
+> * Apps submitted to the [AppSource](https://appsource.microsoft.com) for publishing on Teams are evaluated automatically for mobile responsiveness. For any queries, reach out to teamsubm@microsoft.com.
+> * For all apps that are not distributed through the AppSource, the tabs open in an in-app webview within the Teams clients by default and there is no separate approval process required.
+> * The default behavior of apps is only applicable if distributed through the Teams store. By default, all tabs open in the Teams client.
+> * To initiate an evaluation of your app for mobile-friendliness, reach out to teamsubm@microsoft.com with your app details.
## Authentication
For authentication to work on mobile clients, you must upgrade you Teams JavaScr
## Low bandwidth and intermittent connections
-Mobile clients regularly need to function with low bandwidth and intermittent connections. Your app should handle any timeouts appropriately by providing a contextual message to the user. You should also user progress indicators to provide feedback to your users for any long-running processes.
+Mobile clients function with low bandwidth and intermittent connections. Your app must handle any timeouts appropriately by providing a contextual message to the user. You must also use progress indicators to provide feedback to your users for any long-running processes.
## Testing on mobile clients
-You need to validate that your tab functions properly on mobile devices of various sizes and qualities. For Android devices, you can use the [DevTools](~/tabs/how-to/developer-tools.md) to debug your tab while it is running. We recommend that you test on both high- and low-performance devices, including a tablet.
+You must validate that your tab functions properly on mobile devices of various sizes and qualities. For Android devices, you can use [DevTools](~/tabs/how-to/developer-tools.md) to debug your tab while it is running. It is recommended that you test on both high and low-performance devices, including a tablet.
## Distribution
The following table describes tab availability and behavior when the app is list
| Capability | Mobile availability? | Mobile behavior | |-|--||
-|Channel and group tab|Yes|Tab opens in the device's default browser instead of the Teams mobile client using your app's `websiteUrl` configuration, which also must be included in your source code's `setSettings()` [function](/javascript/api/@microsoft/teams-js/settings?view=msteams-client-js-latest#functions&preserve-view=true). However, users can still view the tab in the Teams mobile client by selecting **More** next to the app and choosing **Open**, which triggers your appΓÇÖs `contentUrl` configuration.|
+|Channel and group tab|Yes|Tab opens in the device's default browser instead of the Teams mobile client using your app's `websiteUrl` configuration, which must also be included in your source code's `setSettings()` [function](/javascript/api/@microsoft/teams-js/settings?view=msteams-client-js-latest#functions&preserve-view=true). However, users can view the tab in the Teams mobile client by selecting **More** next to the app and choosing **Open**, which triggers your appΓÇÖs `contentUrl` configuration.|
|Personal app|No|Not applicable| ### Apps not on Teams store
-If you're sideloading your app or publishing to an org's app catalog, tab behavior will be the same as Teams store apps approved by Microsoft for mobile.
+If you are sideloading your app or publishing to an organization's app catalog, tab behavior is the same as Teams store apps approved by Microsoft for mobile.
## See also * [Tab design guidelines](~/tabs/design/tabs.md)
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Get context for your tab](~/tabs/how-to/access-teams-context.md)
platform Access Teams Context https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/access-teams-context.md
keywords: teams tabs user context
-# Get context for your Microsoft Teams tab
+# Get context for your tab
-Your tab must require contextual information to display relevant content:
+Your tab requires contextual information to display relevant content:
* Basic information about the user, team, or company. * Locale and theme information.
Your tab must require contextual information to display relevant content:
## User context
-Context about the user, team or company can be especially useful when:
+Context about the user, team, or company can be especially useful when:
* You create or associate resources in your app with the specified user or team.
-* You initiate an authentication flow against Azure Active Directory or other identity provider, and you don't want to require the user to enter their username again. For more information on authenticating within your Microsoft Teams tab, see [Authenticate a user in your Microsoft Teams tab](~/concepts/authentication/authentication.md).
+* You initiate an authentication flow from Azure Active Directory (AAD) or other identity provider, and you do not require the user to enter their username again. For more information, see [authenticate a user in your Microsoft Teams tab](~/concepts/authentication/authentication.md).
> [!IMPORTANT]
-> Although this user information can help provide a smooth user experience, you should *not* use it as proof of identity. For example, an attacker could load your page in a "bad browser" and render harmful information or requests.
+> Although this user information can help provide a smooth user experience, you must not use it as proof of identity. For example, an attacker can load your page in a browser and render harmful information or requests.
-## Accessing context
+## Access context information
You can access context information in two ways: * Insert URL placeholder values. * Use the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client).
-### Getting context by inserting URL placeholder values
+### Get context by inserting URL placeholder values
-Use placeholders in your configuration or content URLs. Microsoft Teams replaces the placeholders with the relevant values when determining the actual configuration or content URL. The available placeholders include all fields on the [Context](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true) object. Common placeholders include the following:
+Use placeholders in your configuration or content URLs. Microsoft Teams replaces the placeholders with the relevant values when determining the actual configuration or content URL. The available placeholders include all fields on the [context](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true) object. Common placeholders include the following:
* {entityId}: The ID you supplied for the item in this tab when first [configuring the tab](~/tabs/how-to/create-tab-pages/configuration-page.md).
-* {subEntityId}: The ID you supplied when generating a [deep link](~/concepts/build-and-test/deep-links.md) for a specific item _within_ this tab. This should be used to restore to a specific state within an entity; for example, scrolling to or activating a specific piece of content.
-* {loginHint}: A value suitable as a login hint for Azure AD.This is usually the login name of the current user, in their home tenant.
-* {userPrincipalName}: The User Principal Name of the current user, in the current tenant.
-* {userObjectId}: The Azure AD object ID of the current user, in the current tenant.
-* {theme}: The current UI theme such as `default`, `dark`, or `contrast`.
-* {groupId}: The ID of the Office 365 Group in which the tab resides.
-* {tid}: The Azure AD tenant ID of the current user.
+* {subEntityId}: The ID you supplied when generating a [deep link](~/concepts/build-and-test/deep-links.md) for a specific item within this tab. This must be used to restore to a specific state within an entity; for example, scrolling to or activating a specific piece of content.
+* {loginHint}: A value suitable as a login hint for AAD. This is usually the login name of the current user in their home tenant.
+* {userPrincipalName}: The User Principal Name of the current user in the current tenant.
+* {userObjectId}: The AAD object ID of the current user in the current tenant.
+* {theme}: The current user interface (UI) theme such as `default`, `dark`, or `contrast`.
+* {groupId}: The ID of the Office 365 group in which the tab resides.
+* {tid}: The AAD tenant ID of the current user.
* {locale}: The current locale of the user formatted as languageId-countryId. For example, en-us.
->[!NOTE]
->The previous `{upn}` placeholder is now deprecated. For backward compatibility, it is currently a synonym for `{loginHint}`.
+> [!NOTE]
+> The previous `{upn}` placeholder is now deprecated. For backward compatibility, it is currently a synonym for `{loginHint}`.
-For example, suppose in your tab manifest you set the `configURL` attribute to `"https://www.contoso.com/config?name={loginHint}&tenant={tid}&group={groupId}&theme={theme}"`, the signed-in user has the following attributes:
+For example, in your tab manifest you set the `configURL` attribute to `"https://www.contoso.com/config?name={loginHint}&tenant={tid}&group={groupId}&theme={theme}"`, the signed-in user has the following attributes:
-* Their username is 'user@example.com'.
-* Their company tenant ID is 'e2653c-etc'.
-* They are a member of the Office 365 group with id '00209384-etc'.
-* The user has set their Teams theme to 'dark'.
+* Their username is **user@example.com**.
+* Their company tenant ID is **e2653c-etc**.
+* They are a member of the Office 365 group with id **00209384-etc**.
+* The user has set their Teams theme to **dark**.
-When they configure your tab, Teams calls the following URL:
+When they configure the tab, Teams calls the following URL:
`https://www.contoso.com/config?name=user@example.com&tenant=e2653c-etc&group=00209384-etc&theme=dark`
-### Getting context by using the Microsoft Teams JavaScript library
+### Get context by using the Microsoft Teams JavaScript library
You can also retrieve the information listed above using the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client) by calling `microsoftTeams.getContext(function(context) { /* ... */ })`.
-The context variable looks like the following example:
+The following code provides an example of context variable:
```json {
The context variable looks like the following example:
} ```
-## Retrieving context in private channels
+## Retrieve context in private channels
> [!Note] > Private channels are currently in private developer preview.
-When your content page is loaded in a private channel, the data you receive from the `getContext` call will be obfuscated to protect the privacy of the channel. The following fields are changed when your content page is in a private channel. If your page makes use of any of the values below, you'll need to check the `channelType` field to determine if your page is loaded in a private channel, and respond appropriately.
+When your content page is loaded in a private channel, the data you receive from the `getContext` call is obfuscated to protect the privacy of the channel. The following fields are changed when your content page is in a private channel:
* `groupId`: Undefined for private channels * `teamId`: Set to the threadId of the private channel
When your content page is loaded in a private channel, the data you receive from
* `teamSitePath`: Set to the path of a distinct, unique SharePoint site for the private channel * `teamSiteDomain`: Set to the domain of a distinct, unique SharePoint site domain for the private channel
+If your page makes use of any of these values, you must check the `channelType` field to determine if your page is loaded in a private channel and respond appropriately.
+ > [!Note]
-> teamSiteUrl works well for standard channels also.
+> `teamSiteUrl` also works well for standard channels.
+
+## Handle theme change
+
+You can register your app to be informed if the theme changes by calling `microsoftTeams.registerOnThemeChangeHandler(function(theme) { /* ... */ })`.
+
+The `theme` argument in the function is a string with a value of `default`, `dark`, or `contrast`.
+
+## See also
-## Theme change handling
+* [Tab design guidelines](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
-You can register your app to be told if the theme changes by calling `microsoftTeams.registerOnThemeChangeHandler(function(theme) { /* ... */ })`.
+## Next step
-The `theme` argument in the function will be a string with a value of `default`, `dark`, or `contrast`.
+> [!div class="nextstepaction"]
+> [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
platform Build Adaptive Card Tabs https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/build-adaptive-card-tabs.md
- # Build tabs with Adaptive Cards > [!IMPORTANT] > * This feature is in [Public Developer Preview](~/resources/dev-preview/developer-preview-intro.md) and is supported in desktop and mobile. Support in the web browser is coming soon. > * Tabs with Adaptive Cards are currently only supported as personal apps.
-Use Adaptive Cards to build tabs with ease. You can build your tabs with ready-made UI Lego-blocks that look and feel native on desktop, web, and mobile. Building tabs with Adaptive Cards centralizes all Teams app capabilities around a bot backend and Adaptive Card frontend, thus, eliminating the need for a different backend for your bot and tabs. This greatly reduces server and maintenance costs of your Teams app. This article helps you understand the changes required to be made to the app manifest, how the invoke activity requests and sends information in tab with Adaptive Cards, and the impact on the task module workflow.
+When developing a tab using the traditional method, you might run into these issues, such as HTML and CSS considerations, slow load times, iFrame constraints, and server maintenance and costs. Adaptive Card tabs is a new way to build tabs in Teams. Instead of embedding web content in an IFrame, you can render Adaptive Cards to a tab. While the front-end is rendered with Adaptive Cards, the backend is powered by a bot. The bot is responsible for accepting requests and responding appropriately with the Adaptive Card that is rendered.
+
+You can build your tabs with ready-made user interface (UI) Lego-blocks that look and feel native on desktop, web, and mobile. This article helps you understand the changes required to be made to the app manifest, how the invoke activity requests and sends information in tab with Adaptive Cards, and the impact on the task module workflow.
The following image depicts build tabs with Adaptive Cards in desktop and mobile:+ :::image type="content" source="../../assets/images/tabs/adaptive-cards-rendered-in-tabs.jpg" alt-text="Example of Adaptive Card rendered in tabs." border="false"::: ## Prerequisites Before you start using Adaptive Cards to build tabs, you must:
-* Be familiar with, [bot development](../../bots/what-are-bots.md), [Adaptive Cards](../../task-modules-and-cards/what-are-cards.md#adaptive-cards), and [Task Modules](../../task-modules-and-cards/task-modules/task-modules-bots.md) in Teams.
+* Be familiar with, [bot development](../../bots/what-are-bots.md), [Adaptive Cards](../../task-modules-and-cards/what-are-cards.md#adaptive-cards), and [task modules](../../task-modules-and-cards/task-modules/task-modules-bots.md) in Teams.
* Have a bot running in Teams for your development. * Be in [Public Developer Preview](~/resources/dev-preview/developer-preview-intro.md). ## Changes to app manifest
-Personal apps that render tabs must include a `staticTabs` array in their app manifest. Adaptive Card Tab are rendered when the `contentBotId` property is provided in the `staticTab` definition. Static tab definitions must contain either a `contentBotId`, specifying an Adaptive Card Tab or a `contentUrl`, specifying a typical hosted web content tab experience.
+Personal apps that render tabs must include a `staticTabs` array in their app manifest. Adaptive Card tabs are rendered when the `contentBotId` property is provided in the `staticTab` definition. Static tab definitions must contain either a `contentBotId`, specifying an Adaptive Card tab or a `contentUrl`, specifying a typical hosted web content tab experience.
> [!NOTE]
-> The `contentBotId` property is currently available manifest version 1.9 or later.
+> The `contentBotId` property is currently available in manifest version 1.9 or later.
-Provide the `contentBotId` property with the `botId` that the Adaptive Card Tab must communicate with. The `entityId` configured for the Adaptive Card Tab is sent in the `tabContext` parameter of each invoke request, and can be used to differentiate different Adaptive Card Tabs that are powered by the same bot. For more information about other static tab definition fields, see [manifest schema](../../resources/schem#statictabs).
+Provide the `contentBotId` property with the `botId` that the Adaptive Card tab must communicate with. The `entityId` configured for the Adaptive Card tab is sent in the `tabContext` parameter of each invoke request, and can be used to differentiate Adaptive Card Tabs that are powered by the same bot. For more information about other static tab definition fields, see [manifest schema](../../resources/schem#statictabs).
-Following is a sample Adaptive Card Tab manifest:
+Following is a sample Adaptive Card tab manifest:
```json {
Following is a sample Adaptive Card Tab manifest:
## Invoke activities
-Communication between your Adaptive Card Tab and your bot is done through `invoke` activities. Each `invoke` activity has a corresponding *name*. Use the name of each activity to differentiate each request. `tab/fetch` and `tab/submit` are the activities covered in this section.
+Communication between your Adaptive Card tab and your bot is done through `invoke` activities. Each `invoke` activity has a corresponding **name**. Use the name of each activity to differentiate each request. `tab/fetch` and `tab/submit` are the activities covered in this section.
### Fetch Adaptive Card to render to a tab
-`tab/fetch` is the first invoke request that your bot receives when a user opens an Adaptive Card Tabs. When your bot receives the request, it will either send a tab **continue** response or a tab **auth** response.
+`tab/fetch` is the first invoke request that your bot receives when a user opens an Adaptive Card tab. When your bot receives the request, it either sends a tab **continue** response or a tab **auth** response.
The **continue** response includes an array for **cards**, which is rendered vertically to the tab in the order of the array. > [!NOTE]
-> The **auth** response is explained in detail in the [authentication](#authentication) section.
+> For more information on **auth** response, see [authentication](#authentication).
-The following code snippets are examples of `tab/fetch` request and response:
+The following code provides examples of `tab/fetch` request and response:
**`tab/fetch` request**
The following code snippets are examples of `tab/fetch` request and response:
After an Adaptive Card is rendered in the tab, it must be able to respond to user interactions. This response is handled by the `tab/submit` invoke request.
-When a user selects a button on the Adaptive Card Tab, the `tab/submit` request is triggered to your bot with the corresponding data through the *Action.Submit* function of Adaptive Card. The Adaptive Card data is available through the data property of the `tab/submit` request. You will receive either of the following responses to your request:
+When a user selects a button on the Adaptive Card tab, the `tab/submit` request is triggered to your bot with the corresponding data through the `Action.Submit` function of Adaptive Card. The Adaptive Card data is available through the data property of the `tab/submit` request. You receive either of the following responses to your request:
-* A http status code `200` response with no body. An empty 200 response will result in no action taken by the client.
-* The standard `200` tab **continue** response, as explained in [Fetch Adaptive Card](#fetch-adaptive-card-to-render-to-a-tab) section. A tab **continue** response triggers the client to update the rendered Adaptive Card Tab with the Adaptive Cards provided in the cards array of the **continue** response.
+* An HTTP status code `200` response with no body. An empty 200 response results in no action taken by the client.
+* The standard `200` tab **continue** response, as explained in [fetch Adaptive Card](#fetch-adaptive-card-to-render-to-a-tab). A tab **continue** response triggers the client to update the rendered Adaptive Card tab with the Adaptive Cards provided in the cards array of the **continue** response.
-The following code snippets are examples of `tab/submit` request and response:
+The following code provides examples of `tab/submit` request and response:
**`tab/submit` request**
The following code snippets are examples of `tab/submit` request and response:
## Understand task module workflow
-The task module also uses Adaptive Card to invoke `task/fetch` and `task/submit` requests and responses. For more information, see [Using Task Modules in Microsoft Teams bots](../../task-modules-and-cards/task-modules/task-modules-bots.md).
+The task module also uses Adaptive Card to invoke `task/fetch` and `task/submit` requests and responses. For more information, see [using Task Modules in Microsoft Teams bots](../../task-modules-and-cards/task-modules/task-modules-bots.md).
-However, with the introduction of Adaptive Card Tab there is a change in how the bot responds to a `task/submit` request. If you are using an Adaptive Card Tab, the bot responds to the `task/submit` invoke request with the standard tab **continue** response, and closes the task module. The Adaptive Card Tab is updated by rendering the new list of cards provided in the tab **continue** response body.
+With the introduction of Adaptive Card tab, there is a change in how the bot responds to a `task/submit` request. If you are using an Adaptive Card tab, the bot responds to the `task/submit` invoke request with the standard tab **continue** response, and closes the task module. The Adaptive Card tab is updated by rendering the new list of cards provided in the tab **continue** response body.
### Invoke `task/fetch`
-The following code snippets are examples of `task/fetch` request and response:
+The following code provides examples of `task/fetch` request and response:
**`task/fetch` request** ```json
The following code snippets are examples of `task/fetch` request and response:
### Invoke `task/submit`
-The following code snippets are examples of `task/submit` request and response:
+The following code provides examples of `task/submit` request and response:
**`task/submit` request**
The following code snippets are examples of `task/submit` request and response:
## Authentication
-In the previous sections of this article, you have seen that most of the development paradigms could be extrapolated from the task module requests and responses into tab requests and responses. However, when it comes to handling authentication, the workflow for Adaptive Card Tab follows the authentication pattern for messaging extensions. For more information, see [add authentication](../../messaging-extensions/how-to/add-authentication.md).
+In the previous sections of this article, you have seen that most of the development paradigms can be extended from the task module requests and responses into tab requests and responses. When it comes to handling authentication, the workflow for Adaptive Card tab follows the authentication pattern for messaging extensions. For more information, see [add authentication](../../messaging-extensions/how-to/add-authentication.md).
-In the [invoke activities](#invoke-activities) section, you were informed that `tab/fetch` requests can have either a **continue** or an **auth** response. When a `tab/fetch` request is triggered and receives a tab **auth** response, the sign-in page is shown to the user.
+`tab/fetch` requests can have either a **continue** or an **auth** response. When a `tab/fetch` request is triggered and receives a tab **auth** response, the sign-in page is shown to the user.
**To get an authentication code through `tab/fetch` invoke** 1. Open your app. The sign in page appears. > [!NOTE]
- > The app logo is provided through the `icon` property defined in the app manifest, and the title appearing after the logo is defined in the `title` property returned in the tab **auth** response body.
+ > The app logo is provided through the `icon` property defined in the app manifest. The title appearing after the logo is defined in the `title` property returned in the tab **auth** response body.
-1. Select **Sign in**. You are redirected to the authentication URL provided in the `value` property of the **auth** response body.
+1. Select **Sign in**. You are redirected to the authentication URL provided in the `value` property of the **auth** response body.
1. A pop-up window appears. This pop-up window hosts your web page using the authentication URL.
-1. After you sign in, close the window. An *authentication code* is sent to the Teams client.
-1. The Teams client then reissues the `tab/fetch` request to your service, which includes the authentication code provided by your hosted web page.
+1. After you sign in, close the window. An **authentication code** is sent to the Teams client.
+1. The Teams client then reissues the `tab/fetch` request to your service, which includes the authentication code provided by your hosted web page.
### `tab/fetch` authentication data flow
The following image provides an overview of how the authentication data flow wor
**`tab/fetch` auth response**
-The following code snippet is an example of `tab/fetch` auth response:
+The following code provides an example of `tab/fetch` auth response:
```json // tab/auth POST response (openURL)
The following code snippet is an example of `tab/fetch` auth response:
### Example
-The following shows a reissued request example:
+The following code shows a reissued request example:
```json {
The following shows a reissued request example:
## See also
-> [!div class="nextstepaction"]
-> [Adaptive Card](../../task-modules-and-cards/what-are-cards.md#adaptive-cards)
+* [Adaptive Card](../../task-modules-and-cards/what-are-cards.md#adaptive-cards)
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+> [!div class="nextstepaction"]
+> [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
platform Conversational Tabs https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/conversational-tabs.md
keywords: teams tabs channel configurable
+ # Create conversational tabs
-Conversational sub-entities provides a way to allow users to have conversations about sub-entities in your tab, such as specific task, patient, and sales opportunity, instead of discussing the entire tab, also known as entity. A traditional channel or configurable tab allows the user to have a conversation about a tab, but the user may want a more focused conversation. The requirement for a more focused conversation can arise either, if there is too much content to have a centralized discussion or the content changed over time, making the conversation irrelevant to the content being shown. Conversational sub-entities provides a much more focused conversation experience for dynamic tabs.
+Conversational sub-entities provides a way to allow users to have conversations about sub-entities in your tab, such as specific task, patient, and sales opportunity, instead of discussing the entire tab, also known as entity. A traditional channel or configurable tab allows the user to have a conversation about a tab, but the user requires a more focused conversation. The requirement for a more focused conversation can arise either, if there is too much content to have a centralized discussion or because the content changed over time, making the conversation irrelevant to the content being shown. Conversational sub-entities provides a much more focused conversation experience for dynamic tabs.
-Conversational sub-entities are only supported in channels. However, they can be used from a personal or static tab to create or continue conversations in tabs that are *already* pinned to a channel. The static tab is useful if you wish to provide one location for a user to view and access conversations happening across multiple channels.
+Conversational sub-entities are only supported in channels. They can be used from a personal or static tab to create or continue conversations in tabs that are already pinned to a channel. The static tab is useful if you want to provide one location for a user to view and access conversations happening across multiple channels.
## Prerequisites
-In order to support conversational sub-entities, your tab web application must have the ability to store a mapping between sub-entities Γåö conversations in a backend database. We will provide you with the `conversationId`, but it will be your responsibility to store that `conversationId` and return it to Teams in order for users to continue the conversation.
+In order to support conversational sub-entities, your tab web application must have the ability to store a mapping between sub-entities Γåö conversations in a backend database. The `conversationId` is provided, but you must store that `conversationId` and return it to Teams in order for users to continue the conversation.
## Start a new conversation
-To start a new conversation, you use the `openConversation()` function. Starting and continuing a conversation are all handled by this method, however, the inputs to the function change depending on which action you want to take. From the users perspective, this opens the conversation panel to the right of the screen, either to initiate a conversation or continue a conversation.
+To start a new conversation, use the `openConversation()` function. Starting and continuing a conversation are all handled by this method. The inputs to the function change depending on which action you want to take. From the users perspective, this opens the conversation panel to the right of the screen, either to initiate a conversation or continue a conversation.
``` javascript microsoftTeams.conversations.openConversation(openConversationRequest);
microsoftTeams.conversations.openConversation(openConversationRequest);
* **entityId**: This is the ID of the tab instance when it was created. The ID is important to refer back to the same tab instance. * **channelId**: This is the channel in which the tab instance resides. > [!NOTE]
- > The **channelId** is optional for channel tabs. However, it is recommended if you wish to keep your implementation across channel and static tabs the same.
+ > The **channelId** is optional for channel tabs. However, it is recommended if you want to keep your implementation across channel and static tabs the same.
* **title**: This is the title that is shown to the user in the chat panel. Most of these values can also be retrieved from the `getContext` API.
Most of these values can also be retrieved from the `getContext` API.
microsoftTeams.conversations.openConversation({ΓÇ£subEntityIdΓÇ¥:ΓÇ¥task-1ΓÇ¥, ΓÇ£entityIdΓÇ¥: ΓÇ£tabInstanceId-1ΓÇ¥, ΓÇ£channelIdΓÇ¥: ΓÇ¥19:baa6e71f65b948d189bf5c892baa8e5a@thread.skypeΓÇ¥, ΓÇ£titleΓÇ¥: "Task TitleΓÇ¥}); ```
-This will open the conversation panel.
+The following image shows the conversation panel:
-![Conversationl Sub Entities - Start Conversation](~/assets/images/tabs/conversational-subentities/start-conversation.png)
+![Conversational sub-entities - start conversation](~/assets/images/tabs/conversational-subentities/start-conversation.png)
-If the user starts a conversation, itΓÇÖs important to listen for the callback of that event in order to retrieve and save the **conversationId**:
+If the user starts a conversation, it is important to listen for the callback of that event in order to retrieve and save the **conversationId**:
```javascript microsoftTeams.conversations.onStartConversation = (conversationResponse) => {
microsoftTeams.conversations.onStartConversation = (conversationResponse) => {
}; ```
-The `conversationReponse` object contains information related to the conversation that was just started. We recommend you save all the properties of this response object for reuse later.
+The `conversationResponse` object contains information related to the conversation that was started. It is recommended that you save all the properties of this response object for later use.
## Continue a conversation
-After a conversation starts, subsequent calls to `openConversation()` requires that you also provide the same inputs as in [Starting a new channel tab conversation](#Starting a new channel tab conversation), but also include the **conversationId**. The conversation panel opens for the user with the appropriate conversation in view. Users are able to see new or incoming messages in real-time.
+After a conversation starts, subsequent calls to `openConversation()` requires that you also provide the same inputs as in [start a new conversation](#start-a-new-conversation), but also include the **conversationId**. The conversation panel opens for the user with the appropriate conversation in view. Users are able to see new or incoming messages in real-time.
+
+The following image shows the conversation panel with the appropriate conversation:
-![Conversationl Sub Entities - Continue Conversation](~/assets/images/tabs/conversational-subentities/continue-conversation.png)
+![Conversational sub-entities - continue conversation](~/assets/images/tabs/conversational-subentities/continue-conversation.png)
## Enhance a conversation
-Finally, itΓÇÖs important that your tab consumes [deeplinks to your sub-entity](~/concepts/build-and-test/deep-links.md). For example, user clicking the tab chiclet deeplink from the channel conversation. The expected behavior is for you to receive the deeplink, open that sub-entity, and then open the conversation panel for that specific sub-entity.
+It is important that your tab includes [deeplinks to your sub-entity](~/concepts/build-and-test/deep-links.md). For example, user selecting the tab chiclet deeplink from the channel conversation. The expected behavior is to receive the deeplink, open that sub-entity, and then open the conversation panel for that sub-entity.
-To support conversational sub-entities from your personal or static tab, you do not have to change anything about your implementation. We only support starting or continuing conversations from channel tabs that are already pinned. Supporting static tabs allow you to provide a single location for your users to interact with all your sub-entities. It is, however, important that you save the `subEntityId`, `entityId`, and `channelId` when your tab is originally created in a channel in order for you to have the right properties when opening the conversation view in a static tab.
+To support conversational sub-entities from your personal or static tab, you do not have to change anything in your implementation. We only support starting or continuing conversations from channel tabs that are already pinned. Supporting static tabs allows you to provide a single location for your users to interact with all your sub-entities. It is important that you save the `subEntityId`, `entityId`, and `channelId` when your tab is originally created in a channel to have the right properties when opening the conversation view in a static tab.
## Close a conversation
microsoftTeams.conversations.onCloseConversation = (conversationResponse) => {
// console.log(conversationResponse) }; ```+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Tab margin changes](~/resources/removing-tab-margins.md)
platform Create Channel Group Tab https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/create-channel-group-tab.md
+
+ Title: Create a channel or group tab
+
+description: A quickstart guide to creating a channel and group tab with the Yeoman Generator for Microsoft Teams.
+localization_priority: Normal
++++
+# Create a channel or group tab
+
+## Create a custom channel or group tab
+
+You can create a channel or group tab using Node.js and the Yeoman Generator, ASP.NETCore, or ASP.NETCore MVC.
+
+# [Node.js](#tab/nodejs)
+
+### Create a custom channel and group tab using Node.js and the Yeoman Generator
+
+> [!NOTE]
+> This article follows the steps outlined in the [build Your first Microsoft Teams app](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App) Wiki found in the Microsoft OfficeDev GitHub repository.
+
+You can create a custom channel or group tab using the [Teams Yeoman generator](https://github.com/OfficeDev/generator-teams/).
+
+### Prerequisites for apps
+
+You must have an understanding of the following prerequisites:
+
+- You must have an Office 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not currently have an Office 365 account, you can sign up for a free subscription through the Office 365 Developer Program. The subscription remains active as long as you are using it for ongoing development. See [welcome to the Office 365 Developer Program](/office/developer-program/microsoft-365-developer-program).
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- Any text editor or IDE. You can install and use [Visual Studio Code](https://code.visualstudio.com/download) for free.
+
+- [Node.js/npm](https://nodejs.org/en/). Use the latest LTS version. The Node Package Manager (npm) installs in your system with the installation of Node.js.
+
+- After you have successfully installed Node.js, install the [Yeoman](https://yeoman.io/) and [gulp-cli](https://www.npmjs.com/package/gulp-cli) packages by entering the following in your command prompt:
+
+ ```bash
+ npm install yo gulp-cli --global
+ ```
+
+- Install the Microsoft Teams Apps generator by entering the following in your command prompt:
+
+ ```bash
+ npm install generator-teams --global
+ ```
+
+### Generate your project
+
+**To generate your project**
+
+1. At a command prompt, create a new directory for your tab project.
+
+1. To start the generator, go to your new directory and type the following command:
+
+ ```bash
+ yo teams
+ ```
+
+1. Next, provide a series of values that are used in your application's **manifest.json** file:
+
+ ![generator opening screenshot](/microsoftteams/platform/assets/images/tab-images/teamsTabScreenshot.PNG)
+
+ **What is your solution name?**
+
+ This is your project name. You can accept the suggested name by selecting the **Enter** key.
+
+ **Where do you want to place the files?**
+
+ You are currently in your project directory. Select **Enter**.
+
+ **Title of your Microsoft Teams app project?**
+
+ This is your app package name and will be used in the app manifest and description. Enter a title or select **Enter** to accept the default name.
+
+ **Your (company) name? (max 32 characters)**
+
+ Your company name will be used in the app manifest. Enter a company name or select **Enter** to accept the default name.
+
+ **Which manifest version would you like to use?**
+
+ Select the default schema.
+
+ **Quick scaffolding? (Y/n)**
+
+ The default is yes; enter **n** to enter your Microsoft Partner Id.
+
+ **Enter your Microsoft Partner Id, if you have one? (Leave blank to skip)**
+
+ This field is not required and should only be used if you are already part of the [Microsoft Partner Network](https://partner.microsoft.com).
+
+ **What do you want to add to your project?**
+
+ Select **( &ast; ) A Tab**.
+
+ **The URL where you will host this solution?**
+
+ By default the generator suggests an Azure Web Sites URL. You are only testing your app locally, therefore, a valid URL is not necessary.
+
+ **Would you like show a loading indicator when your app/tab loads?**
+
+ Choose **not** to include a loading indicator when your app or tab loads. The default is no, enter **n**.
+
+ **Would you like personal apps to be rendered without a tab header-bar?**
+
+ Choose **not** to include personal apps to be rendered without a tab header-bar. Default is no, enter **n**.
+
+ **Would you like to include Test framework and initial tests? (y/N)**
+
+ Choose **not** to include a test framework for this project. The default is yes; enter **n**.
+
+ **Would you like to use Azure Applications Insights for telemetry? (y/N)**
+
+ Choose **not** to include [Azure Application Insights](/azure/azure-monitor/app/app-insights-overview). The default is no; enter **n**.
+
+ **Default Tab Name (max 16 characters)?**
+
+ Name your tab. This tab name will be used throughout your project as a file or URL path component.
+
+ **What kind of Tab would you like to create?**
+
+ Use the arrow keys to select **Configurable** tab.
+
+ **What scopes do you intend to use for your Tab?**
+
+ You can select a team or a group chat.
+
+ **Do you require Azure AD Single-Sign-On support for the tab?**
+
+ Choose **not** to include Azure AD Single-Sign-On support for the tab. The default is yes, enter **n**.
+
+ **Do you want this tab to be available in SharePoint Online? (Y/n)**
+
+ Enter **n**.
+
+ > [!IMPORTANT]
+ > The path component **yourDefaultTabNameTab**, is the value that you entered in the generator for **Default Tab Name** plus the word **Tab**.
+ >
+ > For example: DefaultTabName: **MyTab** > **/MyTabTab/**
+
+1. In Visual Studio Code or any code editor, go to your project directory and open the following file:
+
+ ```bash
+ ./src/app/scripts/<yourDefaultTabNameTab>/<yourDefaultTabNameTab>.tsx
+ ```
+
+1. Locate the `render()` method and add the following `<div>` tag and content to the top of the `<PanelBody>` container code:
+
+ ```html
+ <PanelBody>
+ <div style={styles.section}>
+ Hello World! Yo Teams rocks!
+ </div>
+ </PanelBody>
+ ```
+
+1. Make sure to save the updated file.
+
+### Build and run your application
+
+At a command prompt, open your project directory to complete the next tasks.
+
+#### Create the app package
+
+You must have an app package to test your tab in Teams. It is a zip folder that contains the following required files:
+
+- A **full color icon** measuring 192 x 192 pixels.
+- A **transparent outline icon** measuring 32 x 32 pixels.
+- A **manifest.json** file that specifies the attributes of your app.
+
+The package is created through a gulp task that validates the manifest.json file and generates the zip folder in the **./package directory**. In the command prompt, enter the following command:
+
+```bash
+gulp manifest
+```
+
+#### Build your application
+
+The build command transpiles your solution into the **./dist** folder. Enter the following command in the command prompt:
+
+```bash
+gulp build
+```
+
+#### Run your application in localhost
+
+1. Start a local web server by entering the following in the command prompt:
+
+ ```bash
+ gulp serve
+ ```
+
+1. Enter `http://localhost:3007/<yourDefaultAppNameTab>/` in your browser, replace **<yourDefaultAppNameTab>** with your tab name, and view your application's home page as shown in the following image:
+
+ ![home page screenshot](~/assets/images/tab-images/homePage.png)
+
+1. To view your tab configuration page, go to `https://localhost:3007/<yourDefaultAppNameTab>/config.html`. The following is shown:
+
+ ![Configuration page screenshot](~/assets/images/tab-images/configurationPage.png)
+
+### Establish a secure tunnel to your tab
+
+Microsoft Teams is a cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams does not allow local hosting. You must either publish your tab to a public URL or use a proxy that exposes your local port to an internet-facing URL.
+
+To test your tab extension, use [ngrok](https://ngrok.com/docs), which is built into this application. Ngrok is a reverse proxy software tool that creates a tunnel to your locally running web server's publicly-available HTTPS endpoints. Your server's web endpoints are available during the current session on your computer. When the computer is shut down or goes to sleep the service is no longer available.
+
+In your command prompt, exit localhost and enter the following:
+
+```bash
+gulp ngrok-serve
+```
+
+> [!IMPORTANT]
+> After your tab has been uploaded to Microsoft Teams and successfully saved, you can view it in the tabs gallery, add it to the tabs bar, and interact with it until your ngrok tunnel session ends. If you restart your ngrok session, you must update your app with the new URL.
+
+### Upload your application to Teams
+
+**To upload your application to Teams**
+
+1. Go to Microsoft Teams. If you use the [web-based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+1. From your teams on the left pane, select the ellipses &#x25CF;&#x25CF;&#x25CF; next to the team that you are using to test your tab and choose **Manage team**.
+1. In the main pane, select **Apps** from the tab bar and choose **Upload a custom app** located in the lower right corner of the page.
+1. Go your project directory, browse to the **./package** folder, select the app package zip folder, and choose **Open**.
+
+ ![Channel tab added](../../assets/images/tab-images/channeltabadded.png)
+
+1. Select **Add** in the pop-up dialog box. Your tab uploads into Teams.
+1. Return to your team, choose the channel where you want to display the tab, select Γ₧ò from the tab bar, and choose your tab from the gallery.
+1. Follow the directions for adding a tab. There is a custom configuration dialog box for your channel or group tab.
+1. Select **Save** and your tab is added to the channel's tab bar.
+
+ ![Channel tab uploaded](../../assets/images/tab-images/channeltabuploaded.png)
+
+# [ASP.NET Core](#tab/aspnetcore)
+
+### Create a custom channel or group tab with ASP.NET Core
+
+You can create a custom channel or group tab using C# and ASP.Net Core Razor page. [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) is also used to finalize your app manifest and deploy your tab to Teams.
+
+### Prerequisites for Teams apps
+
+You must have an understanding of the following prerequisites:
+
+- You must have an Office 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not currently have a Microsoft 365 account, you can sign up for a free subscription through the [Microsoft Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program). The subscription remains active as long as you are using it for ongoing development.
+
+- Use App Studio to import your application to Teams. To install App Studio, select **Apps** ![Store App](~/assets/images/tab-images/storeApp.png) at the lower left corner of the Teams app, and search for **App Studio**. After you find the tile, select it and choose **Add** in the pop-up dialog box to install it.
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- The current version of the Visual Studio IDE with the **.NET CORE cross-platform development** workload installed. If you do not already have Visual Studio, you can download and install the latest [Microsoft Visual Studio Community](https://visualstudio.microsoft.com/downloads) version for free.
+
+- The [ngrok](https://ngrok.com) reverse proxy tool. Use ngrok to create a tunnel to your locally running web server's publicly-available HTTPS endpoints. You can [download ngrok](https://ngrok.com/download).
+
+### Get the source code
+
+At a command prompt, create a new directory for your tab project. A simple project is provided to get you started. Clone the sample repository into your new directory using the following command:
+
+```bash
+git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
+```
+
+Alternately, you can retrieve the source code by downloading the zip folder and extracting the files.
+
+**To build and run the tab project**
+
+1. After you have the source code, go to Visual Studio and select **Open a project or solution**.
+1. Go to the tab application directory and open **ChannelGroupTab.sln**.
+1. To build and run your application, press **F5** or choose **Start Debugging** from the **Debug** menu.
+1. In a browser, go to the following URLs and verify the application loaded properly:
+
+ - `http://localhost:44355`
+ - `http://localhost:44355/privacy`
+ - `http://localhost:44355/tou`
+
+### Review the source code
+
+#### Startup.cs
+
+This project was created from an ASP.NET Core 2.2 Web Application empty template with the **Advanced - Configure for HTTPS** check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template does not enable serving static content by default, so the static files middleware is added to the `Configure()` method using the following code:
+
+```csharp
+public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+ }
+public void Configure(IApplicationBuilder app)
+ {
+ app.UseStaticFiles();
+ app.UseMvc();
+ }
+```
+
+#### wwwroot folder
+
+In ASP.NET Core, the web root folder is where the application looks for static files.
+
+#### Index.cshtml
+
+ASP.NET Core treats files called **Index** as the default or home page for the site. When your browser URL points to the root of the site, **Index.cshtml** is displayed as the home page for your application.
+
+#### Tab.cs
+
+This C# file contains a method that is called from **Tab.cshtml** during configuration.
+
+#### AppManifest folder
+
+This folder contains the following required app package files:
+
+- A **full color icon** measuring 192 x 192 pixels.
+- A **transparent outline icon** measuring 32 x 32 pixels.
+- A **manifest.json** file that specifies the attributes of your app.
+
+These files need to be zipped in an app package for use in uploading your tab to Teams. When a user chooses to add or update your tab, Microsoft Teams loads the `configurationUrl` specified in your manifest, embeds it in an IFrame, and renders it in your tab.
+
+#### .csproj
+
+In the Visual Studio Solution Explorer window, right-click on the project and select **Edit Project File**. At the end of the file, you see the following code that creates and updates your zip folder when the application builds:
+
+```xml
+<PropertyGroup>
+ <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <EmbeddedResource Include="AppManifest\icon-outline.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\icon-color.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\manifest.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ </ItemGroup>
+```
+
+### Establish a secure tunnel to your tab for Teams
+
+Microsoft Teams is a cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams does not allow local hosting. You must either publish your tab to a public URL, or use a proxy that exposes your local port to an internet-facing URL.
+
+To test your tab, use [ngrok](https://ngrok.com/docs). Your server's web endpoints are available while ngrok is running on your computer. In the free version of ngrok, if you close ngrok, the URLs are different the next time you start it.
+
+- At a command prompt in the root of your project directory, run the following command:
+
+ ```bash
+ ngrok http https://localhost:44355 -host-header="localhost:44355"
+ ```
+
+- Ngrok listens to requests from the internet and routes them to your application when it is running on port 44355. It should resemble `https://y8rCgT2b.ngrok.io/` where **y8rCgT2b** is replaced by your ngrok alpha-numeric HTTPS URL.
+
+- Ensure that you keep the command prompt with ngrok running and make a note of the URL.
+
+### Update your application
+
+Within **Tab.cshtml** the application presents the user with two option buttons for displaying the tab with either a red or gray icon. Choosing the **Select Gray** or **Select Red** button triggers `saveGray()` or `saveRed()`, respectively, sets `settings.setValidityState(true)`, and enables the **Save** button on the configuration page. This code lets Teams know that you have completed the configuration requirements and the installation can proceed. The parameters of `settings.setSettings` are set. Finally, `saveEvent.notifySuccess()` is called to indicate that the content URL has been successfully resolved.
+
+#### _Layout.cshtml
+
+For your tab to display in Teams, you must include the **Microsoft Teams JavaScript client SDK** and include a call to `microsoftTeams.initialize()` after your page loads. This is how your tab and the Teams client communicate:
+
+Go to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tag:
+
+```html
+<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
+<script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>
+```
+
+> [!IMPORTANT]
+> Do not copy and paste the `<script src="...">` URLs from this page, as they do not represent the latest version. To get the latest version of the SDK, always go to [Microsoft Teams JavaScript API](https://www.npmjs.com/package/@microsoft/teams-js).
+
+#### Tab.cshtml
+
+**To update Tab.cshtml**
+
+1. Open **Tab.cshtml** in Visual Studio and update the embedded `<script>`.
+
+1. At the top of the script, call `microsoftTeams.initialize()`.
+
+1. Update the `websiteUrl` and `contentUrl` values in each function with the HTTPS ngrok URL to your tab.
+
+ Your code should now include the following with **y8rCgT2b** replaced with your ngrok URL:
+
+ ```javascript
+ microsoftTeams.initialize();
+
+ let saveGray = () => {
+ microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
+ microsoftTeams.settings.setSettings({
+ websiteUrl: `https://y8rCgT2b.ngrok.io`,
+ contentUrl: `https://y8rCgT2b.ngrok.io/gray/`,
+ entityId: "grayIconTab",
+ suggestedDisplayName: "MyNewTab"
+ });
+ saveEvent.notifySuccess();
+ });
+ }
+
+ let saveRed = () => {
+ microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) {
+ microsoftTeams.settings.setSettings({
+ websiteUrl: `https://y8rCgT2b.ngrok.io`,
+ contentUrl: `https://y8rCgT2b.ngrok.io/red/`,
+ entityId: "redIconTab",
+ suggestedDisplayName: "MyNewTab"
+ });
+ saveEvent.notifySuccess();
+ });
+ }
+ ```
+
+1. Save the updated **Tab.cshtml**.
+
+### Build and run your application for Teams
+
+**To build and run your application**
+
+1. In Visual Studio, press **F5** or choose **Start Debugging** from the **Debug** menu.
+1. Verify that **ngrok** is running and working properly by opening your browser and going to your content page via the ngrok HTTPS URL that was provided in your command prompt window.
+
+> [!TIP]
+> You need to have both your application in Visual Studio and ngrok running to complete the steps provided in this article. If you need to stop running your application in Visual Studio to work on it, **keep ngrok running**. It listens and resumes routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service it returns a new URL and you have to update your application with the new URL.
+
+### Upload your tab for Teams
+
+> [!NOTE]
+> App Studio can be used to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit the **manifest.json** file. If you do, ensure that you build the solution again to create the **tab.zip** file to upload.
+
+**To upload your tab with App Studio**
+
+1. Go to Microsoft Teams. If you use the [web-based version](https://teams.microsoft.com), you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+
+1. Go to **App Studio** and select the **Manifest editor** tab.
+
+1. Select **Import an existing app** in the **Manifest editor** to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It is available from the following path:
+
+ ```bash
+ /bin/Debug/netcoreapp2.2/tab.zip
+ ```
+
+1. Upload **tab.zip** to App Studio.
+
+#### Update your app package with Manifest editor
+
+After you have uploaded your app package into App Studio, you must configure it.
+
+Select the tile for your newly imported tab in the right panel of the Manifest editor welcome page.
+
+There is a list of steps on the left side of the Manifest editor, and on the right, a list of properties that must have values for each of those steps. Much of the information has been provided by your **manifest.json** but there are fields that you must update.
+
+##### Details: App details
+
+In the **App details** section:
+
+1. Under **Identification**, select **Generate** to replace the placeholder ID with the required GUID for your tab.
+
+1. Under **Developer information**, update **Website** with your **ngrok** HTTPS URL.
+
+1. Under **App URLs**, update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
+
+##### Capabilities: Tabs
+
+In the **Tabs** section:
+
+1. Under **Team tab**, select **Add**.
+
+1. In the **Team tab** pop-up window, update the **Configuration URL** to `https://<yourngrokurl>/tab`.
+
+1. Ensure the **Can update configuration?**, **Team**, and **Group chat** checkboxes are selected and select **Save**.
+
+##### Finish: Domains and permissions
+
+In the **Domains and permissions** section, **Domains from your tabs** must contain your ngrok URL without the HTTPS prefix `<yourngrokurl>.ngrok.io/`.
+
+##### Finish: Test and distribute
+
+> [!IMPORTANT]
+> On the right, in **Description**, you see the following warning:
+>
+> &#9888; "**The 'validDomains' array cannot contain a tunneling site...**"
+>
+> This warning can be ignored while testing your tab.
+
+1. In the **Test and Distribute** section, select **Install**.
+
+1. In the pop-up dialog box, select **Add to a team** or from the drop-down, select **Add to a chat**.
+
+1. Choose the team or chat where you want the tab to be displayed and select **Set up a tab**.
+
+1. In the next pop-up dialog box, choose either **Select Gray** or **Select Red**, and select **Save**.
+
+1. To view your tab, go to the team or chat where you installed the tab, and select it from the tab bar. The page that you chose during configuration is displayed.
+
+ ![Channel tab ASPNET uploaded](../../assets/images/tab-images/channeltabaspnetuploaded.png)
+
+# [ASP.NET Core MVC](#tab/aspnetcoremvc)
+
+### Create a custom channel or group tab with ASP.NET Core MVC
+
+You can create a custom channel or group tab using C# and ASP.Net Core MVC. [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) is also used to finalize your app manifest and deploy your tab to Teams.
+
+### Prerequisites for custom channel or group tab
+
+- You must have a Microsoft 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not currently have a Microsoft 365 account, you can sign up for a free subscription through the [Microsoft Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program). The subscription remains active as long as you are using it for ongoing development.
+
+- Use App Studio to import your application to Teams. To install App Studio, select **Apps** ![Store App](~/assets/images/tab-images/storeApp.png) at the lower left corner of the Teams app, and search for **App Studio**. After you find the tile, select it and choose **Add** in the pop-up dialog box to install it.
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- The current version of the Visual Studio IDE with the **.NET CORE cross-platform development** workload installed. If you do not already have Visual Studio, you can download and install the latest [Microsoft Visual Studio Community](https://visualstudio.microsoft.com/downloads) version for free.
+
+- The [ngrok](https://ngrok.com) reverse proxy tool. Use ngrok to create a tunnel to your locally running web server's publicly-available HTTPS endpoints. You can [download ngrok](https://ngrok.com/download).
+
+### Get the source code
+
+At a command prompt, create a new directory for your tab project. A simple [Channel Group Tab](https://github.com/OfficeDev/microsoft-teams-sample-tabs/tree/master/ChannelGroupTabMVC) project is provided to get you started. Clone the sample repository into your new directory using the following command:
+
+```bash
+git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
+```
+
+Alternately, you can retrieve the source code by downloading the zip folder and extracting the files.
+
+**To build and run the tab project**
+
+1. After you have the source code, go to Visual Studio and select **Open a project or solution**.
+1. Go to the tab application directory and open **ChannelGroupTabMVC.sln**.
+1. To build and run your application, press **F5** or choose **Start Debugging** from the **Debug** menu.
+1. In a browser, navigate to the following URLs and verify that the application loaded properly:
+
+ - `http://localhost:44360`
+ - `http://localhost:44360/privacy`
+ - `http://localhost:44360/tou`
+
+### Review the source code
+
+#### Startup.cs
+
+This project was created from an ASP.NET Core 2.2 Web Application empty template with the **Advanced - Configure for HTTPS** check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template does not enable serving static content by default, so the static files middleware is added to the `Configure()` method using the following code:
+
+```csharp
+public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+ }
+public void Configure(IApplicationBuilder app)
+ {
+ app.UseStaticFiles();
+ app.UseMvc();
+ }
+```
+
+#### wwwroot folder
+
+In ASP.NET Core, the web root folder is where the application looks for static files.
+
+#### AppManifest folder
+
+This folder contains the following required app package files:
+
+- A **full color icon** measuring 192 x 192 pixels.
+- A **transparent outline icon** measuring 32 x 32 pixels.
+- A **manifest.json** file that specifies the attributes of your app.
+
+These files need to be zipped in an app package for use in uploading your tab to Teams.
+
+#### .csproj
+
+In the Visual Studio Solution Explorer window, right-click on the project and select **Edit Project File**. At the end of the file you see the following code that creates and updates your zip folder when the application builds:
+
+```xml
+<PropertyGroup>
+ <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <EmbeddedResource Include="AppManifest\icon-outline.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\icon-color.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\manifest.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ </ItemGroup>
+```
+
+#### Models
+
+**ChannelGroup.cs** presents a Message object and methods that will be called from the controllers during configuration.
+
+#### Views
+
+These are the different views in ASP.NET Core MVC:
+
+* Home: ASP.NET Core treats files called **Index** as the default or home page for the site. When your browser URL points to the root of the site, **Index.cshtml** will be displayed as the home page for your application.
+
+* Shared: The partial view markup **_Layout.cshtml** contains the application's overall page structure and shared visual elements. It will also reference the Teams Library.
+
+#### Controllers
+
+The controllers use the `ViewBag` property to transfer values dynamically to the views.
++
+* Open a command prompt in the root of your project directory and run the following command:
+
+ ```bash
+ ngrok http https://localhost:443560 -host-header="localhost:44360"
+ ```
+
+* Ngrok will listen to requests from the internet and will route them to your application when it is running on port 44355. It should resemble `https://y8rCgT2b.ngrok.io/` where **y8rCgT2b** is replaced by your ngrok alpha-numeric HTTPS URL.
+
+* Ensure that you keep the command prompt with ngrok running and make a note of the URL.
+
+### Update your application
+
+Within **Tab.cshtml** the application presents the user with two option buttons for displaying the tab with either a red or gray icon. Choosing the **Select Gray** or **Select Red** button, triggers `saveGray()` or `saveRed()`, respectively, sets `settings.setValidityState(true)`, and enables the **Save** button on the configuration page. This code lets Teams know that you have completed the configuration requirements and the installation can proceed. On save, the parameters of `settings.setSettings` are set. Finally, `saveEvent.notifySuccess()` is called to indicate that the content URL has been successfully resolved.
++++
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
platform Create Personal Tab https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/create-personal-tab.md
+
+ Title: Create a personal tab
+
+description: A quickstart guide to creating a personal tab with the Yeoman Generator for Microsoft Teams.
+localization_priority: Normal
++++
+# Create a personal tab
+
+## Create a custom personal tab
+
+You can create a personal tab using Node.js and the Yeoman Generator, ASP.NET Core, or ASP.NET Core MVC.
+
+# [Node.js](#tab/nodejs)
+
+### Create a custom personal tab using Node.js and the Yeoman Generator
+
+> [!NOTE]
+> This article follows the steps outlined in the [build your first Microsoft Teams app](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App) Wiki found in the Microsoft OfficeDev GitHub repository.
+
+You can create a custom personal tab using the [Teams Yeoman generator](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App). The application is also uploaded to Teams.
+
+### Prerequisites for Teams apps
+
+You must have an understanding of the following prerequisites:
+
+- You must have an Office 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not have an Office 365 account, you can sign up for a free subscription through the Office 365 Developer Program. The subscription remains active as long as you are using it for ongoing development. See [welcome to the Office 365 Developer Program](/office/developer-program/microsoft-365-developer-program).
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- Any text editor or IDE. You can install and use [Visual Studio Code](https://code.visualstudio.com/download) for free.
+
+- [Node.js/npm](https://nodejs.org/en/). Use the latest LTS version. The Node Package Manager (npm) is installed in your system with the installation of Node.js.
+
+- After you have successfully installed Node.js, install the [Yeoman](https://yeoman.io/) and [gulp-cli](https://www.npmjs.com/package/gulp-cli) packages by entering the following in your command prompt:
+
+ ```bash
+ npm install yo gulp-cli --global
+ ```
+
+- Install the Microsoft Teams Apps generator by entering the following in your command prompt:
+
+ ```bash
+ npm install generator-teams --global
+ ```
+
+### Generate your project
+
+**To generate your project**
+
+1. At a command prompt, create a new directory for your tab project.
+
+1. To start the generator, go to your new directory and enter the following command:
+
+ ```bash
+ yo teams
+ ```
+
+1. Next, provide a series of values that are used in your application's **manifest.json** file:
+
+ ![generator opening screenshot](/microsoftteams/platform/assets/images/tab-images/teamsTabScreenshot.PNG)
+
+ **What is your solution name?**
+
+ This is your project name. You can accept the suggested name by selecting the **Enter** key.
+
+ **Where do you want to place the files?**
+
+ You are currently in your project directory. Select **Enter**.
+
+ **Title of your Microsoft Teams app project?**
+
+ This is your app package name and will be used in the app manifest and description. Enter a title or select **Enter** to accept the default name.
+
+ **Your (company) name? (max 32 characters)**
+
+ Your company name will be used in the app manifest. Enter a company name or select **Enter** to accept the default name.
+
+ **Which manifest version would you like to use?**
+
+ Select the default schema.
+
+ **Quick scaffolding? (Y/n)**
+
+ The default is yes; enter **n** to enter your Microsoft Partner Id.
+
+ **Enter your Microsoft Partner Id, if you have one? (Leave blank to skip)**
+
+ This field is not required and should only be used if you are already part of the [Microsoft Partner Network](https://partner.microsoft.com).
+
+ **What do you want to add to your project?**
+
+ Select **( &ast; ) A Tab**.
+
+ **The URL where you will host this solution?**
+
+ By default the generator suggests an Azure Web Sites URL. You are only testing your app locally, therefore, a valid URL is not necessary.
+
+ **Would you like show a loading indicator when your app/tab loads?**
+
+ Choose **not** to include a loading indicator when your app or tab loads. The default is no, enter **n**.
+
+ **Would you like personal apps to be rendered without a tab header-bar?**
+
+ Choose **not** to include personal apps to be rendered without a tab header-bar. Default is no, enter **n**.
+
+ **Would you like to include Test framework and initial tests? (y/N)**
+
+ Choose **not** to include a test framework for this project. The default is yes, enter **n**.
+
+ **Would you like to use Azure Applications Insights for telemetry? (y/N)**
+
+ Choose **not** to include [Azure Application Insights](/azure/azure-monitor/app/app-insights-overview). The default is no; enter **n**.
+
+ **Default Tab Name (max 16 characters)?**
+
+ Name your tab. This tab name is used throughout your project as a file or URL path component.
+
+ **What kind of Tab would you like to create?**
+
+ Use the arrow keys to select **Personal (static)**.
+
+ **Do you require Azure AD Single-Sign-On support for the tab?**
+
+ Choose **not** to include Azure AD Single-Sign-On support for the tab. The default is yes, enter **n**.
+
+ > [!IMPORTANT]
+ > The path component **yourDefaultTabNameTab** is the value that you entered in the generator for **Default Tab Name** plus the word **Tab**.
+ >
+ > For example: DefaultTabName: **MyTab** > **/MyTabTab/**
+
+### Add a personal tab
+
+**To add a personal tab to this application, create a content page, and update existing files**
+
+1. In your code editor, create a new HTML file, **personal.html** and add the following markup:
+
+ ```html
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8">
+ <title>
+ <!-- Todo: add your a title here -->
+ </title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <!-- inject:css -->
+ <!-- endinject -->
+ </head>
+ <body>
+ <h1>Personal Tab</h1>
+ <p><img src="/assets/icon.png"></p>
+ <p>This is your personal tab!</p>
+ </body>
+ </html>
+ ```
+
+1. Save **personal.html** in your application's **web** folder in the following location:
+
+ ```bash
+ ./src/app/web/<yourDefaultTabNameTab>/personal.html
+ ```
+
+1. Open **manifest.json** from the following location in your code editor:
+
+ ```bash
+ ./src/manifest/manifest.json/
+ ```
+
+1. Add the following to the empty `staticTabs` array (`staticTabs":[]`) and add the following JSON object:
+
+ ```json
+ {
+ "entityId": "personalTab",
+ "name": "Personal Tab ",
+ "contentUrl": "https://{{HOSTNAME}}/<yourDefaultTabNameTab>/personal.html",
+ "websiteUrl": "https://{{HOSTNAME}}",
+ "scopes": ["personal"]
+ }
+ ```
+
+1. Update the **contentURL** path component **yourDefaultTabNameTab** with your actual tab name.
+
+1. Save the updated **manifest.json** file.
+
+1. To provide your content page in an IFrame, open **Tab.ts** in your code editor from the following path:
+
+ ```bash
+ ./src/app/<yourDefaultTabNameTab>/<yourDefaultTabNameTab>.ts
+ ```
+
+1. Add the following to the list of IFrame decorators:
+
+ ```typescript
+ @PreventIframe("/<yourDefaultAppName>TabNameTab>/personal.html")
+ ```
+
+1. Save the updated **Tab.ts** file. Your tab code is complete.
+
+### Build and run your application
+
+At a command prompt, open your project directory to complete the next tasks.
+
+#### Create the app package
+
+You must have an app package to test your tab in Teams. It is a zip folder that contains the following required files:
+
+- A **full color icon** measuring 192 x 192 pixels.
+- A **transparent outline icon** measuring 32 x 32 pixels.
+- A **manifest.json** file that specifies the attributes of your app.
+
+The package is created through a gulp task that validates the manifest.json file and generates the zip folder in the **./package directory**. In the command prompt, enter the following command:
+
+```bash
+gulp manifest
+```
+
+#### Build your application
+
+The build command transpiles your solution into the **./dist** folder. Enter the following command in the command prompt:
+
+```bash
+gulp build
+```
+
+#### Run your application in localhost
+
+1. Start a local web server by entering the following in the command prompt:
+
+ ```bash
+ gulp serve
+ ```
+
+1. Enter `http://localhost:3007/<yourDefaultAppNameTab>/` in your browser, replace **<yourDefaultAppNameTab>** with your tab name, and view your application's home page as shown in the following image:
+
+ ![home page screenshot](~/assets/images/tab-images/homePage.png)
+
+1. To view your personal tab, go to `http://localhost:3007/<yourDefaultAppNameTab>/personal.html`.
+
+ >![Personal tab screenshot](/microsoftteams/platform/assets/images/tab-images/personalTab.PNG)
+
+### Establish a secure tunnel to your tab
+
+Microsoft Teams is a cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams does not allow local hosting. You must either publish your tab to a public URL or use a proxy that exposes your local port to an internet-facing URL.
+
+To test your tab extension, you can use [ngrok](https://ngrok.com/docs), which is built into this application. Ngrok is a reverse proxy software tool that creates a tunnel to your locally running web server's publicly-available HTTPS endpoints. Your server's web endpoints are available during the current session on your computer. When the computer is shut down or goes to sleep, the service is no longer available.
+
+In your command prompt, exit localhost and enter the following:
+
+```bash
+gulp ngrok-serve
+```
+
+> [!IMPORTANT]
+> After your tab has been uploaded to Microsoft Teams through **ngrok**, and successfully saved, you can view it in Teams until your tunnel session ends.
+
+### Upload your application to Teams
+
+**To upload your application to Teams**
+
+1. Go to Microsoft Teams. If you use the [web-based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+1. From the lower left corner, select **Apps**.
+1. From the lower left corner, choose **Upload a custom app**.
+1. Go to your project directory, browse to the **./package** folder, select the zip folder, and choose **Open**.
+
+ ![Adding your personal tab](../../assets/images/tab-images/addingpersonaltab.png)
+
+1. Select **Add** in the pop-up dialog box. Your tab is uploaded to Teams.
+
+ ![Personal tab uploaded](../../assets/images/tab-images/personaltabuploaded.png)
+
+### View your personal tab
+
+In the navigation bar located at the far left in Teams, select the ellipses &#x25CF;&#x25CF;&#x25CF; and choose your app from the list.
+
+# [ASP.NET Core](#tab/aspnetcore)
+
+### Create a custom personal tab using ASP.NET Core
+
+You can create a custom personal tab using C# and ASP.NET Core Razor pages. [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) is also used to finalize your app manifest and deploy your tab to Teams.
+
+### Prerequisites for personal tab
+
+You must have an understanding of the following prerequisites:
+
+- You must have an Office 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not have a Microsoft 365 account, you can sign up for a free subscription through the [Microsoft Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program). The subscription remains active as long as you are using it for ongoing development.
+
+- Use App Studio to import your application to Teams. To install App Studio, select **Apps** ![Store App](~/assets/images/tab-images/storeApp.png) at the lower left corner of the Teams app, and search for **App Studio**. After you find the tile, select it and choose **Add** in the pop-up dialog box to install it.
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- The current version of the Visual Studio IDE with the **.NET CORE cross-platform development** workload installed. If you do not already have Visual Studio, you can download and install the latest [Microsoft Visual Studio Community](https://visualstudio.microsoft.com/downloads) version for free.
+
+- The [ngrok](https://ngrok.com) reverse proxy tool. Use ngrok to create a tunnel to your locally running web server's publicly-available HTTPS endpoints. You can [download ngrok](https://ngrok.com/download).
+
+### Get the source code
+
+At a command prompt, create a new directory for your tab project. A simple project is provided to get you started. Clone the sample repository into your new directory using the following command:
+
+```bash
+git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
+```
+
+Alternately, you can retrieve the source code by downloading the zip folder and extracting the files.
+
+**To build and run the tab project**
+
+1. After you get the source code, go to Visual Studio and select **Open a project or solution**.
+1. Go to the tab application directory and open **PersonalTab.sln**.
+1. To build and run your application, press **F5** or choose **Start Debugging** from the **Debug** menu.
+1. In a browser, go to the following URLs to verify the application loaded properly:
+
+ - `http://localhost:44325/`
+ - `http://localhost:44325/personal`
+ - `http://localhost:44325/privacy`
+ - `http://localhost:44325/tou`
+
+### Review the source code
+
+#### Startup.cs
+
+This project was created from an ASP.NET Core 2.2 Web Application empty template with the **Advanced - Configure for HTTPS** check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template does not enable serving static content by default, so the static files middleware is added to the `Configure()` method using the following code:
+
+```csharp
+public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+ }
+public void Configure(IApplicationBuilder app)
+ {
+ app.UseStaticFiles();
+ app.UseMvc();
+ }
+```
+
+#### wwwroot folder
+
+In ASP.NET Core, the web root folder is where the application looks for static files.
+
+#### Index.cshtml
+
+ASP.NET Core treats files called **Index** as the default or home page for the site. When your browser URL points to the root of the site, **Index.cshtml** is displayed as the home page for your application.
+
+#### AppManifest folder
+
+This folder contains the following required app package files:
+
+- A **full color icon** measuring 192 x 192 pixels.
+- A **transparent outline icon** measuring 32 x 32 pixels.
+- A **manifest.json** file that specifies the attributes of your app.
+
+These files need to be zipped in an app package for use in uploading your tab to Teams. Microsoft Teams loads the `contentUrl` specified in your manifest, embeds it in an <iframe\>, and renders it in your tab.
+
+#### .csproj
+
+In the Visual Studio Solution Explorer window, right-click on the project and select **Edit Project File**. At the end of the file, you see the following code that creates and updates your zip folder when the application builds:
+
+```xml
+<PropertyGroup>
+ <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <EmbeddedResource Include="AppManifest\icon-outline.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\icon-color.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\manifest.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ </ItemGroup>
+```
+
+### Update your application for Teams
+
+#### _Layout.cshtml
+
+For your tab to display in Teams, you must include the **Microsoft Teams JavaScript client SDK** and include a call to `microsoftTeams.initialize()` after your page loads. This is how your tab and the Teams app communicate:
+
+Go to the **Shared** folder, open **_Layout.cshtml**, and add the following to the `<head>` tags section:
+
+```html
+<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
+<script src="https://statics.teams.cdn.office.net/sdk/v1.6.0/js/MicrosoftTeams.min.js"></script>
+```
+
+#### PersonalTab.cshtml
+
+Open **PersonalTab.cshtml** and update the embedded `<script>` tags by calling `microsoftTeams.initialize()`.
+
+Ensure you save your updated **PersonalTab.cshtml**.
+
+### Establish a secure tunnel to your tab for Teams
+
+Microsoft Teams is a cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams does not allow local hosting. You must either publish your tab to a public URL, or use a proxy that exposes your local port to an internet-facing URL.
+
+To test your tab, use [ngrok](https://ngrok.com/docs). Your server's web endpoints are available while ngrok is running on your computer. In the free version of ngrok, if you close ngrok, the URLs are different the next time you start it.
+
+**To establish a secure tunnel to your tab**
+
+1. At a command prompt in the root of your project directory, run the following command:
+
+ ```bash
+ ngrok http https://localhost:44325 -host-header="localhost:44325"
+ ```
+
+ Ngrok listens to requests from the internet and routes them to your application when it is running on port 44325. It resembles `https://y8rPrT2b.ngrok.io/` where **y8rPrT2b** is replaced by your ngrok alpha-numeric HTTPS URL.
+
+ Ensure that you keep the command prompt with ngrok running, and make a note of the URL.
+
+2. Verify that **ngrok** is running and working properly by opening your browser and going to your content page through the ngrok HTTPS URL that was provided in your command prompt window.
+
+> [!TIP]
+> You need to have both your application in Visual Studio and ngrok running to complete the steps provided in this article. If you need to stop running your application in Visual Studio to work on it, **keep ngrok running**. It listens and resumes routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service, it returns a new URL and you have to update every place that uses that URL.
+
+#### Run your application
+
+In Visual Studio, press **F5** or choose **Start Debugging** from your application's **Debug** menu.
+
+### Upload your tab with App Studio for Teams
+
+> [!NOTE]
+> **App Studio** can be used to edit your **manifest.json** file and upload the completed package to Teams. You can also manually edit **manifest.json**. If you do, ensure that you build the solution again to create the **Tab.zip** file to upload.
+
+**To upload your tab with App Studio**
+
+1. Go to Microsoft Teams. If you use the [web-based version](https://teams.microsoft.com), you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).
+
+1. Go to **App Studio** and select the **Manifest editor** tab.
+
+1. Select **Import an existing app** in the **Manifest editor** to begin updating the app package for your tab. The source code comes with its own partially complete manifest. The name of your app package is **tab.zip**. It is available from the following path:
+
+ ```bash
+ /bin/Debug/netcoreapp2.2/tab.zip
+ ```
+
+1. Upload **tab.zip** to **App Studio**.
+
+#### Update your app package with Manifest editor
+
+After you have uploaded your app package into App Studio, you must configure it.
+
+Select the tile for your newly imported tab in the right pane of the Manifest editor welcome page.
+
+There is a list of steps on the left side of the Manifest editor, and on the right, a list of properties that must have values for each of those steps. Much of the information has been provided by your **manifest.json** but there are fields that you must update.
+
+##### Details: App details
+
+In the **App details** section:
+
+1. Under **Identification**, select **Generate** to generate a new App ID for your app.
+
+1. Under **Developer information**, update **Website** with your **ngrok** HTTPS URL.
+
+ ![App URLs updated](../../assets/images/tab-images/appurls.png)
+
+1. Under **App URLs**, update the **Privacy statement** to `https://<yourngrokurl>/privacy` and **Terms of use** to `https://<yourngrokurl>/tou`>.
+
+##### Capabilities: Tabs
+
+In the **Tabs** section:
+
+1. Under **Add a personal tab**, select **Add**. A pop-up dialog box appears.
+
+1. Enter a name for the personal tab in **Name**.
+
+1. Enter the **Entity ID**.
+
+1. Update **Content URL** with `https://<yourngrokurl>/personalTab`.
+
+ Leave the **Website URL** field blank.
+
+ ![Personal tab details](../../assets/images/tab-images/personaltabdetails.png)
+
+1. Select **Save**.
+
+##### Finish: Domains and permissions
+
+In the **Domains and permissions** section, **Domains from your tabs** must contain your ngrok URL without the HTTPS prefix `<yourngrokurl>.ngrok.io/`.
+
+###### Finish: Test and distribute
+
+> [!IMPORTANT]
+> On the right, in **Description**, you see the following warning:
+>
+> &#9888; **The 'validDomains' array cannot contain a tunneling site...**
+>
+> This warning can be ignored while testing your tab.
+
+1. In the **Test and Distribute** section, select **Install**.
+
+1. In the pop-up dialog box, select **Add** and your tab is displayed.
+
+ ![Personal tab ASPNET uploaded](../../assets/images/tab-images/personaltabaspnetuploaded.png)
+
+### View your personal tab in Teams
+
+1. In the navigation bar located at the far left of the Teams app, select the ellipses &#x25CF;&#x25CF;&#x25CF;. A list of personal apps is shown.
+
+1. Select your tab from the list to view it.
+
+# [ASP.NET Core MVC](#tab/aspnetcoremvc)
+
+### Create a custom personal tab with ASP.NET Core MVC
+
+You can create a custom personal tab using C# and ASP.NET Core MVC. [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) is also used to finalize your app manifest and deploy your tab to Teams.
+
+### Prerequisites for personal tab with ASP.NET Core MVC
+
+- You must have a Microsoft 365 tenant and a team configured with **Allow uploading custom apps** enabled. For more information, see [prepare your Office 365 tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md).
+
+ > [!NOTE]
+ > If you do not have a Microsoft 365 account, you can sign up for a free subscription through the [Microsoft Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program). The subscription remains active as long as you are using it for ongoing development.
+
+- Use App Studio to import your application to Teams. To install App Studio, select **Apps** ![Store App](~/assets/images/tab-images/storeApp.png) at the lower left corner of the Teams app, and search for **App Studio**. After you find the tile, select it and choose **Add** in the pop-up dialog box to install it.
+
+In addition, this project requires that you have the following installed in your development environment:
+
+- The current version of the Visual Studio IDE with the **.NET CORE cross-platform development** workload installed. If you do not already have Visual Studio, you can download and install the latest [Microsoft Visual Studio Community](https://visualstudio.microsoft.com/downloads) version for free.
+
+- The [ngrok](https://ngrok.com) reverse proxy tool. Use ngrok to create a tunnel to your locally running web server's publicly-available HTTPS endpoints. You can [download ngrok](https://ngrok.com/download).
+
+### Get the source code
+
+At a command prompt, create a new directory for your tab project. A simple project is provided to get you started. Clone the sample repository into your new directory using the following command:
+
+``` bash
+git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
+```
+
+Alternately, you can retrieve the source code by downloading the zip folder and extracting the files.
+
+**To build and run the tab project**
+
+1. After you have the source code, go to Visual Studio and select **Open a project or solution**.
+1. Go to the tab application directory and open **PersonalTabMVC.sln**.
+1. To build and run your application, press **F5** or choose **Start Debugging** from the **Debug** menu.
+1. In a browser, go to the following URLs to verify that the application loaded properly:
+
+ * `http://localhost:44335`
+ * `http://localhost:44335/privacy`
+ * `http://localhost:44335/tou`
+
+### Review the source code
+
+#### Startup.cs
+
+This project was created from an ASP.NET Core 2.2 Web Application empty template with the **Advanced - Configure for HTTPS** check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template does not enable serving static content by default, so the static files middleware is added to the `Configure()` method using the following code:
+
+``` csharp
+public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+ }
+public void Configure(IApplicationBuilder app)
+ {
+ app.UseStaticFiles();
+ app.UseMvc();
+ }
+```
+
+#### wwwroot folder
+
+In ASP.NET Core, the web root folder is where the application looks for static files.
+
+#### AppManifest folder
+
+This folder contains the following required app package files:
+
+* A **full color icon** measuring 192 x 192 pixels.
+* A **transparent outline icon** measuring 32 x 32 pixels.
+* A **manifest.json** file that specifies the attributes of your app.
+
+These files need to be zipped in an app package for use in uploading your tab to Teams. Microsoft Teams loads the `contentUrl` specified in your manifest, embeds it in an IFrame, and renders it in your tab.
+
+#### .csproj
+
+In the Visual Studio Solution Explorer window, right-click on the project and select **Edit Project File**. At the end of the file, you see the following code that creates and updates your zip folder when the application builds:
+
+``` xml
+<PropertyGroup>
+ <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <EmbeddedResource Include="AppManifest\icon-outline.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\icon-color.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ <EmbeddedResource Include="AppManifest\manifest.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </EmbeddedResource>
+ </ItemGroup>
+```
+
+#### Models
+
+**PersonalTab.cs** presents a Message object and methods that are called from **PersonalTabController** when a user selects a button in the **PersonalTab** View.
+
+#### Views
+
+These are the different views in ASP.NET Core MVC:
+
+* Home: ASP.NET Core treats files called **Index** as the default or home page for the site. When your browser URL points to the root of the site, **Index.cshtml** is displayed as the home page for your application.
+
+* Shared: The partial view markup **_Layout.cshtml** contains the application's overall page structure and shared visual elements. It also references the Teams Library.
+
+#### Controllers
+
+The controllers use the `ViewBag` property to transfer values dynamically to the Views.
+++
+**To run ngrok and verify the content page**
+
+1. At a command prompt in the root of your project directory, run the following command:
+
+ ``` bash
+ ngrok http https://localhost:44345 -host-header="localhost:44345"
+ ```
+
+ Ngrok listens to requests from the internet and routes them to your application when it is running on port 44325. It resembles `https://y8rPrT2b.ngrok.io/` where **y8rPrT2b** is replaced by your ngrok alpha-numeric HTTPS URL.
+
+ Ensure you keep the command prompt with ngrok running, and make a note of the URL.
+
+1. Verify that **ngrok** is running and working properly by opening your browser and going to your content page through the ngrok HTTPS URL that was provided in your command prompt window.
+
+> [!TIP]
+> You need to have both your application in Visual Studio and ngrok running to complete the steps provided in this article. If you need to stop running your application in Visual Studio to work on it, **keep ngrok running**. It listens and resumes routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service it returns a new URL and you have to update every place that uses that URL.
+
+#### Run your application
+
+In Visual Studio, press **F5** or choose **Start Debugging** from your application's **Debug** menu.
++++
+## Reorder static personal tabs
+
+Starting with manifest version 1.7, developers can rearrange all tabs in their personal app. In particular, a developer can move the **bot chat** tab, which always defaults to the first position, anywhere in the personal app tab header. Two reserved tab `entityId` keywords are declared, **conversations** and **about**.
+
+If you create a bot with a **personal** scope, it appears in the first tab position in a personal app by default. If you want to move it to another position, you must add a static tab object to your manifest with the reserved keyword, **conversations**. The **conversation** tab appears on web or desktop depending on where you add the **conversation** tab in the `staticTabs` array.
+
+```json
+{
+ "staticTabs":[
+ {
+
+ },
+ {
+ "entityId":"conversations",
+ "scopes":[
+ "personal"
+ ]
+ }
+ ]
+}
+```
+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
platform Configuration Page https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/create-tab-pages/configuration-page.md
A configuration page is a special type of [content page](content-page.md). The users configure some aspects of the Microsoft Teams app using the configuration page and use that configuration as part of the following:
-* A channel or group chat tab: Collect information from the users and set the `contentUrl` of the content page to display.
+* A channel or group chat tab: Collect information from the users and set the `contentUrl` of the content page to be displayed.
* A [messaging extension](~/messaging-extensions/what-are-messaging-extensions.md). * An [Office 365 Connector](~/webhooks-and-connectors/what-are-webhooks-and-connectors.md).
-## Configuring a channel or group chat tab
+## Configure a channel or group chat tab
-The application must reference the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) and call `microsoft.initialize()`. Also, the URLs used must be secured HTTPS endpoints and available from the cloud.
+The application must reference the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) and call `microsoft.initialize()`. The URLs used must be secured HTTPS endpoints and available from the cloud.
### Example
-An example of a configuration page is shown in the following image:
+An example of a configuration page is shown in the following image:
<img src="~/assets/images/tab-images/configuration-page.png" alt="Configuration page" width="400"/>
-The corresponding code for configuration page is shown in the following section:
+The following code is an example of corresponding code for the configuration page:
```html <head>
The corresponding code for configuration page is shown in the following section:
... ```
-Choose either **Select Gray** or **Select Red** button in the configuration page, to display the tab content with a gray or red icon.
+Choose either **Select Gray** or **Select Red** button in the configuration page, to display the tab content with a gray or red icon.
-The following image displays the tab content with gray icon:
+The following image displays the tab content with a gray icon:
<img src="~/assets/images/tab-images/configure-tab-with-gray.png" alt="Configure tab with select gray" width="400"/>
-The following image displays the tab content with red icon:
+The following image displays the tab content with a red icon:
<img src="~/assets/images/tab-images/configure-tab-with-red.png" alt="Configure tab with select red" width="400"/>
-Choosing the relative button triggers either `saveGray()` or `saveRed()`, and invokes the following:
+Choosing the appropriate button triggers either `saveGray()` or `saveRed()`, and invokes the following:
-1. The `settings.setValidityState(true)` is set to true.
-1. The `microsoftTeams.settings.registerOnSaveHandler()` event handler is triggered.
-1. The **Save** button on the app's configuration page, uploaded in Teams, is enabled.
+* Set `settings.setValidityState(true)` to true.
+* The `microsoftTeams.settings.registerOnSaveHandler()` event handler is triggered.
+* **Save** on the app's configuration page, is enabled.
-The configuration page code informs the Teams that the configuration requirements are satisfied and the installation can proceed. When the user selects **Save**, the parameters of `settings.setSettings()` are set, as defined by the `Settings` interface. For more information, see [Settings interface](/javascript/api/@microsoft/teams-js/microsoftteams.settings.settings?view=msteams-client-js-latest&preserve-view=true). In the last step, `saveEvent.notifySuccess()` is called to indicate that the content URL has successfully resolved.
+The configuration page code informs Teams that the configuration requirements are satisfied and the installation can proceed. When the user selects **Save**, the parameters of `settings.setSettings()` are set, as defined by the `Settings` interface. For more information, see [settings interface](/javascript/api/@microsoft/teams-js/microsoftteams.settings.settings?view=msteams-client-js-latest&preserve-view=true). `saveEvent.notifySuccess()` is called to indicate that the content URL has successfully resolved.
>[!NOTE] > >* If you register a save handler using `microsoftTeams.settings.registerOnSaveHandler()`, the callback must invoke `saveEvent.notifySuccess()` or `saveEvent.notifyFailure()` to indicate the outcome of the configuration.
->* If you don't register a save handler, the `saveEvent.notifySuccess()` call is made automatically when the user selects **Save**.
+>* If you do not register a save handler, the `saveEvent.notifySuccess()` call is made automatically when the user selects **Save**.
### Get context data for your tab settings
-Your tab might require contextual information to display relevant content. Contextual information further enhances your tab's appeal by providing a more customized user experience.
+Your tab requires contextual information to display relevant content. Contextual information further enhances your tab's appeal by providing a more customized user experience.
-For more information on the properties used for tab configuration, see [Context interface](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true). Collect the values of context data variables in the following two ways:
+For more information on the properties used for tab configuration, see [context interface](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true). Collect the values of context data variables in the following two ways:
-1. Insert URL query string placeholders in your manifest's `configurationURL`.
+* Insert URL query string placeholders in your manifest's `configurationURL`.
-1. Use the [Teams SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) `microsoftTeams.getContext((context) =>{})` method.
+* Use the [Teams SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) `microsoftTeams.getContext((context) =>{})` method.
#### Insert placeholders in the `configurationUrl`
Add context interface placeholders to your base `configurationUrl`. For example:
... ```
-After your page uploads, the Teams updates the query string placeholders with relevant values. Include logic in the configuration page to retrieve and use those values. For more information on working with URL query strings, see [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) in MDN Web Docs. The following example describes the way to extract a value from the `configurationUrl` property:
+After your page uploads, Teams updates the query string placeholders with relevant values. Include logic in the configuration page to retrieve and use those values. For more information on working with URL query strings, see [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) in MDN Web Docs. The following code example provides the way to extract a value from the `configurationUrl` property:
```html <script>
document.write(getId());
### Use the `getContext()` function to retrieve context
-The `microsoftTeams.getContext((context) => {})` function retrieves the [Context interface](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true) when invoked. Add this function to the configuration page to retrieve context values:
+The `microsoftTeams.getContext((context) => {})` function retrieves the [context interface](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true) when invoked.
+
+The following code provides an example of adding this function to the configuration page to retrieve context values:
```html <!-- `userPrincipalName` will render in the span with the id "user". -->
The `microsoftTeams.getContext((context) => {})` function retrieves the [Context
## Context and authentication
- Authenticate before allowing a user to configure your app. Otherwise, your content might include sources that have their authentication protocols. For more information, see [Authenticate a user in a Microsoft Teams tab](~/tabs/how-to/authentication/auth-flow-tab.md). Use context information to construct the authentication requests and authorization page URLs.
-Ensure that all domains used in your tab pages are listed in the `manifest.json` and `validDomains` array.
+Authenticate before allowing a user to configure your app. Otherwise, your content might include sources that have their authentication protocols. For more information, see [authenticate a user in a Microsoft Teams tab](~/tabs/how-to/authentication/auth-flow-tab.md). Use context information to construct the authentication requests and authorization page URLs. Ensure that all domains used in your tab pages are listed in the `manifest.json` and `validDomains` array.
## Modify or remove a tab
-Supported removal options further refine the user experience. Set your manifest's `canUpdateConfiguration` property to `true`, that enables the users to modify, reconfigure, or rename a group or channel tab. Also, indicate what happens to the content when a tab is removed, by including a removal options page in the app and setting a value for the `removeUrl` property in the `setSettings()` configuration. The user can uninstall the Personal tabs but cannot modify them. For more information, see [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md).
+Set your manifest's `canUpdateConfiguration` property to `true`, that enables the users to modify, reconfigure, or rename a channel or group tab. Also, indicate what happens to the content when a tab is removed, by including a removal options page in the app and setting a value for the `removeUrl` property in the `setSettings()` configuration. The user can uninstall personal tabs but cannot modify them. For more information, see [create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md).
-Microsoft Teams setSettings() configuration for removal page:
+Microsoft Teams `setSettings()` configuration for removal page:
```javascript microsoftTeams.settings.setSettings({
microsoftTeams.settings.setSettings({
## Mobile clients If you choose to have your channel or group tab appear on the Teams mobile clients, the `setSettings()` configuration must have a value for `websiteUrl`. For more information, see [guidance for tabs on mobile](~/tabs/design/tabs-mobile.md).+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
platform Content Page https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/create-tab-pages/content-page.md
localization_priority: Normal
+ # Create a content page for your tab
-A content page is a webpage that is rendered within the Teams client. Typically these are part of:
+A content page is a webpage that is rendered within the Teams client. These are part of:
-* A personal-scoped custom tab: In this instance the content page is the first page the user encounters.
-* A channel/group custom tab: After the user pins and configures the tab in the appropriate context, the content page is displayed.
-* A [task module](~/task-modules-and-cards/what-are-task-modules.md): You can create a content page and embed it as a webview inside a task module. The page will be rendered inside the modal popup.
+* A personal-scoped custom tab: In this case, the content page is the first page the user encounters.
+* A channel or group custom tab: The content page is displayed after the user pins and configures the tab in the appropriate context.
+* A [task module](~/task-modules-and-cards/what-are-task-modules.md): You can create a content page and embed it as a webview inside a task module. The page is rendered inside the modal pop-up.
-This article is specific to using content pages as tabs; however the majority of the guidance here would apply regardless of how the content page is presented to the end-user.
+This article is specific to using content pages as tabs; however the majority of the guidance here applies regardless of how the content page is presented to the user.
## Tab content and design guidelines
-Your tab's overall objective should be to provide access to meaningful and engaging content that has a practical value and an evident purpose. That does not mean that you should forego a pleasing style, but you should focus on minimizing clutter by making your tab design clean, navigation intuitive, and content immersive.
+Your tab's overall objective is to provide access to meaningful and engaging content that has practical value and an evident purpose. You must focus on making your tab design clean, navigation intuitive, and content immersive.
-For more information, see the [tab design guidelines](~/tabs/design/tabs.md) and [Microsoft Teams store validation guidelines](~/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md)
+For more information, see [tab design guidelines](~/tabs/design/tabs.md) and [Microsoft Teams store validation guidelines](~/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md).
## Integrate your code with Teams
-For your page to display in Teams, you must include the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) and include a call to `microsoftTeams.initialize()` after your page loads. That is how your page and the Teams client communicate:
+For your page to display in Teams, you must include the [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client?view=msteams-client-js-latest&preserve-view=true) and include a call to `microsoftTeams.initialize()` after your page loads.
+
+The following code provides an example of how your page and the Teams client communicate:
```html <!DOCTYPE html>
For your page to display in Teams, you must include the [Microsoft Teams JavaScr
</body> ```
-## Accessing additional content
-
-### Using the SDK to interact with Teams
+## Access additional content
-The [Teams client JavaScript SDK](~/tabs/how-to/using-teams-client-sdk.md) provides many additional functions you may find useful while developing your content page.
-
-### Deep links
+You can access additional content by using the SDK to interact with Teams, creating deep links, using task modules, and verifying if URL domains are included in the `validDomains` array.
-You can create deep links to entities in Teams. Typically, these are used to create links that navigate to content and information within your tab. For more information, see [Create deep links to content and features in Microsoft Teams](~/concepts/build-and-test/deep-links.md).
+### Use the SDK to interact with Teams
-### Task Modules
+The [Teams client JavaScript SDK](~/tabs/how-to/using-teams-client-sdk.md) provides many additional functions that you can find useful while developing your content page.
-A task module is a modal popup-like experience that you can trigger from your tab. Typically in a content page you do not want to navigate your user through multiple pages. Instead, you will use task modules to present forms for gathering additional information, displaying the details of an item in a list, or any other time you need to present the user with additional information. The task modules themselves can be additional content pages, or created completely using Adaptive Cards. See [Using task modules in tabs](~/task-modules-and-cards/task-modules/task-modules-tabs.md) for complete information.
+### Deep links
-### Valid Domains
+You can create deep links to entities in Teams. These are used to create links that navigate to content and information within your tab. For more information, see [create deep links to content and features in Teams](~/concepts/build-and-test/deep-links.md).
-Ensure that the all URL domains used in your tabs are included in the `validDomains` array in your [manifest](~/concepts/build-and-test/apps-package.md). For more information, see [validDomains](~/resources/schem#validdomains) in the manifest schema reference. However, be mindful that the core functionality of your tab exists within Teams and not outside of Teams.
+### Task modules
-## Reorder static personal tabs
+A task module is a modal pop-up experience that you can trigger from your tab. In a content page, you can use task modules to present forms for gathering additional information, displaying the details of an item in a list, or presenting the user with additional information. The task modules themselves can be additional content pages, or created completely using Adaptive Cards. For more information, see [using task modules in tabs](~/task-modules-and-cards/task-modules/task-modules-tabs.md).
-Starting with manifest version 1.7, developers can rearrange all tabs in their personal app. In particular, a developer can move the *bot chat* tab, which always defaults to the first position, anywhere in the personal app tab header. WeΓÇÖve declared two reserved tab entityId keywords, *conversations* and *about*.
+### Valid domains
-If you create a bot with a *personal* scope, it will show up in the first tab position in a personal app by default. If you wish to move it to another position, you must add a static tab object to your manifest with the reserved keyword, *conversations*. The *conversation* tab appears on web or desktop based on where you add the *conversation* tab in the `staticTabs` array.
+Ensure that all URL domains used in your tabs are included in the `validDomains` array in your [manifest](~/concepts/build-and-test/apps-package.md). For more information, see [validDomains](~/resources/schem#validdomains) in the manifest schema reference.
-```json
-{
- "staticTabs":[
- {
-
- },
- {
- "entityId":"conversations",
- "scopes":[
- "personal"
- ]
- }
- ]
-}
-```
+> [!NOTE]
+> The core functionality of your tab exists within Teams and not outside of Teams.
## Show a native loading indicator
-Starting with [manifest schema v1.7](../../../resources/schem).
+Starting with [manifest schema v1.7](../../../resources/schem).
> [!NOTE]
-> * The behavior on mobile clients is not configurable through this manifest property. Mobile clients show a native loading indicator by default across content pages and iframe-based task modules. This indicator on mobile is shown when a request is made to fetch content and gets dismissed as soon as the request gets completed.
-> * If you indicate `"showLoadingIndicator : true` in your app manifest, then all tab configuration, content, and removal pages and all iframe-based task modules must follow the mandatory protocol, below:
+> * The behavior on mobile clients is not configurable through the native loading indicator property. Mobile clients show this indicator by default across content pages and iframe-based task modules. This indicator on mobile is shown when a request is made to fetch content and gets dismissed as soon as the request gets completed.
+
+If you indicate `showLoadingIndicator : true` in your app manifest, then all tab configuration, content, and removal pages and all iframe-based task modules must follow these steps:
**To show the loading indicator**
-* Add `"showLoadingIndicator": true` to your manifest.
-* Remember to call `microsoftTeams.initialize();`.
-* **Optional**: If you're ready to print to the screen and wish to lazy load the rest of your application's content, you can manually hide the loading indicator by calling `microsoftTeams.appInitialization.notifyAppLoaded();`
-* **Mandatory**: Finally, call `microsoftTeams.appInitialization.notifySuccess()` to notify Teams that your app has successfully loaded. Teams will then hide the loading indicator if applicable. If `notifySuccess` is not called within 30 seconds, it will be assumed that your app timed out and an error screen with a retry option will appear.
-* If your application fails to load, you can call `microsoftTeams.appInitialization.notifyFailure(reason);` to let Teams know there was an error. An error screen will then be shown to the user:
+1. Add `"showLoadingIndicator": true` to your manifest.
+1. Call `microsoftTeams.initialize();`.
+1. As a **mandatory** step, call `microsoftTeams.appInitialization.notifySuccess()` to notify Teams that your app has successfully loaded. Teams then hides the loading indicator, if applicable. If `notifySuccess` is not called within 30 seconds, it is assumed that your app timed out and an error screen with a retry option appears.
+1. **Optionally**, if you are ready to print to the screen and wish to lazy load the rest of your application's content, you can manually hide the loading indicator by calling `microsoftTeams.appInitialization.notifyAppLoaded();`.
+1. If your application fails to load, you can call `microsoftTeams.appInitialization.notifyFailure(reason);` to let Teams know there was an error. An error screen is shown to the user. The following code provides an example of application failure reasons:
```typescript
- ``
/* List of failure reasons */ export const enum FailedReason { AuthFailed = "AuthFailed",
Starting with [manifest schema v1.7](../../../resources/schema/manifest-schema.m
Other = "Other" } ```
- >
+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
platform Removal Page https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/create-tab-pages/removal-page.md
localization_priority: Normal
-# Modify or remove a channel group tab
+# Create a removal page
-You can extend and enhance the user experience by supporting removal and modification options in your app. Teams enables users to rename or remove a channel/group tab and you can permit users to reconfigure your tab after installation. Additionally, your tab removal experience can include designating what happens to the content when your tab is removed or giving users post-removal options such as deleting or archiving the content.
+You can extend and enhance the user experience by supporting removal and modification options in your app. Teams enables users to rename or remove a channel or group tab and you can permit users to reconfigure your tab after installation. Additionally, the tab removal experience provides the users with post-removal options to delete or archive content.
## Enable your tab to be reconfigured after installation
-Your **manifest.json** defines your tab's features and capabilities. The tab instance `canUpdateConfiguration` property takes a Boolean value that indicates whether a user can modify or reconfigure the tab after it is created:
+Your **manifest.json** defines your tab's features and capabilities. The tab instance `canUpdateConfiguration` property takes a Boolean value that indicates whether a user can modify or reconfigure the tab after it is created. The following table provides the property details:
|Name| Type| Maximum size | Required | Description| ||||||
-|`canUpdateConfiguration`|Boolean|||A value indicating whether an instance of the tab's configuration can be updated by the user after creation. Default: `true`|
+|`canUpdateConfiguration`|Boolean|||A value indicating whether an instance of the tab's configuration can be updated by the user after creation. Default is `true`. |
-When your tab is uploaded to a channel or group chat, Teams will add a right-click drop-down menu for your tab. The available options are determined by the `canUpdateConfiguration` setting:
+When your tab is uploaded to a channel or group chat, Teams adds a right-click drop-down menu for your tab. The available options are determined by the `canUpdateConfiguration` setting. The following table provides the setting details:
| `canUpdateConfiguration`| true | false | description | | -- | :-: | -- | -- |
-| Settings | √ | |The `configurationUrl` page is reloaded in an IFrame allowing the user to reconfigure the tab. |
+| Settings | √ | |The `configurationUrl` page is reloaded in an IFrame allowing the user to reconfigure the tab. |
| Rename | √ | √ | The user can change the tab name as it appears in the tab bar. |
-| Remove | √ | √ | If the `removeURL` property and value are included in the **configuration page**, the **removal page** is loaded into an IFrame and presented to the user. If a removal page is not included the user is presented with a confirm dialog box. |
-|||||
+| Remove | √ | √ | If the `removeURL` property and value are included in the **configuration page**, the **removal page** is loaded into an IFrame and presented to the user. If a removal page is not included, the user is presented with a confirm dialog box. |
## Create a tab removal page for your application
-The optional removal page is an HTML page that you host and is displayed when the tab is removed. The removal page URL is designated by the `setSettings()` method within your configuration page. As with all pages in your app, the removal page must comply with [Teams tab requirements](../../../tabs/how-to/tab-requirements.md).
+The optional removal page is an HTML page that you host and is displayed when the tab is removed. The removal page URL is designated by the `setSettings()` method within your configuration page. As with all pages in your app, the removal page must comply with [Teams tab prerequisites](../../../tabs/how-to/tab-requirements.md).
### Register a remove handler
-Optionally, within your removal page logic, you can invoke the `registerOnRemoveHandler((RemoveEvent) => {}` event handler when the user removes an existing tab configuration. The method takes in the [`RemoveEvent`](/javascript/api/@microsoft/teams-js/microsoftteams.settings.removeevent?view=msteams-client-js-latest&preserve-view=true) interface and executes the code in the handler when a user attempts to remove content. It is used to perform cleanup operations such as removing the underlying resource powering the tab content. Only one remove handler can be registered at a time.
+Optionally, within your removal page logic, you can invoke the `registerOnRemoveHandler((RemoveEvent) => {}` event handler when the user removes an existing tab configuration. The method takes in the [`RemoveEvent`](/javascript/api/@microsoft/teams-js/microsoftteams.settings.removeevent?view=msteams-client-js-latest&preserve-view=true) interface and executes the code in the handler when a user attempts to remove content. The method is used to perform cleanup operations such as removing the underlying resource powering the tab content. At a time only one remove handler can be registered.
The `RemoveEvent` interface describes an object with two methods: * The `notifySuccess()` function is required. It indicates that the removal of the underlying resource succeeded and its content can be removed.
-* The `notifyFailure(string)` function is optional. It indicates that removal of the underlying resource failed and its content cannot be removed. The optional string parameter specifies a reason for the failure. If provided, this string is displayed to the user; otherwise a generic error is displayed.
+* The `notifyFailure(string)` function is optional. It indicates that removal of the underlying resource failed and its content cannot be removed. The optional string parameter specifies a reason for the failure. If provided, this string is displayed to the user; else a generic error is displayed.
#### Use the `getSettings()` function
-You can use `getSettings()`to designate the tab content to be removed. The `getSettings((Settings) =>{})` function takes in the [`Settings interface`](/javascript/api/@microsoft/teams-js/microsoftteams.settings.settings?view=msteams-client-js-latest&preserve-view=true) and provides the valid settings property values that can be retrieved.
+You can use `getSettings()`to assign the tab content to be removed. The `getSettings((Settings) =>{})` function takes in the [`Settings interface`](/javascript/api/@microsoft/teams-js/microsoftteams.settings.settings?view=msteams-client-js-latest&preserve-view=true) and provides the valid settings property values that can be retrieved.
#### Use the `getContext()` function
-You can use `getContext()` to retrieves the current context in which the frame is running. The `getContext((Context) =>{})` function takes in the [`Context interface`](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true) and provides valid `Context` property values that you can use in your removal page logic to determine the content to display in the removal page.
+You can use `getContext()` to get the current context in which the frame is running. The `getContext((Context) =>{})` function takes in the [`Context interface`](/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest&preserve-view=true). The function provides valid `Context` property values that you can use in your removal page logic to determine the content to display in the removal page.
#### Include authentication
-You might require authentication before allowing a user to delete the tab content. Context information can be used to help construct authentication requests and authorization page URLs. See [Microsoft Teams authentication flow for tabs](~/tabs/how-to/authentication/auth-flow-tab.md). Make sure that all domains used in your tab pages are listed in the `manifest.json` `validDomains` array.
+Authentication is required before allowing a user to delete the tab content. Context information can be used to help construct authentication requests and authorization page URLs. See [Microsoft Teams authentication flow for tabs](~/tabs/how-to/authentication/auth-flow-tab.md). Make sure that all domains used in your tab pages are listed in the `manifest.json` `validDomains` array.
-Below is a sample tab removal code block:
+The following is a sample tab removal code block:
```html <body>
Below is a sample tab removal code block:
```
-When a user selects **Remove** from the tab's drop-down menu, Teams will load the optional `removeUrl` page (designated in your **configuration page**) into an IFrame. Here, the user is presented with a button loaded with the `onClick()` function that calls `microsoftTeams.settings.setValidityState(true)` and enables the **Remove** button located near the bottom of the removal page IFrame.
+When a user selects **Remove** from the tab's drop-down menu, Teams loads the optional `removeUrl` page assigned in your **configuration page**, into an IFrame. The user is shown a button loaded with the `onClick()` function that calls `microsoftTeams.settings.setValidityState(true)` and enables the **Remove** button shown at the bottom of the removal page IFrame.
-Following the execution of the remove handler, `removeEvent.notifySuccess()` or `removeEvent.notifyFailure()` notifies Teams of the content removal outcome.
+After the remove handler is executed, `removeEvent.notifySuccess()` or `removeEvent.notifyFailure()` notifies Teams of the content removal outcome.
>[!NOTE]
-> * To ensure that an authorized user's control over a tab is not inhibited, Teams will remove the tab in both success and failure cases.\
-> * Teams enables the **Remove** button after 5 seconds, even if your tab hasn't called `setValidityState()`.\
-> * When the user selects **Remove** Teams removes the tab after 30 seconds regardless of whether your actions have completed.
+> * To ensure that an authorized user's control over a tab is not inhibited, Teams removes the tab in both success and failure cases.
+> * Teams enables the **Remove** button after five seconds, even if your tab has not called `setValidityState()`.
+> * When the user selects **Remove**, Teams removes the tab after 30 seconds regardless of whether the actions have been completed or not.
+
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Tabs on mobile](~/tabs/design/tabs-mobile.md)
platform Tab Requirements https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/how-to/tab-requirements.md
Title: Tab requirements
+ Title: Prerequisites
description: Every tab in Microsoft Teams must adhere to these requirements. keywords: teams tabs group channel configurable
-# Tab requirements
+# Prerequisites
-Teams tabs must adhere to the following requirements:
+Teams tabs must adhere to the following prerequisites:
-* You must allow your tab pages to be served in an iFrame, using X-Frame-Options and Content-Security-Policy HTTP response headers.
+* You must allow your tab pages to be shown in an iFrame, using X-Frame-Options and Content-Security-Policy HTTP response headers.
* Set header: `Content-Security-Policy: frame-ancestors teams.microsoft.com *.teams.microsoft.com *.skype.com` * For Internet Explorer 11 compatibility, set `X-Content-Security-Policy`. * Alternately, set header `X-Frame-Options: ALLOW-FROM https://teams.microsoft.com/`. This header is deprecated but still accepted by most browsers.
-* Typically, as a safeguard against click-jacking, login pages do not render in iFrames. Your authentication logic needs to use a method other than redirect. For example, use token-based or cookie-based authentication.
+
+* Typically, as a safeguard against clickjacking, login pages do not render in iFrames. Your authentication logic needs to use a method other than redirect. For example, use token-based or cookie-based authentication.
> [!NOTE]
- > Chrome 80, scheduled for release in early 2020, introduces new cookie values and imposes cookie policies by default. It is recommended that you set the intended use for your cookies rather than rely on default browser behavior. For more information, see [SameSite cookie attribute 2020 update](../../resources/samesite-cookie-update.md).
+ > Chrome 80, scheduled for release in early 2020, introduces new cookie values and imposes cookie policies by default. It is recommended that you set the intended use for your cookies rather than rely on default browser behavior. For more information, see [SameSite cookie attribute](../../resources/samesite-cookie-update.md).
-* Browsers adhere to a same-origin policy restriction that prevents a webpage from making requests to a different domain than the one that served a web page. However, you can redirect the configuration or content page to another domain or subdomain. Your cross-domain navigation logic must allow the Teams client to validate the origin against a static validDomains list in the app manifest when loading or communicating with the tab.
+* Browsers adhere to a same-origin policy restriction. It prevents webpages from making requests to different domains than the served web page. However, you can redirect the configuration or content page to another domain or subdomain. Your cross-domain navigation logic must allow the Teams client to validate the origin against a static `validDomains` list in the app manifest when loading or communicating with the tab.
-* To create a seamless experience, you must style your tabs based on the Teams client's theme, design, and intent. Typically, tabs work best when they are built to address a specific need and focus on a small set of tasks or a subset of data that is relevant to the tab's channel location.
+* You must style your tabs based on the Teams client's theme, design, and intent. Typically, tabs work best when they are built to address a specific need and focus on a small set of tasks or a subset of data that is relevant to the tab's channel location.
* Within your content page, add a reference to [Microsoft Teams JavaScript client SDK](/javascript/api/overview/msteams-client) using script tags. After your page loads, make a call to `microsoftTeams.initialize()`, otherwise your page is not displayed.
-* For authentication to work on mobile clients, you must upgrade you Teams JavaScript SDK to at least version 1.4.1.
+* For authentication to work on mobile clients, you must upgrade Teams JavaScript SDK to at least version 1.4.1.
* If you choose to have your channel or group tab appear on Teams mobile clients, the `setSettings()` configuration must have a value for the `websiteUrl` property. * MS Teams tab does not support the ability to load intranet websites that use self-signed certificates.
+## See also
+
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tabs link unfurling and Stage View](~/tabs/tabs-link-unfurling.md)
+* [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+ ## Next step > [!div class="nextstepaction"]
-> [Create a custom personal tab using Node.js and the Yeoman Generator for Microsoft Teams](~/tabs/quickstarts/create-personal-tab-node-yeoman.md)
+> [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
platform Create Channel Group Tab Dotnet Core Mvc https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-channel-group-tab-dotnet-core-mvc.md
- Title: "Create a Channel and Group Tab with ASP.NET Core MVC" -
-description: A quickstart guide to creating a custom channel and group tab with ASP.NET Core MVC
-localization_priority: Normal
---
-# Create a Custom Channel and Group Tab with ASP.NET Core MVC
-
-In this quickstart we'll walk-through creating a custom channel/group tab with C# and ASP.Net Core MVC. We'll also use [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) to finalize your app manifest and deploy your tab to Teams.
--
-## Get the source code
-
-Open a command prompt and create a new directory for your tab project. We have provided a simple [Channel Group Tab](https://github.com/OfficeDev/microsoft-teams-sample-tabs/tree/master/ChannelGroupTabMVC) project to get you started. To retrieve the source code you can download the zip folder and extract the files or clone the sample repository into your new directory:
-
-```bash
-git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
-```
-
-Once you have the source code, open Visual Studio and select **Open a project or solution**. Navigate to the tab application directory and open **ChannelGroupTabMVC.sln**.
-
-To build and run your application press **F5** or choose **Start Debugging** from the **Debug** menu. In a browser, navigate to the URLs below and verify that the application loaded properly:
--- `http://localhost:44360`-- `http://localhost:44360/privacy`-- `http://localhost:44360/tou`-
-## Review the source code
-
-### Startup.cs
-
-This project was created from an ASP.NET Core 2.2 Web Application empty template with the *Advanced - Configure for HTTPS* check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template doesn't enable serving static content by default, so the static files middleware is added to the `Configure()` method:
-
-```csharp
-public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- }
-public void Configure(IApplicationBuilder app)
- {
- app.UseStaticFiles();
- app.UseMvc();
- }
-```
-
-### wwwroot folder
-
-In ASP.NET Core, the web root folder is where the application looks for static files.
-
-### AppManifest folder
-
-This folder contains the following required app package files:
--- A **full color icon** measuring 192 x 192 pixels.-- A **transparent outline icon** measuring 32 x 32 pixels.-- A **manifest.json** file that specifies the attributes of your app.-
-These files need to be zipped in an app package for use in uploading your tab to Teams.
-
-### .csproj
-
-In the Visual Studio Solution Explorer window right-click on the project and select **Edit Project File**. At the bottom of the file you'll see the code that creates and updates your zip folder when the application builds:
-
-```xml
-<PropertyGroup>
- <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
- </PropertyGroup>
-
- <ItemGroup>
- <EmbeddedResource Include="AppManifest\icon-outline.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\icon-color.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\manifest.json">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- </ItemGroup>
-```
-
-### Models
-
-*ChannelGroup.cs* presents a Message object and methods that will be called from the Controllers during configuration.
-
-### Views
-
-#### Home
-
-ASP.NET Core treats files called *Index* as the default/home page for the site. When your browser URL points to the root of the site, **Index.cshtml** will be displayed as the home page for your application.
-
-#### Shared
-
-The partial view markup *_Layout.cshtml* contains the application's overall page structure and shared visual elements. It will also reference the Teams Library.
-
-### Controllers
-
-The controllers use the ViewBag property to transfer values dynamically to the Views.
---- Open a command prompt in the root of your project directory and run the following command:-
- ```bash
- ngrok http https://localhost:443560 -host-header="localhost:44360"
- ```
--- Ngrok will listen to requests from the internet and will route them to your application when it is running on port 44355. It should resemble `https://y8rCgT2b.ngrok.io/` where *y8rCgT2b* is replaced by your ngrok alpha-numeric HTTPS URL.--- Be sure to keep the command prompt with ngrok running and to make note of the URL ΓÇö you'll need it later.-
-## Update your application
-
-Within **Tab.cshtml** the application presents the user with two option buttons for displaying the tab with either a red or gray icon. Choosing the **Select Gray** or **Select Red** button fires `saveGray()` or `saveRed()`, respectively, sets `settings.setValidityState(true)`, and enables the **Save** button on the configuration page. This code lets Teams know that you have satisfied the configuration requirements and the installation can proceed. On save, the parameters of `settings.setSettings` are set. Finally, `saveEvent.notifySuccess()` is called to indicate that the content URL has successfully resolved.
-
platform Create Channel Group Tab Dotnet Core https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-channel-group-tab-dotnet-core.md
- Title: "Create a Channel and Group Tab with ASP.NET Core" -
-description: A quickstart guide to creating a custom channel and group tab with ASP.NET Core.
-localization_priority: Normal
---
-# Create a Custom Channel and Group Tab with ASP.NETCore
-
-In this quickstart we'll walk-through creating a custom channel/group tab with C# and ASP.Net Core Razor page. We'll also use [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) to finalize your app manifest and deploy your tab to Teams.
--
-## Get the source code
-
-Open a command prompt and create a new directory for your tab project. We have provided a simple project to get you started. To retrieve the source code you can download the zip folder and extract the files or clone the sample repository into your new directory:
-
-```bash
-git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
-```
-
-Once you have the source code, open Visual Studio and select **Open a project or solution**. Navigate to the tab application directory and open **ChannelGroupTab.sln**.
-
-To build and run your application press **F5** or choose **Start Debugging** from the **Debug** menu. In a browser navigate to the URLs below and verify the application loaded properly:
--- `http://localhost:44355`-- `http://localhost:44355/privacy`-- `http://localhost:44355/tou`-
-## Review the source code
-
-### Startup.cs
-
-This project was created from an ASP.NET Core 2.2 Web Application empty template with the *Advanced - Configure for HTTPS* check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template doesn't enable serving static content by default, so the static files middleware is added to the `Configure()` method:
-
-```csharp
-public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- }
-public void Configure(IApplicationBuilder app)
- {
- app.UseStaticFiles();
- app.UseMvc();
- }
-```
-
-### wwwroot folder
-
-In ASP.NET Core, the web root folder is where the application looks for static files.
-
-### Index.cshtml
-
-ASP.NET Core treats files called *Index* as the default/home page for the site. When your browser URL points to the root of the site, **Index.cshtml** will be displayed as the home page for your application.
-
-### Tab.cs
-
-This C# file contains a method that will be called from **Tab.cshtml** during configuration.
-
-### AppManifest folder
-
-This folder contains the following required app package files:
--- A **full color icon** measuring 192 x 192 pixels.-- A **transparent outline icon** measuring 32 x 32 pixels.-- A **manifest.json** file that specifies the attributes of your app.-
-These files need to be zipped in an app package for use in uploading your tab to Teams. When a user chooses to add or update your tab, Microsoft Teams will load the `configurationUrl` specified in your manifest, embed it in an IFrame, and render it in your tab.
-
-### .csproj
-
-In the Visual Studio Solution Explorer window right-click on the project and select **Edit Project File**. At the bottom of the file you'll see the code that creates and updates your zip folder when the application builds:
-
-```xml
-<PropertyGroup>
- <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
- </PropertyGroup>
-
- <ItemGroup>
- <EmbeddedResource Include="AppManifest\icon-outline.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\icon-color.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\manifest.json">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- </ItemGroup>
-```
---- Open a command prompt in the root of your project directory and run the following command:-
- ```bash
- ngrok http https://localhost:44355 -host-header="localhost:44355"
- ```
--- Ngrok will listen to requests from the internet and will route them to your application when it is running on port 44355. It should resemble `https://y8rCgT2b.ngrok.io/` where *y8rCgT2b* is replaced by your ngrok alpha-numeric HTTPS URL.--- Be sure to keep the command prompt with ngrok running and to make note of the URL ΓÇö you'll need it later.-
-## Update your application
-
-Within *Tab.cshtml* the application presents the user with two option buttons for displaying the tab with either a red or gray icon. Choosing the **Select Gray** or **Select Red** button fires `saveGray()` or `saveRed()`, respectively, sets `settings.setValidityState(true)`, and enables the **Save** button on the configuration page. This code lets Teams know that you have satisfied the configuration requirements and the installation can proceed. On save, the parameters of `settings.setSettings` are set. Finally, `saveEvent.notifySuccess()` is called to indicate that the content URL has successfully resolved.
--
-## Next step
-
-> [!div class="nextstepaction"]
-> [Create a Custom Channel and Group Tab with ASP.NETCore MVC](~/tabs/quickstarts/create-channel-group-tab-dotnet-core-mvc.md)
platform Create Channel Group Tab Node Yeoman https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-channel-group-tab-node-yeoman.md
- Title: "Create a custom channel and group Tab with Node.js and the Yeoman Generator for Microsoft Teams"-
-description: A quickstart guide to creating a channel and group tab with the Yeoman Generator for Microsoft Teams.
-localization_priority: Normal
---
-# Create a custom channel and group tab using Node.js and the Yeoman Generator for Microsoft Teams
-
->[!NOTE]
->This quickstart follows the steps outlined in the [Build Your First Microsoft Teams App](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App) Wiki found in the Microsoft OfficeDev GitHub repository.
-
-In this quickstart we'll walk-through creating a custom channel and group tab using the [Teams Yeoman generator](https://github.com/OfficeDev/generator-teams/).
--
-**Do you want to create a configurable or static tab?**
-
-Use the arrow keys to select configurable tab.
-
-**What scopes do you intend to use for your Tab?**
-
-You can select a Team and/or a group chat
-
-**Do you want this tab to be available in SharePoint Online? (Y/n)**
-
-Select **n**.
-
->[!IMPORTANT]
->The path component **yourDefaultTabNameTab**, referenced in this quickstart, is the value that you entered in the generator for **Default Tab Name** plus the word **Tab**.
->
->For example: DefaultTabName: **MyTab** => **/MyTabTab/**
-
-In your project directory, navigate to the following:
-
-```bash
-./src/app/scripts/<yourDefaultTabNameTab>/<yourDefaultTabNameTab>.tsx
-```
-
-That is where you'll find your tab logic. Locate the `render()` method and add the following `<div>` tag and content to the top of the `<PanelBody>` container code:
-
-```html
- <PanelBody>
- <div style={styles.section}>
- Hello World! Yo Teams rocks!
- </div>
- </PanelBody>
-```
-
-Make sure to save the updated file.
-
-## Build and Run Your Application
-
-Open a command prompt in your project directory to complete the next tasks.
--
-To view your tab configuration page go to `https://localhost:3007/<yourDefaultAppNameTab>/config.html`. You should see the following:
-
-![configuration page screenshot](~/assets/images/tab-images/configurationPage.png)
-
-## Establish a secure tunnel to your tab
-
-Microsoft Teams is an entirely cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams doesn't allow local hosting, therefore, you need to either publish your tab to a public URL or use a proxy that will expose your local port to an internet-facing URL.
-
-To test your tab extension, you'll use [ngrok](https://ngrok.com/docs), which is built into this application. Ngrok is a reverse proxy software tool that will create a tunnel to your locally running web server's publicly-available HTTPS endpoints. Your server's web endpoints will be available during the current session on your local machine. When the machine is shut down or goes to sleep the service will no longer be available.
-
-In your command prompt, exit localhost and enter the following:
-
-```bash
-gulp ngrok-serve
-```
-
-> [!IMPORTANT]
-> After your tab has been uploaded to Microsoft teams and successfully saved, you can view it in the tabs gallery, add it to the tabs bar, and interact with it until your ngrok tunnel session ends. If you restart your ngrok session, you'll need to update your app with the new URL.
-
-## Upload your application to Teams
--- Open the Microsoft Teams client. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).-- In the *YourTeams* panel on the left, select the `...` menu next to the team that you're using to test your tab and choose **Manage team**.-- In the main panel select **Apps** from the tab bar and choose **Upload a custom app** located in the lower right-hand corner of the page.-- Open your project directory, browse to the **./package** folder, select the app package zip folder and choose **Open**. Your tab will upload into Teams.-- Return to your team, choose the channel where you would like to display the tab, select Γ₧ò from the tab bar, and choose your tab from the gallery.-- Follow the directions for adding a tab. Note that there's a custom configuration dialog for your channel/group tab.-- Select **Save** and your tab will be added to the channel's tab bar.-
-## Next step
-
-> [!div class="nextstepaction"]
-> [Create a Custom Channel and Group Tab with ASP.NETCore](~/tabs/quickstarts/create-channel-group-tab-dotnet-core.md)
platform Create Personal Tab Dotnet Core Mvc https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-personal-tab-dotnet-core-mvc.md
- Title: "Create a Personal Tab with ASP. NET Core MVC" -
-description: A quickstart guide to creating a custom personal tab with ASP. NET Core MVC.
-localization_priority: Normal
---
-# Create a Custom Personal Tab with ASP.NET Core MVC
-
-In this quickstart we'll walk-through creating a custom personal tab with C# and ASP.Net Core MVC. We'll also use [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) to finalize your app manifest and deploy your tab to Teams.
--
-## Get the source code
-
-Open a command prompt and create a new directory for your tab project. We have provided a simple project to get you started. To retrieve the source code you can download the zip folder and extract the files or clone the sample repository into your new directory:
-
-``` bash
-git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
-```
-
-Once you have the source code, open Visual Studio and select **Open a project or solution**. Navigate to the tab application directory and open **PersonalTabMVC.sln**.
-
-To build and run your application press **F5** or choose **Start Debugging** from the **Debug** menu. In a browser navigate to the URLs below to verify that the application loaded properly:
-
-* `http://localhost:44335`
-* `http://localhost:44335/privacy`
-* `http://localhost:44335/tou`
-
-## Review the source code
-
-### Startup.cs
-
-This project was created from an ASP. NET Core 2.2 Web Application empty template with the *Advanced - Configure for HTTPS* check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template doesn't enable serving static content by default, so the static files middleware is added to the `Configure()` method:
-
-``` csharp
-public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- }
-public void Configure(IApplicationBuilder app)
- {
- app.UseStaticFiles();
- app.UseMvc();
- }
-```
-
-### wwwroot folder
-
-In ASP. NET Core, the web root folder is where the application looks for static files.
-
-### AppManifest folder
-
-This folder contains the following required app package files:
-
-* A **full color icon** measuring 192 x 192 pixels.
-* A **transparent outline icon** measuring 32 x 32 pixels.
-* A **manifest.json** file that specifies the attributes of your app.
-
-These files need to be zipped in an app package for use in uploading your tab to Teams. Microsoft Teams will load the `contentUrl` specified in your manifest, embed it in an IFrame, and render it in your tab.
-
-### .csproj
-
-In the Visual Studio Solution Explorer window right-click on the project and select **Edit Project File**. At the bottom of the file you'll see the code that creates and updates your zip folder when the application builds:
-
-``` xml
-<PropertyGroup>
- <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
- </PropertyGroup>
-
- <ItemGroup>
- <EmbeddedResource Include="AppManifest\icon-outline.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\icon-color.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\manifest.json">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- </ItemGroup>
-```
-
-### Models
-
-**PersonalTab.cs** presents a Message object and methods that will be called from *PersonalTabController* when a user selects a button in the **PersonalTab** View.
-
-### Views
-
-#### Home
-
-ASP. NET Core treats files called **Index** as the default or home page for the site. When your browser URL points to the root of the site, **Index.cshtml** will be displayed as the home page for your application.
-
-#### Shared
-
-The partial view markup *_Layout.cshtml* contains the application's overall page structure and shared visual elements. It will also reference the Teams Library.
-
-### Controllers
-
-The controllers use the ViewBag property to transfer values dynamically to the Views.
---
-* Open a command prompt in the root of your project directory and run the following command:
-
- ``` bash
- ngrok http https://localhost:44345 -host-header="localhost:44345"
- ```
-
-* Ngrok will listen to requests from the internet and will route them to your application when it is running on port 44325. It should resemble `https://y8rPrT2b.ngrok.io/` where *y8rPrT2b* is replaced by your ngrok alpha-numeric HTTPS URL.
-
-* Be sure to keep the command prompt with ngrok running, and to make a note of the URL ΓÇö you'll need it later.
-
-* Verify that **ngrok** is running and working properly by opening your browser and going to your content page via the ngrok HTTPS URL that was provided in your command prompt window.
-
-> [!TIP]
-> You need to have both your application in Visual Studio and ngrok running to complete this quickstart. If you need to stop running your application in Visual Studio to work on it, **keep ngrok running**. It will continue to listen and will resume routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service it will return a new URL and you'll have to update every place that uses that URL.
-
-### Run your application
-
-* In Visual Studio press **F5** or choose **Start Debugging** from your application's **Debug** menu.
--
-## Next step
-
-> [!div class="nextstepaction"]
-> [Create a custom channel and group tab using Node.js and the Yeoman Generator for Microsoft Teams](~/tabs/quickstarts/create-channel-group-tab-node-yeoman.md)
platform Create Personal Tab Dotnet Core https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-personal-tab-dotnet-core.md
- Title: Create a Personal Tab with ASP.NET Core-
-description: A quickstart guide to creating a custom personal tab with ASP.NET Core.
-
-localization_priority: Normal
--
-# Create a personal tab using ASP.NETCore
-
-In this quickstart, we'll walk-through creating a custom personal tab with C# and ASP.Net Core Razor pages. We'll also use [App Studio for Microsoft Teams](~/concepts/build-and-test/app-studio-overview.md) to finalize your app manifest and deploy your tab to Teams.
--
-## Get the source code
-
-Open a command prompt and create a new directory for your tab project. We have provided a simple project to get you started. To retrieve the source code you can download the zip folder and extract the files or clone the sample repository into your new directory:
-
-```bash
-git clone https://github.com/OfficeDev/microsoft-teams-sample-tabs.git
-```
-
-Once you have the source code, open Visual Studio and select **Open a project or solution**. Navigate to the tab application directory and open **PersonalTab.sln**.
-
-To build and run your application press **F5** or choose **Start Debugging** from the **Debug** menu. In a browser navigate to the URLs below to verify the application loaded properly:
--- `http://localhost:44325/`-- `http://localhost:44325/personal`-- `http://localhost:44325/privacy`-- `http://localhost:44325/tou`-
-## Review the source code
-
-### Startup.cs
-
-This project was created from an ASP.NET Core 2.2 Web Application empty template with the **Advanced - Configure for HTTPS** check box selected at setup. The MVC services are registered by the dependency injection framework's `ConfigureServices()` method. Additionally, the empty template doesn't enable serving static content by default, so the static files middleware is added to the `Configure()` method:
-
-```csharp
-public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- }
-public void Configure(IApplicationBuilder app)
- {
- app.UseStaticFiles();
- app.UseMvc();
- }
-```
-
-### wwwroot folder
-
-In ASP.NET Core, the web root folder is where the application looks for static files.
-
-### Index.cshtml
-
-ASP.NET Core treats files called *Index* as the default/home page for the site. When your browser URL points to the root of the site, **Index.cshtml** will be displayed as the home page for your application.
-
-### AppManifest folder
-
-This folder contains the following required app package files:
--- A **full color icon** measuring 192 x 192 pixels.-- A **transparent outline icon** measuring 32 x 32 pixels.-- A **manifest.json** file that specifies the attributes of your app.-
-These files need to be zipped in an app package for use in uploading your tab to Teams. Microsoft Teams will load the `contentUrl` specified in your manifest, embed it in an <iframe\>, and render it in your tab.
-
-### .csproj
-
-In the Visual Studio Solution Explorer window, right-click on the project and select **Edit Project File**. At the bottom of the file you'll see the code that creates and updates your zip folder when the application builds:
-
-```xml
-<PropertyGroup>
- <PostBuildEvent>powershell.exe Compress-Archive -Path \"$(ProjectDir)AppManifest\*\" -DestinationPath \"$(TargetDir)tab.zip\" -Force</PostBuildEvent>
- </PropertyGroup>
-
- <ItemGroup>
- <EmbeddedResource Include="AppManifest\icon-outline.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\icon-color.png">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- <EmbeddedResource Include="AppManifest\manifest.json">
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </EmbeddedResource>
- </ItemGroup>
-```
----- Open a command prompt in the root of your project directory and run the following command:-
- ```bash
- ngrok http https://localhost:44325 -host-header="localhost:44325"
- ```
--- Ngrok will listen to requests from the internet and will route them to your application when it is running on port 44325. It should resemble `https://y8rPrT2b.ngrok.io/` where *y8rPrT2b* is replaced by your ngrok alpha-numeric HTTPS URL.--- Be sure to keep the command prompt with ngrok running, and to make a note of the URL ΓÇö you'll need it later.--- Verify that **ngrok** is running and working properly by opening your browser and going to your content page via the ngrok HTTPS URL that was provided in your command prompt window.-
->[!TIP]
->You need to have both your application in Visual Studio and ngrok running to complete this quickstart. If you need to stop running your application in Visual Studio to work on it, **keep ngrok running**. It will continue to listen and will resume routing your application's request when it restarts in Visual Studio. If you have to restart the ngrok service it will return a new URL and you'll have to update every place that uses that URL.
-
-### Run your application
--- In Visual Studio press **F5** or choose **Start Debugging** from your application's **Debug** menu.--
-## Next step
-
-> [!div class="nextstepaction"]
-> [Create a Custom Personal Tab with ASP.NETCore MVC](~/tabs/quickstarts/create-personal-tab-dotnet-core-mvc.md)
platform Create Personal Tab Node Yeoman https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/quickstarts/create-personal-tab-node-yeoman.md
- Title: "Quickstart: Create a custom personal tab with Node.js and the Yeoman Generator for Microsoft Teams"-
-description: A quickstart guide to creating a personal tab with the Yeoman Generator for Microsoft Teams.
-localization_priority: Normal
---
-# Create a custom personal tab using Node.js and the Yeoman Generator for Microsoft Teams
-
->[!NOTE]
->This quickstart follows the steps outlined in the [Build Your First Microsoft Teams App](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App) Wiki found in the Microsoft OfficeDev GitHub repository.
-
-In this quickstart we'll walk-through creating a custom personal tab using the [Teams Yeoman generator](https://github.com/OfficeDev/generator-teams/wiki/Build-Your-First-Microsoft-Teams-App). We'll also upload the application to Team.
--
-**Create a configurable or static tab**
-
-Use the arrow keys to select static tab.
-
->[!IMPORTANT]
->The path component *yourDefaultTabNameTab*, referenced in this quickstart, is the value that you entered in the generator for *Default Tab Name* plus the word *Tab*.
->
->For example: DefaultTabName: *MyTab* => */MyTabTab/*
-
-## Create your personal tab
-
-To add a personal tab to this application you'll create a content page and update existing files:
--- In your code editor, create a new HTML file, **personal.html** and add the following markup:-
- ```html
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>
- <!-- Todo: add your a title here -->
- </title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <!-- inject:css -->
- <!-- endinject -->
- </head>
- <body>
- <h1>Personal Tab</h1>
- <p><img src="/assets/icon.png"></p>
- <p>This is your personal tab!</p>
- </body>
- </html>
- ```
--- Save **personal.html** in your application's **web** folder:-
- ```bash
- ./src/app/web/<yourDefaultTabNameTab>/personal.html
- ```
--- Open **manifest.json** in your code editor:-
- ```bash
- ./src/manifest/manifest.json/
- ```
-
-Add the following to the empty `staticTabs` array (`staticTabs":[]`) and add the following JSON object:
-
-```json
-{
- "entityId": "personalTab",
- "name": "Personal Tab ",
- "contentUrl": "https://{{HOSTNAME}}/<yourDefaultTabNameTab>/personal.html",
- "websiteUrl": "https://{{HOSTNAME}}",
- "scopes": ["personal"]
-}
-
-```
-
-Remember to update the **"contentURL"** path component **yourDefaultTabNameTab** with your actual tab name.
--- Save the updated **manifest.json**.--- Your content page must be served in an IFrame. Open **Tab.ts** in your code editor:-
- ```bash
- ./src/app/<yourDefaultTabNameTab>/<yourDefaultTabNameTab>.ts
- ```
--- Add the following to the list of IFrame decorators:-
- ```typescript
- @PreventIframe("/<yourDefaultAppName>TabNameTab>/personal.html")
- ```
--- Make sure to save the updated **Tab.ts** file. Your tab code is complete.-
-## Build and Run Your Application
-
-Open a command prompt in your project directory to complete the next tasks.
--
-To view your personal tab, go to `http://localhost:3007/<yourDefaultAppNameTab>/personal.html`
-
->![personal tab screenshot](/microsoftteams/platform/assets/images/tab-images/personalTab.PNG)
-
-## Establish a secure tunnel to your tab
-
-Microsoft Teams is an entirely cloud-based product and requires that your tab content be available from the cloud using HTTPS endpoints. Teams doesn't allow local hosting, therefore, you need to either publish your tab to a public URL or use a proxy that will expose your local port to an internet-facing URL.
-
-To test your tab extension, you'll use [ngrok](https://ngrok.com/docs), which is built into this application. Ngrok is a reverse proxy software tool that will create a tunnel to your locally running web server's publicly-available HTTPS endpoints. Your server's web endpoints will be available during the current session on your local machine. When the machine is shut down or goes to sleep the service will no longer be available.
-
-In your command prompt, exit localhost and enter the following:
-
-```bash
-gulp ngrok-serve
-```
-
-> [!IMPORTANT]
-> After your tab has been uploaded to Microsoft teams, via **ngrok**, and successfully saved, you can view it in Teams until your tunnel session ends.
-
-## Upload your application to Teams
--- Open the Microsoft Teams client. If you use the [web based version](https://teams.microsoft.com) you can inspect your front-end code using your browser's [developer tools](~/tabs/how-to/developer-tools.md).-- In the **YourTeams** panel on the left, select the `...` menu next to the team that you're using to test your tab and choose **Manage team**.-- In the main panel select **Apps** from the tab bar and choose **Upload a custom app** located in the lower right-hand corner of the page.-- Open your project directory, browse to the **./package** folder, select the zip folder, right-click, and choose **Open**. Your tab will upload into Teams.-
-## View your personal tabs
-
-In the navbar located at the far-left of the Teams client, select the `...` menu and choose your app from the list.
-
-## Next step
-
-> [!div class="nextstepaction"]
-> [Create a personal tab using ASP.NETCore](~/tabs/quickstarts/create-personal-tab-dotnet-core.md)
platform Tabs Link Unfurling https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/tabs-link-unfurling.md
> [!NOTE] > This feature is available in [public developer preview](../resources/dev-preview/developer-preview-intro.md) only.
-Stage View is a new UI component, which allows you to render the content that is opened in full screen in Teams and pinned as a tab.
+Stage View is a new user interface (UI) component, which allows you to render the content that is opened in full screen in Teams and pinned as a tab.
> [!NOTE] > Currently, Teams mobile clients do no support tabs link unfurling and Stage View. Mobile clients use the `websiteUrl` attribute provided by the developer to open the page in the device's web browser. ## Stage View
-Stage View is a full screen UI component that you can invoke to surface your web content. The existing link unfurling service is updated so that it is used to turn URLs into a tab using an Adaptive Card and Chat Services. When a user sends a URL in a chat or channel, the URL is unfurled to an Adaptive Card. The user can select **View** in the card, and pin the content as a tab directly from the Stage View.
+Stage View is a full screen UI component that you can invoke to surface your web content. The existing link unfurling service is updated so that it is used to turn URLs into a tab using an Adaptive Card and Chat Services. When a user sends a URL in a chat or channel, the URL is unfurled to an Adaptive Card. The user can select **View** in the card, and pin the content as a tab directly from Stage View.
## Advantage of Stage View Stage View helps provide a more seamless experience of viewing content in Teams. Users can open and view the content provided by your app without leaving the context, and they can pin the content to the chat or channel for future quick access. This leads to a higher user engagement with your app.
-## Stage View vs. Task module
+## Stage View vs. Task module
|Stage View|Task module| |:--|:--|
-|Stage View is useful when you have a rich content to display to the users, such as a page, a dashboard, a file, and so on. It provides maximum real estate that helps to render your content in the full-screen canvas.|[Task module](../task-modules-and-cards/task-modules/task-modules-tabs.md) is especially useful to display messages that requires user's attention, or collect information required to move to the next step.|
+|Stage View is useful when you have rich content to display to the users, such as a page, a dashboard, a file, and so on. It provides rich features that helps to render your content in the full-screen canvas.|[Task module](../task-modules-and-cards/task-modules/task-modules-tabs.md) is especially useful to display messages that require user attention, or collect information required to move to the next step.|
-## Invoke the Stage View
+## Invoke Stage View
-You can invoke the Stage View in the following ways:
+You can invoke Stage View in the following ways:
* [Invoke Stage View from Adaptive Card](#invoke-stage-view-from-adaptive-card) * [Invoke Stage View through deep link](#invoke-stage-view-through-deep-link) ## Invoke Stage View from Adaptive Card
-When the user enters a URL on the Teams desktop client, the bot is invoked and returns an [Adaptive Card](../task-modules-and-cards/cards/cards-actions.md) with the option to open the URL in a stage. After a stage is launched and the `tabInfo` is passed in, you can add the ability to pin the stage as a tab.
+When the user enters a URL on the Teams desktop client, the bot is invoked and returns an [Adaptive Card](../task-modules-and-cards/cards/cards-actions.md) with the option to open the URL in a stage. After a stage is launched and the `tabInfo` is provided, you can add the ability to pin the stage as a tab.
The following images display a stage opened from an Adaptive Card:
-<img src="~/assets/images/tab-images/open-stage-from-adaptive-card1.png" alt="Open a stage from Adaptive Card" width="400"/>
+<img src="~/assets/images/tab-images/open-stage-from-adaptive-card1.png" alt="Open a stage from Adaptive Card" width="700"/>
-<img src="~/assets/images/tab-images/open-stage-from-adaptive-card2.png" alt="Open a stage" width="400"/>
+<img src="~/assets/images/tab-images/open-stage-from-adaptive-card2.png" alt="Open a stage" width="700"/>
-### Example
+### Example
Following is the code to open a stage from an Adaptive Card:
Following is the code to open a stage from an Adaptive Card:
} ```
-The `invoke` request type must be `composeExtension/queryLink`.
+The `invoke` request type must be `composeExtension/queryLink`.
> [!NOTE] > * `invoke` workflow is similar to the current `appLinking` workflow.
-> * To maintain consistency, it is recommended to name the `Action.Submit` as `View`.
+> * To maintain consistency, it is recommended to name `Action.Submit` as `View`.
> * `websiteUrl` is a required property to be passed in the `TabInfo` object.
-**Process to invoke Stage View**
+Following is the process to invoke Stage View:
-1. When the user selects **View**, the bot receives an `invoke` request. The request type is `composeExtension/queryLink`.
-1. `invoke` response from bot contains an Adaptive Card with type `tab/tabInfoAction` in it.
-1. The bot responds with a `200` code.
+* When the user selects **View**, the bot receives an `invoke` request. The request type is `composeExtension/queryLink`.
+* `invoke` response from bot contains an Adaptive Card with type `tab/tabInfoAction` in it.
+* The bot responds with a `200` code.
> [!NOTE] > Currently, Teams mobile clients do not support the Stage View capability. When a user selects **View** on a mobile client, the user is taken to the device's browser. The browser opens the URL specified in the `websiteUrl` parameter of the `TabInfo` object. ## Invoke Stage View through deep link
-To invoke the Stage View through deep link from your tab, you must wrap the deep link URL in the `microsoftTeams.executeDeeplink(url)` API. The deeplink can also be passed through an `OpenURL` action in the card.
+To invoke the Stage View through deep link from your tab, you must wrap the deep link URL in the `microsoftTeams.executeDeeplink(url)` API. The deep link can also be passed through an `OpenURL` action in the card.
The following image displays a Stage View invoked through a deep link: <img src="~/assets/images/tab-images/invoke-stage-view-through-deep-link.png" alt="Invoke a Stage View through a deep link" width="400"/>
-### Syntax
+### Syntax
Following is the deeplink syntax:
https://teams.microsoft.com/l/stage/{appId}/0?context={ΓÇ£contentUrlΓÇ¥:ΓÇ¥[cont
### Examples When a user enters a URL, it is unfurled into an Adaptive card.
-Following are the deep link examples to invoke the Stage View:
+
+Following are the deep link examples to invoke Stage View:
**Example 1**
https://teams.microsoft.com/l/stage/2a527703-1f6f-4559-a332-d8a7d288cd88/0?conte
https://teams.microsoft.com/l/Meeting_Stage/2a527703-1f6f-4559-a332-d8a7d288cd88/0?context={ΓÇ£contentUrlΓÇ¥:ΓÇ¥https%3A%2F%2Fmicrosoft.sharepoint.com%2Fteams%2FLokisSandbox%2FSitePages%2FSandbox-Page.aspxΓÇ¥,ΓÇ£websiteUrlΓÇ¥:ΓÇ¥https%3A%2F%2Fmicrosoft.sharepoint.com%2Fteams%2FLokisSandbox%2FSitePages%2FSandbox-Page.aspxΓÇ¥,ΓÇ£nameΓÇ¥:ΓÇ¥ContosoΓÇ¥} > [!NOTE]
-> * The `name` is optional in deep link. If not included, the app name replaces it.
-> * The deep link can also be passed through an `OpenURL` action.
-> * Currently, Teams mobile clients do not support the Stage View capability. When users selects a deep link to a Stage View, they are taken to their device's web browser. The web browser opens the URL specified in the `websiteUrl` parameter of the deep link.
+> * The `name` is optional in deep link. If not included, the app name replaces it.
+> * The deep link can also be passed through an `OpenURL` action.
+> * Currently, Teams mobile clients do not support the Stage View capability. When users select a deep link to a Stage View, they are taken to their device's web browser. The web browser opens the URL specified in the `websiteUrl` parameter of the deep link.
> * When you launch a Stage from a certain context, ensure that your app works in that context. For example, if your Stage View is launched from a personal app, you must ensure your app has a personal scope. ## Tab information property
https://teams.microsoft.com/l/Meeting_Stage/2a527703-1f6f-4559-a332-d8a7d288cd88
## See also
-[Messaging extensions link unfurling](~/messaging-extensions/how-to/link-unfurling.md)
--
+* [Messaging extensions link unfurling](~/messaging-extensions/how-to/link-unfurling.md)
+* [Teams tabs](~/tabs/what-are-tabs.md)
+* [Prerequisites](~/tabs/how-to/tab-requirements.md)
+* [Create a personal tab](~/tabs/how-to/create-personal-tab.md)
+* [Create a channel or group tab](~/tabs/how-to/create-channel-group-tab.md)
+* [Create a content page](~/tabs/how-to/create-tab-pages/content-page.md)
+* [Create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md)
+* [Create a removal page for your tab](~/tabs/how-to/create-tab-pages/removal-page.md)
+* [Tabs on mobile](~/tabs/design/tabs-mobile.md)
+* [Get context for your tab](~/tabs/how-to/access-teams-context.md)
+* [Build tabs with Adaptive Cards](~/tabs/how-to/build-adaptive-card-tabs.md)
+* [Tab margin changes](~/resources/removing-tab-margins.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Create conversational tabs](~/tabs/how-to/conversational-tabs.md)
platform What Are Tabs https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/tabs/what-are-tabs.md
Title: What are custom tabs in Teams?
+ Title: Microsoft Teams tabs
description: An overview of custom tabs on the Teams platform localization_priority: Normal + # Microsoft Teams tabs Tabs are Teams-aware webpages embedded in Microsoft Teams. They are simple HTML <iframe\> tags that point to domains declared in the app manifest and can be added as part of a channel inside a team, group chat, or personal app for an individual user. You can include custom tabs with your app to embed your own web content in Teams or add Teams-specific functionality to your web content. For more information, see [Teams JavaScript client SDK](/javascript/api/overview/msteams-client).
-There are two types of tabs available in Teams ΓÇö channel/group and personal. Channel/group tabs deliver content to channels and group chats, and are a great way to create collaborative spaces around dedicated web-based content. Personal tabs, along with personally-scoped bots, are part of personal apps and are scoped to a single user. They can be pinned to the left navigation bar for easy access.
+The following image shows Contoso channel tabs:
+
+![Channel or group and personal tabs](../assets/images/tabs/tabs.png)
+
+> [!VIDEO https://www.youtube-nocookie.com/embed/Jw6i7Mkt0dg]
++
+> [!VIDEO https://www.youtube-nocookie.com/embed/T2a8yJC3VcQ]
+
+There are few prerequisites that you must go through before working on tabs.
+
+There are two types of tabs available in Teams, personal and channel or group. [Personal tabs](~/tabs/how-to/create-personal-tab.md), along with personally-scoped bots, are part of personal apps and are scoped to a single user. They can be pinned to the left navigation bar for easy access. [Channel or group tabs](~/tabs/how-to/create-channel-group-tab.md) deliver content to channels and group chats, and are a great way to create collaborative spaces around dedicated web-based content.
+
+You can [create a content page](~/tabs/how-to/create-tab-pages/content-page.md) as part of a personal tab, channel or group tab, or task module. You can [create a configuration page](~/tabs/how-to/create-tab-pages/configuration-page.md) that enables users to configure Microsoft Teams app and use it to configure a channel or group chat tab, a messaging extension, or an Office 365 Connector. You can permit users to reconfigure your tab after installation and [create a tab removal page](~/tabs/how-to/create-tab-pages/removal-page.md) for your application. When you build a Teams app that includes a tab, you must test how your [tab functions on both the Android and iOS Teams clients](~/tabs/design/tabs-mobile.md). Your tab must [get context](~/tabs/how-to/access-teams-context.md) through basic information, locale and theme information, and `entityId` or `subEntityId` that identifies what is in the tab.
+
+You can build tabs with Adaptive Cards and centralize all Teams app capabilities by eliminating the need for a different backend for your bots and tabs. [Stage View](~/tabs/tabs-link-unfurling.md) is a new UI component that allows you to render the content opened in full screen in Teams and pinned as a tab. The existing [link unfurling](~/tabs/tabs-link-unfurling.md) service is updated so that it is used to turn URLs into a tab using an Adaptive Card and Chat Services. You can [create conversational tabs](~/tabs/how-to/conversational-tabs.md) using conversational sub-entities that allow users to have conversations about sub-entities in your tab, such as specific task, patient, and sales opportunity, instead of discussing the entire tab. You can make changes to [tab margins](~/resources/removing-tab-margins.md) to enhance the developer's experience when building apps.
## Tab features
-> [!div class="checklist"]
->
-> * If a tab is added to an app that also has a bot, the bot is added to the team as well.
-> * Awareness of Azure Active Directory (Azure AD) ID of the current user.
-> * Locale awareness for the user to indicate language, i.e., `en-us`.
-> * Single sign-on (SSO) capability, if supported.
-> * Ability to use bots or app notifications to deep link to the tab or to a sub-entity within the service, e.g., an individual work item.
-> * The ability to open a task module from links within a tab.
-> * Reuse of SharePoint web parts within the tab.
+The tab features are as follows:
+
+* If a tab is added to an app that also has a bot, the bot is also added to the team.
+* Awareness of Azure Active Directory (AAD) ID of the current user.
+* Locale awareness for the user to indicate language that is `en-us`.
+* Single sign-on (SSO) capability, if supported.
+* Ability to use bots or app notifications to deep link to the tab or to a sub-entity within the service, for example an individual work item.
+* The ability to open a task module from links within a tab.
+* Reuse of SharePoint web parts within the tab.
## Tabs user scenarios
There are two types of tabs available in Teams ΓÇö channel/group and personal. C
**Example:** You create a personal tab in your Teams app that presents an informational corporate website to users. **Scenario:** Add support pages to a Teams bot or messaging extension. \
-**Example:** You create personal tabs that provide *about* and *help* webpage content to users.
+**Example:** You create personal tabs that provide **about** and **help** webpage content to users.
**Scenario:** Provide access to items that your users interact with regularly for cooperative dialogue and collaboration. \
-**Example:** You create a channel/group tab with deep linking to individual items.
+**Example:** You create a channel or group tab with deep linking to individual items.
## Understand how tabs work You can use one of the following methods to create tabs:+ * [Declare custom tab in app manifest](#declare-custom-tab-in-app-manifest)
-* [Use Adaptive Card to build tabs](#use-adaptive-card-to-build-tabs)
+* [Use Adaptive Card to build tabs](~/tabs/how-to/build-adaptive-card-tabs.md)
### Declare custom tab in app manifest
-A custom tab is declared in the app manifest of your app package. For each webpage you want included as a tab in your app, you define a URL and a scope. Additionally, you need to add the [Teams JavaScript client SDK](/javascript/api/overview/msteams-client) to your page, and call `microsoftTeams.initialize()` after your page loads. Doing so will tell Teams to display your page, give you access to Teams-specific information (for example if the Teams client is running the *dark theme*), and allow you to take action based on the results.
-
-Whether you choose to expose your tab within the channel/group or personal scope, you'll need to present an <iframe\> HTML [content page](~/tabs/how-to/create-tab-pages/content-page.md) in your tab. For personal tabs, the content URL is set directly in your Teams app manifest by the `contentUrl` property in the `staticTabs` array. Your tab's content will be the same for all users.
-
-For channel/group tabs, you also need to create an additional configuration page that allows users to configure your content page URL, typically by using URL query string parameters to load the appropriate content for that context. This is because your channel/group tab can be added to multiple different teams or group chats. On each subsequent install, your users will be able to configure the tab, allowing you to tailor the experience as needed. When users add or configure a tab, a URL is being associated with the tab that is presented in the Teams UI. Configuring a tab is simply adding additional parameters to that URL. For example, when you add the Azure Boards tab, the configuration page allows you to choose which board the tab will load. The configuration page URL is specified by the `configurationUrl` property in the `configurableTabs` array in your app manifest.
-
-You can have multiple channels or group tabs, and up to sixteen personal tabs per app.
--
-### Use Adaptive Card to build tabs
-
-When developing a tab using the traditional method, you need to consider things, such as HTML, CSS considerations to feel native, slow load times, iFrame constraints, server maintenance and costs, and so on. Adaptive Card Tabs is a new way to build tabs in Teams. Instead of embedding web content in an iframe, you can render Adaptive Card to a tab. While the front-end is rendered as Adaptive Card, the backend is powered by a bot. The bot is responsible for accepting requests and responding appropriately with the Adaptive Card to render.
-
-## Mobile clients
+A custom tab is declared in the app manifest of your app package. For each webpage you want included as a tab in your app, you define a URL and a scope. Additionally, you can add the [Teams JavaScript client SDK](/javascript/api/overview/msteams-client) to your page, and call `microsoftTeams.initialize()` after your page loads. Teams displays your page and provides access to Teams-specific information, for example the Teams client is running the dark theme.
-If you choose to have your channel or group tab appear on Teams mobile clients, the `setSettings()` configuration must have a value for the `websiteUrl` property. To ensure optimal user experience, you must follow the [guidance for tabs on mobile](~/tabs/design/tabs-mobile.md) when creating your tabs.
-Apps [distributed through the Teams store](~/concepts/deploy-and-publish/appsource/publish.md) have a separate approval process for mobile clients. The default behavior of such apps is as follows:
+Whether you choose to expose your tab within the channel or group, or personal scope, you must present an <iframe\> HTML [content page](~/tabs/how-to/create-tab-pages/content-page.md) in your tab. For personal tabs, the content URL is set directly in your Teams app manifest by the `contentUrl` property in the `staticTabs` array. Your tab's content is the same for all users.
-| **App capability** | **Behavior if app is approved** | **Behavior if app is not approved** |
-| | | |
-| **Personal tabs** | App appears in the bottom bar of the mobile clients. Tabs open in the Teams client. | App does not appear in the bottom bar of the mobile clients. |
-| **Channel and group tabs** | The tab opens in the Teams client using `contentUrl`. | The tab opens in a browser outside the Teams client using `websiteUrl`. |
+For channel or group tabs, you can also create an additional configuration page. This page allows you to configure content page URL, typically by using URL query string parameters to load the appropriate content for that context. This is because your channel or group tab can be added to multiple teams or group chats. On each subsequent install, your users can configure the tab, allowing you to tailor the experience as required. When users add or configure a tab, a URL is associated with the tab that is presented in the Teams user interface (UI). Configuring a tab simply adds additional parameters to that URL. For example, when you add the Azure Boards tab, the configuration page allows you to choose, which board the tab loads. The configuration page URL is specified by the `configurationUrl` property in the `configurableTabs` array in your app manifest.
-> [!NOTE]
-> [Apps submitted to the AppSource for publishing on Teams ](../concepts/deploy-and-publish/overview.md#publish-to-appsource) are evaluated automatically for mobile responsiveness. For any queries, reach out to teamsubm@microsoft.com.
-> For all [apps that are not distributed through the AppSource](../concepts/deploy-and-publish/overview.md), the tabs open in an in-app webview within the Teams clients by default and there is no separate approval process required.
->
-> The default behavior of apps is only applicable if distributed through the Teams store. By default, all tabs open in the Teams client.
-> To initiate an evaluation of your app for mobile-friendliness, reach out to teamsubm@microsoft.com with your app details.
+You can have multiple channels or group tabs, and up to 16 personal tabs per app.
## See also
Apps [distributed through the Teams store](~/concepts/deploy-and-publish/appsour
## Next step > [!div class="nextstepaction"]
-> [Tab requirements](~/tabs/how-to/tab-requirements.md)
+> [Prerequisites](~/tabs/how-to/tab-requirements.md)
platform Cards And Task Modules https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/cards-and-task-modules.md
+
+ Title: Cards and task modules
+description: Cards and task modules.
++
+localization_priority: Normal
++
+# Cards and task modules
+
+Cards provide users with a variety of visual, audio, and selectable messages and assist in conversation flow.
+
+With task modules, you can create modal pop-up experiences in Microsoft Teams. They are particularly useful for starting and completing tasks or displaying rich information like videos or Power business intelligence (BI) dashboards.
+
+The following types of cards are supported in bots for Teams:
+
+* Adaptive Card
+* Hero card
+* List card
+* Office 365 Connector card
+* Receipt card
+* Signin card
+* Thumbnail card
+* Card collections
+
+You can format card text using a subset of XML or HTML formatting or Markdown, depending on the card type. You can add and respond to card actions that open a URL, send messages and payload to the bot, or initiate OAuth flow.
+
+You can invoke the task modules in channel or personal tabs, bots, or deep links. Your user's experience for any workflows that requires data input can be improved by adding a task module to the user's tab. You can invoke task modules from Teams bots using buttons on Adaptive Cards and Bot Framework cards.
+
+## See also
+
+* [Cards](~/task-modules-and-cards/what-are-cards.md)
+* [Task modules](~/task-modules-and-cards/what-are-task-modules.md)
platform Cards Actions https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/cards/cards-actions.md
keywords: teams bots cards actions
# Card actions
-Cards used by bots and messaging extensions in Teams support the following activity ([`CardAction`](/bot-framework/dotnet/bot-builder-dotnet-add-rich-card-attachments#process-events-within-rich-cards)) types. Note that these actions differ from `potentialActions` for Office 365 Connector cards when used from Connectors.
+Cards used by bots and messaging extensions in Teams support the following activity [`CardAction`](/bot-framework/dotnet/bot-builder-dotnet-add-rich-card-attachments#process-events-within-rich-cards) types:
+
+> [!NOTE]
+> The `CardAction` actions differ from `potentialActions` for Office 365 Connector cards when used from connectors.
| Type | Action | | | | | `openUrl` | Opens a URL in the default browser. |
-| `messageBack` | Sends a message and payload to the bot from the user who clicked the button or tapped the card and sends a separate message to the chat stream. |
-| `imBack`| Sends a message to the bot from the user who clicked the button or tapped the card. This message (from user to bot) is visible to all conversation participants. |
-| `invoke` | Sends a message and payload to the bot from the user who clicked the button or tapped the card. This message is not visible. |
+| `messageBack` | Sends a message and payload to the bot from the user who selected the button or tapped the card. Sends a separate message to the chat stream. |
+| `imBack`| Sends a message to the bot from the user who selected the button or tapped the card. This message from user to bot is visible to all conversation participants. |
+| `invoke` | Sends a message and payload to the bot from the user who selected the button or tapped the card. This message is not visible. |
| `signin` | Initiates OAuth flow, allowing bots to connect with secure services. | > [!NOTE]
->* Teams does not support `CardAction` types not listed in the preceding table.
+>* Teams does not support `CardAction` types not listed in the previous table.
>* Teams does not support the `potentialActions` property.
->* Card actions are different than [suggested actions](/azure/bot-service/bot-builder-howto-add-suggested-actions?view=azure-bot-service-4.0&tabs=javascript#suggest-action-using-button&preserve-view=true) in Bot Framework/Azure Bot Service. Suggested actions are not supported in Microsoft Teams: if you want buttons to appear on a Teams bot message, use a card.
->* If you are using a card action as part of a messaging extension, the actions do not work until the card is submitted to the channel. They do not work while the card is in the compose message box.
+>* Card actions are different than [suggested actions](/azure/bot-service/bot-builder-howto-add-suggested-actions?view=azure-bot-service-4.0&tabs=javascript#suggest-action-using-button&preserve-view=true) in Bot Framework or Azure Bot Service. Suggested actions are not supported in Microsoft Teams. If you want buttons to appear on a Teams bot message, use a card.
+>* If you are using a card action as part of a messaging extension, the actions do not work until the card is submitted to the channel. The actions do not work while the card is in the compose message box.
+
+## Action type openUrl
+
+`openUrl` action type specifies a URL to launch in the default browser.
-Teams also supports [Adaptive Cards actions](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions), which are only used by Adaptive Cards. These actions are listed in their own section at the end of this reference.
+> [!NOTE]
+> Your bot does not receive any notice on which button was selected.
-## openUrl
+With `openUrl`, you can create an action with the following properties:
-This action type specifies a URL to launch in the default browser. Note that your bot does not receive any notice on which button was clicked.
+| Property | Description |
+| | |
+| `title` | Appears as the button label. |
+| `value` | This field must contain a full and properly formed URL. |
-The `value` field must contain a full and properly formed URL.
+# [JSON](#tab/json)
+
+The following code shows an example of `openUrl` action type in JSON:
```json {
The `value` field must contain a full and properly formed URL.
} ```
-## messageBack
+# [C#](#tab/csharp)
+
+The following code shows an example of `openUrl` action type in C#:
+
+```csharp
+var button = new CardAction()
+{
+ Type = ActionTypes.OpenUrl,
+ Title = "Tabs in Teams",
+ Value = "https://docs.microsoft.com/en-us/microsoftteams/platform/"
+};
+```
+
+# [JavaScript/Node.js](#tab/javascript)
+
+The following code shows an example of `openUrl` action type in JavaScript:
+
+```javascript
+CardFactory.actions([
+{
+ type: 'openUrl',
+ Title: 'Tabs in Teams',
+ value: 'https://docs.microsoft.com/en-us/microsoftteams/platform/'
+}])
+```
+++
+## Action type messageBack
With `messageBack`, you can create a fully customized action with the following properties: | Property | Description | | | | | `title` | Appears as the button label. |
-| `displayText` | Optional. Echoed by the user into the chat stream when the action is performed. This text is *not* sent to your bot. |
+| `displayText` | Optional. Used by the user in the chat stream when the action is performed. This text is not sent to your bot. |
| `value` | Sent to your bot when the action is performed. You can encode context for the action, such as unique identifiers or a JSON object. |
-| `text` | Sent to your bot when the action is performed. Use this property to simplify bot development: Your code can check a single top-level property to dispatch bot logic. |
+| `text` | Sent to your bot when the action is performed. Use this property to simplify bot development. Your code can check a single top-level property to dispatch bot logic. |
+
+The flexibility of `messageBack` means that your code cannot leave a visible user message in the history simply by not using `displayText`.
-The flexibility of `messageBack` means that your code can choose not to leave a visible user message in the history simply by not using `displayText`.
+# [JSON](#tab/json)
+
+The following code shows an example of `messageBack` action type in JSON:
```json {
The flexibility of `messageBack` means that your code can choose not to leave a
The `value` property can be either a serialized JSON string or a JSON object.
+# [C#](#tab/csharp)
+
+The following code shows an example of `messageBack` action type in C#:
+
+```csharp
+var button = new CardAction()
+{
+ Type = ActionTypes.MessageBack,
+ Title = "My MessageBack button",
+ DisplayText = "I clicked this button",
+ Text = "User just clicked the MessageBack button",
+ Value = "{\"property\": \"propertyValue\" }"
+};
+```
+
+# [JavaScript/Node.js](#tab/javascript)
+
+The following code shows an example of `messageBack` action type in JavaScript:
+
+```javascript
+CardFactory.actions([
+{
+ type: 'messageBack',
+ Title: "My MessageBack button",
+ displayText: "I clicked this button",
+ text: "User just clicked the MessageBack button",
+ value: {property: "propertyValue" }
+}])
+```
+++ ### Inbound message example `replyToId` contains the ID of the message that the card action came from. Use it if you want to update the message.
+The following code shows an example of inbound message:
+ ```json { "text":"User just clicked the MessageBack button",
The `value` property can be either a serialized JSON string or a JSON object.
} ```
-## imBack
+## Action type imBack
+
+The `imBack` action triggers a return message to your bot, as if the user typed it in a normal chat message. Your user and all other users in a channel can see the button response.
+
+With `imBack`, you can create an action with the following properties:
+
+| Property | Description |
+| | |
+| `title` | Appears as the button label. |
+| `value` | This field must contain the text string used in the chat and therefore sent back to the bot. This is the message text you process in your bot to perform the desired logic. |
+
+> [!NOTE]
+> The `value` field is a simple string. There is no support for formatting or hidden characters.
-This action triggers a return message to your bot, as if the user typed it in a normal chat message. Your user, and all other users if in a channel, will see that button response.
+# [JSON](#tab/json)
-The `value` field should contain the text string echoed in the chat and therefore sent back to the bot. This is the message text you will process in your bot to perform the desired logic. Note: this field is a simple string - there is no support for formatting or hidden characters.
+The following code shows an example of `imBack` action type in JSON:
```json {
The `value` field should contain the text string echoed in the chat and therefor
} ```
-## invoke
+# [C#](#tab/csharp)
+
+The following code shows an example of `imBack` action type in C#:
+
+```csharp
+var button = new CardAction()
+{
+ Type = ActionTypes.ImBack,
+ Title = "More",
+ Value = "Show me more"
+};
+```
+
+# [JavaScript/Node.js](#tab/javascript)
+
+The following code shows an example of `imBack` action type in JavaScript:
+
+```javascript
+CardFactory.actions([
+{
+ type: "imBack",
+ Title: "More",
+ value: "Show me more"
+}])
+```
+++
+## Action type invoke
The `invoke` action is used for invoking [task modules](~/task-modules-and-cards/task-modules/task-modules-bots.md).
-The `invoke` action contains three properties: `type`, `title`, and `value`. The `value` property can contain a string, a stringified JSON object, or a JSON object.
+The `invoke` action contains three properties, `type`, `title`, and `value`.
+
+With `invoke`, you can create an action with the following properties:
+
+| Property | Description |
+| | |
+| `title` | Appears as the button label. |
+| `value` | This property can contain a string, a stringified JSON object, or a JSON object. |
+
+# [JSON](#tab/json)
+
+The following code shows an example of `invoke` action type in JSON:
```json {
The `invoke` action contains three properties: `type`, `title`, and `value`. The
} ```
-When a user clicks the button, your bot will receive the `value` object with some additional info. Please note that the activity type will be `invoke` instead of `message` (`activity.Type == "invoke"`).
+When a user selects the button, your bot receives the `value` object with some additional information.
+
+> [!NOTE]
+> The activity type is `invoke` instead of `message` that is `activity.Type == "invoke"`.
+
+# [C#](#tab/csharp)
-### Example: Invoke button definition (.NET)
+The following code shows an example of `invoke` action type in C#:
```csharp var button = new CardAction()
var button = new CardAction()
}; ```
-### Example: Incoming invoke message
+# [JavaScript/Node.js](#tab/javascript)
+
+The following code shows an example of `invoke` action type in Node.js:
+
+```javascript
+CardFactory.actions([
+{
+ type: "invoke",
+ Title: "Option 1",
+ value: {
+ option: "opt1"
+ }
+}])
+```
+++
+### Example of incoming invoke message
The top-level `replyToId` property contains the ID of the message that the card action came from. Use it if you want to update the message.
+The following code shows an example of incoming invoke message:
+ ```json { "type": "invoke",
The top-level `replyToId` property contains the ID of the message that the card
} ```
-## signin
+## Action type signin
+
+`signin` action type initiates an OAuth flow that permits bots to connect with secure services. For more information, see [authentication flow in bots](~/bots/how-to/authentication/auth-flow-bot.md).
+
+Teams also supports [Adaptive Cards actions](#adaptive-cards-actions) that are only used by Adaptive Cards.
+
+# [JSON](#tab/json)
+
+The following code shows an example of `signin` action type in JSON:
+
+```json
+{
+"type": "signin",
+"title": "Click me for signin",
+"value": "https://signin.com"
+}
+```
+
+# [C#](#tab/csharp)
+
+The following code shows an example of `signin` action type in C#:
+
+```csharp
+var button = new CardAction()
+{
+ Type = ActionTypes.Signin,
+ Title = "Click me for signin",
+ Value = "https://signin.com"
+};
+```
+
+# [JavaScript/Node.js](#tab/javascript)
+
+The following code shows an example of `signin` action type in JavaScript:
+
+```javascript
+CardFactory.actions([
+{
+ type: "signin",
+ Title: "Click me for signin",
+ value: "https://signin.com"
+}])
+```
-Initiates an OAuth flow, allowing bots to connect with secure services, as described in more detail here: [Authentication flow in bots](~/bots/how-to/authentication/auth-flow-bot.md).
+ ## Adaptive Cards actions
Adaptive Cards support four action types:
* [Action.ShowCard](http://adaptivecards.io/explorer/Action.ShowCard.html) * [Action.Execute](/adaptive-cards/authoring-cards/universal-action-model#actionexecute)
-In addition to the actions mentioned above, you can modify the Adaptive Card `Action.Submit` payload to support existing Bot Framework actions using a `msteams` property in the `data` object of `Action.Submit`. The below sections detail how to use existing Bot Framework actions with Adaptive Cards.
+You can also modify the Adaptive Card `Action.Submit` payload to support existing Bot Framework actions using an `msteams` property in the `data` object of `Action.Submit`. The next section provide details on how to use existing Bot Framework actions with Adaptive Cards.
> [!NOTE]
-> Adding `msteams` to data, with a Bot Framework action, does not work with an Adaptive Card task module.
+> Adding `msteams` to data with a Bot Framework action does not work with an Adaptive Card task module.
### Adaptive Cards with messageBack action
-To include a `messageBack` action with an Adaptive Card include the following details in the `msteams` object. Note that you can include additional hidden properties in the `data` object if needed.
+To include a `messageBack` action with an Adaptive Card include the following details in the `msteams` object:
+
+> [!NOTE]
+> You can include additional hidden properties in the `data` object, if required.
| Property | Description | | | |
-| `type` | Set to `messageBack` |
-| `displayText` | Optional. Echoed by the user into the chat stream when the action is performed. This text is *not* sent to your bot. |
+| `type` | Set to `messageBack`. |
+| `displayText` | Optional. Used by the user in the chat stream when the action is performed. This text is not sent to your bot. |
| `value` | Sent to your bot when the action is performed. You can encode context for the action, such as unique identifiers or a JSON object. |
-| `text` | Sent to your bot when the action is performed. Use this property to simplify bot development: Your code can check a single top-level property to dispatch bot logic. |
+| `text` | Sent to your bot when the action is performed. Use this property to simplify bot development. Your code can check a single top-level property to dispatch bot logic. |
-#### Example
+The following code shows an example of Adaptive Cards with `messageBack` action:
```json {
To include a `messageBack` action with an Adaptive Card include the following de
### Adaptive Cards with imBack action
-To include a `imBack` action with an Adaptive Card include the following details in the `msteams` object. Note that you can include additional hidden properties in the `data` object if needed.
+To include an `imBack` action with an Adaptive Card include the following details in the `msteams` object:
+
+> [!NOTE]
+> You can include additional hidden properties in the `data` object, if required.
| Property | Description | | | |
-| `type` | Set to `imBack` |
-| `value` | String that needs to be echoed back in the chat |
+| `type` | Set to `imBack`. |
+| `value` | String that needs to be echoed back in the chat. |
-#### Example
+The following code shows an example of Adaptive Cards with `imBack` action:
```json {
To include a `imBack` action with an Adaptive Card include the following details
### Adaptive Cards with signin action
-To include a `signin` action with an Adaptive Card include the following details in the `msteams` object. Note that you can include additional hidden properties in the `data` object if needed.
+To include a `signin` action with an Adaptive Card include the following details in the `msteams` object:
+
+> [!NOTE]
+> You can include additional hidden properties in the `data` object, if required.
| Property | Description | | | | | `type` | Set to `signin`. |
-| `value` | Set to the URL that you want to redirect to. |
+| `value` | Set to the URL where you want to redirect. |
-#### Example
+The following code shows an example of Adaptive Cards with `signin` action:
```json {
To include a `signin` action with an Adaptive Card include the following details
``` ### Adaptive Cards with invoke action
-
-To include a `invoke` action with an Adaptive Card include the following details in the `msteams` object. Note that you can include additional hidden properties in the `data` object if needed.
+
+To include an `invoke` action with an Adaptive Card include the following details in the `msteams` object:
+
+> [!NOTE]
+> You can include additional hidden properties in the `data` object, if required.
| Property | Description | | | |
-| `type` | Set to `task/fetch` |
-| `data` | Set the value |
+| `type` | Set to `task/fetch`. |
+| `data` | Set the value. |
-#### Example
+The following code shows an example of Adaptive Cards with `invoke` action:
```json {
To include a `invoke` action with an Adaptive Card include the following details
} ```
-#### Example 2 (with additional payload data)
+The following code shows an example of Adaptive Cards with `invoke` action with additional payload data:
```json {
To include a `invoke` action with an Adaptive Card include the following details
} } ```+
+## See also
+
+[Cards reference](./cards-reference.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Universal Actions for Adaptive Cards](../cards/Universal-actions-for-adaptive-cards/Overview.md)
platform Cards Format https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/cards/cards-format.md
Last updated 03/29/2018
-# Format cards in Teams
+# Format cards in Microsoft Teams
-You can add rich text formatting to your cards using either Markdown or HTML, depending on the card type.
+Following are the two ways to add rich text formatting to your cards:
+* [Markdown](#format-cards-with-markdown)
+* [HTML](#format-cards-with-html)
-Cards support formatting in the text property only, not in the title or subtitle properties. Formatting can be specified using a subset of XML (HTML) formatting, or Markdown depending on card type. For current and future development Adaptive cards using Markdown formatting is recommended.
+Cards support formatting in the text property only, not in the title or subtitle properties. Formatting can be specified using a subset of XML or HTML formatting or Markdown, depending on the card type. For current and future development of Adaptive Cards, Markdown formatting is recommended.
-Formatting support differs between different card types, and rendering of the card can differ slightly between the desktop and the mobile Teams clients, as well as Teams in the desktop browser.
+Formatting support differs between card types. Rendering of the card can differ slightly between the desktop and the mobile Microsoft Teams clients, as well as Teams in the desktop browser.
-You can include an inline image with any Teams card. Images an be formatted as `.png`, `.jpg`, or `.gif` files and must not exceed 1024 ×1024 px or 1 MB. Animated GIF is not officially supported. For more information, see [Cards reference](./cards-reference.md#inline-card-images).
+You can include an inline image with any Teams card. Images can be formatted as `.png`, `.jpg`, or `.gif` files and must not exceed 1024 ×1024 px or 1 MB. Animated GIF is not supported. For more information, see [types of cards](./cards-reference.md#inline-card-images).
-## Formatting cards with Markdown
+You can format Adaptive Cards and Office 365 Connector cards with Markdown that include certain supported styles.
-There are two card types that support Markdown in Teams:
+## Format cards with Markdown
-> [!div class="checklist"]
-> * **Adaptive cards**: Markdown is supported in Adaptive card `Textblock` field, as well as `Fact.Title` and `Fact.Value`. HTML is not supported in Adaptive cards.
-> * **O365 Connector Cards**: Markdown and limited HTML is supported in Office 365 Connector cards in the text fields.
+The following card types support Markdown formatting in Teams:
-# [**Markdown formatting: Adaptive cards**](#tab/adaptive-md)
+* Adaptive Cards: Markdown is supported in Adaptive Card `Textblock` field, as well as `Fact.Title` and `Fact.Value`. HTML is not supported in Adaptive Cards.
+* O365 Connector cards: Markdown and limited HTML is supported in O365 Connector cards in the text fields.
- The supported styles for `Textblock`, `Fact.Title` and `Fact.Value` are:
+You can use newlines for Adaptive Cards using `\r` or `\n` escape sequences for newlines in lists. Formatting is different between the desktop and the mobile versions of Teams for Adaptive Cards. Card-based mentions are supported in web, desktop, and mobile clients. You can use the information masking property to mask specific information, such as password or sensitive information from users within the Adaptive Card `Input.Text` input element. You can expand the width of an Adaptive Card using the `width` object. You can enable typeahead support within Adaptive Cards and filter the set of input choices as the user types the input. You can use the `msteams` property to add the ability to display images in stage view selectively.
+
+Formatting is different between the desktop and the mobile versions of Teams for Adaptive Cards and connector cards. In this section, you can go through the Markdown format example for Adaptive Cards and connector cards.
+
+# [Markdown format for Adaptive Cards](#tab/adaptive-md)
+
+ The following table provides the supported styles for `Textblock`, `Fact.Title`, and `Fact.Value`:
| Style | Example | Markdown | | | | |
-| bold | **Bold** | ```**Bold**``` |
-| italic | _Italic_ | ```_Italic_``` |
-| unordered list | <ul><li>text</li><li>text</li></ul> | ```- Item 1\r- Item 2\r- Item 3``` |
-| ordered list | <ol><li>text</li><li>text</li></ol> | ```1. Green\r2. Orange\r3. Blue``` |
+| Bold | **Bold** | ```**Bold**``` |
+| Italic | _Italic_ | ```_Italic_``` |
+| Unordered list | <ul><li>text</li><li>text</li></ul> | ```- Item 1\r- Item 2\r- Item 3``` |
+| Ordered list | <ol><li>text</li><li>text</li></ol> | ```1. Green\r2. Orange\r3. Blue``` |
| Hyperlinks |[Bing](https://www.bing.com/)| ```[Title](url)``` | The following Markdown tags are not supported:
The following Markdown tags are not supported:
* Preformatted text * Blockquotes
-> [!IMPORTANT]
-> Adaptive cards do not support HTML formatting.
-
-### Newlines for Adaptive cards
+### Newlines for Adaptive Cards
-In lists you can use the `\r` or `\n` escape sequences for newlines. Using `\n\n` in a list will cause the next element in the list to be indented. If you need newlines elsewhere in the textblock, use `\n\n`.
+You can use the `\r` or `\n` escape sequences for newlines in lists. Using `\n\n` in lists causes the next element in the list to be indented. If you require newlines elsewhere in the TextBlock, use `\n\n`.
-### Mobile and desktop differences for Adaptive cards
+### Mobile and desktop differences for Adaptive Cards
-Formatting is slightly different between the desktop and the mobile versions of Teams.
+On the desktop, Adaptive Card Markdown formatting appears as shown in the following image in both web browsers and in the Teams client application:
-On the desktop, Adaptive card Markdown formatting appears like this in both web browsers and in the Teams client application:
+![Adaptive Card Markdown formatting in the desktop client](../../assets/images/cards/Adaptive-markdown-desktop-client.png)
-![Adaptive card Markdown formatting in the desktop client](../../assets/images/cards/Adaptive-markdown-desktop-client.png)
+On iOS, Adaptive Card Markdown formatting appears as shown in the following image:
-On iOS, Adaptive card Markdown formatting appears like this:
+![Adaptive Card Markdown formatting in iOS](../../assets/images/cards/Adaptive-markdown-iOS-75.png)
-![Adaptive card Markdown formatting in iOS](../../assets/images/cards/Adaptive-markdown-iOS-75.png)
+On Android, Adaptive Card Markdown formatting appears as shown in the following image:
-On Android, Adaptive Card Markdown formatting appears like this:
+![Adaptive Card Markdown formatting in Android](../../assets/images/cards/Adaptive-markdown-Android.png)
-![Adaptive card Markdown formatting in Android](../../assets/images/cards/Adaptive-markdown-Android.png)
+For more information, see [text features in Adaptive Cards](/adaptive-cards/create/textfeatures).
-### More information on Adaptive cards
+> [!NOTE]
+> The date and localization features mentioned in this section are not supported in Teams.
-[Text features in Adaptive cards](/adaptive-cards/create/textfeatures)
-The date and localization features mentioned in this topic are not supported in Teams.
+### Adaptive Cards format sample
-### Formatting sample for Adaptive cards
+The following code shows an example of Adaptive Cards formatting:
``` json {
The date and localization features mentioned in this topic are not supported in
} ```
-### Mention support within Adaptive cards v1.2
+### Mention support within Adaptive Cards v1.2
-Card based mentions are supported in web, desktop and mobile clients. You can add @ mentions within an adaptive card body for bots and messaging extension responses. To add @ mentions in cards, follow the same notification logic and rendering as that of message based [mentions in channel and group chat conversations](../../bots/how-to/conversations/channel-and-group-conversations.md#work-with-mentions).
+You can add @mentions within an Adaptive Card body for bots and messaging extension responses. To add @mentions in cards, follow the same notification logic and rendering as that of message based [mentions in channel and group chat conversations](../../bots/how-to/conversations/channel-and-group-conversations.md#work-with-mentions).
Bots and messaging extensions can include mentions within the card content in [TextBlock](https://adaptivecards.io/explorer/TextBlock.html) and [FactSet](https://adaptivecards.io/explorer/FactSet.html) elements. > [!NOTE]
-> * [Media elements](https://adaptivecards.io/explorer/Media.html) are currently not supported in Adaptive cards v1.2 on the Teams platform.
-> * Channel & Team mentions are not supported in bot messages.
-
-#### Constructing mentions
+> * [Media elements](https://adaptivecards.io/explorer/Media.html) are currently not supported in Adaptive Cards v1.2 on the Teams platform.
+> * Channel and team mentions are not supported in bot messages.
-To include a mention in an Adaptive Card your app needs to include the following elements:
+To include a mention in an Adaptive Card, your app needs to include the following elements:
-* `<at>username</at>` in the supported Adaptive card elements.
-* The `mention` object inside of an `msteams` property in the card content, which includes the Teams user id of the user being mentioned.
+* `<at>username</at>` in the supported Adaptive Card elements.
+* The `mention` object inside of an `msteams` property in the card content includes the Teams user ID of the user being mentioned.
* The `userId` is unique to your bot ID and a particular user. It can be used to @mention a particular user. The `userId` can be retrieved using one of the options mentioned in [get the user ID](/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages?tabs=dotnet#get-the-user-id-team-id-or-channel-id).
-#### Sample Adaptive card with a mention
+#### Sample Adaptive Card with a mention
+
+The following code shows an example of Adaptive Card with a mention:
``` json {
To include a mention in an Adaptive Card your app needs to include the following
} ```
-### Information masking in Adaptive cards
-Use the information masking property to mask specific information, such as password or sensitive information from users within the Adaptive card [`Input.Text`](https://adaptivecards.io/explorer/Input.Text.html) input element.
+### Information masking in Adaptive Cards
+
+Use the information masking property to mask specific information, such as password or sensitive information from users within the Adaptive Card [`Input.Text`](https://adaptivecards.io/explorer/Input.Text.html) input element.
> [!NOTE]
-> The feature only supports client side information masking, the masked input text is sent as clear text to the https endpoint address that was specified during [bot configuration](../../build-your-first-app/build-bot.md).
+> The feature only supports client side information masking. The masked input text is sent as clear text to the HTTPS endpoint address that was specified during [bot configuration](../../build-your-first-app/build-bot.md#4-register-your-bot-endpoint).
-#### Sample Adaptive card with masking property
+To mask information in Adaptive Cards, add the `isMasked` property to **type** `Input.Text`, and set its value to **true**.
+
+#### Sample Adaptive Card with masking property
+
+The following code shows an example of Adaptive Card with masking property:
```json {
Use the information masking property to mask specific information, such as passw
}, ```
-The following image is an example of masking information in Adaptive cards:
+The following image is an example of masking information in Adaptive Cards:
![Masking information image](../../assets/images/cards/masking-information-view.png)
-### Full width Adaptive card
-You can use the `msteams` property to expand the width of an Adaptive card and make use of additional canvas space. For information on how to use the property, see the following example:
+### Full width Adaptive Card
+
+You can use the `msteams` property to expand the width of an Adaptive Card and make use of additional canvas space. The next section provides information on how to use the property.
+
+#### Construct full width cards
-#### Constructing full width cards
-To make a full width Adaptive card the `width` object in `msteams` property in the card content must be set to `Full`.
-In addition, your app must include the following elements:
+To make a full width Adaptive Card, the `width` object in `msteams` property in the card content must be set to `Full`.
-#### Sample adaptive card with full width
+#### Sample Adaptive Card with full width
+
+To make a full width Adaptive Card, your app must include the elements from the following code sample:
``` json {
In addition, your app must include the following elements:
} ```
-A full width Adaptive Card appears as follows:
+The following image shows a full width Adaptive Card:
+ ![Full width Adaptive Card view](../../assets/images/cards/full-width-adaptive-card.png)
-If you have not set the `width` property to *Full*, then the default view of the Adaptive Card appears as follows:
+The following image shows the default view of the Adaptive Card when you have not set the `width` property to **Full**:
+ ![Small width Adaptive Card view](../../assets/images/cards/small-width-adaptive-card.png) ### Typeahead support
-Within the [`Input.Choiceset`](https://adaptivecards.io/explorer/Input.ChoiceSet.html) schema element, asking users to filter through and select through a sizable number of choices can significantly slow down task completion. Typeahead support within Adaptive cards can simplify input selection by narrowing or filtering the set of input choices as a user is typing the input.
+Within the [`Input.Choiceset`](https://adaptivecards.io/explorer/Input.ChoiceSet.html) schema element, asking users to filter and select a sizeable number of choices can significantly slow down task completion. Typeahead support within Adaptive Cards can simplify input selection by narrowing or filtering the set of input choices as the user types the input.
-#### Enable typeahead in Adaptive cards
+To enable typeahead within the `Input.Choiceset`, set `style` to `filtered` and ensure `isMultiSelect` is set to `false`.
-To enable typeahead within the `Input.Choiceset` set `style` to `filtered` and ensure `isMultiSelect` is set to `false`.
+#### Sample Adaptive Card with typeahead support
-#### Sample adaptive card with typeahead support
+The following code shows an example of Adaptive Card with typeahead support:
``` json {
To enable typeahead within the `Input.Choiceset` set `style` to `filtered` and e
], "style": "filtered" }
-```
+```
### Stage view for images in Adaptive Cards
-In an Adaptive card, you can use the `msteams` property to add the ability to display images in stage view selectively. When users hover over the images, they would see an expand icon, for which the `allowExpand` attribute is set to `true`. For information on how to use the property, see the following example:
+In an Adaptive Card, you can use the `msteams` property to add the ability to display images in stage view selectively. When users hover over the images, they can see an expand icon, for which the `allowExpand` attribute is set to `true`. For information on how to use the property, see the following example:
``` json {
In an Adaptive card, you can use the `msteams` property to add the ability to di
} ```
-When users hover over the image, an expand icon appears at top right corner of the image:
-![Adaptive card with expandable image](../../assets/images/cards/adaptivecard-hover-expand-icon.png)
+When users hover over the image, an expand icon appears at the top right corner as shown in the following image:
-The image appears in stage view when the user selects the expand button:
-![Image expanded to stage view](../../assets/images/cards/adaptivecard-expand-image.png)
+![Adaptive Card with expandable image](../../assets/images/cards/adaptivecard-hover-expand-icon.png)
-In the stage view, users can zoom in and zoom out of the image. You can select which images in your Adaptive card needs to have this capability.
+The image appears in stage view when the user selects the expand icon as shown in the following image:
-> [!NOTE]
-> Zoom in and zoom out capability applies only to the image elements (Image type) in an Adaptive card.
+![Image expanded to stage view](../../assets/images/cards/adaptivecard-expand-image.png)
+
+In the stage view, users can zoom in and zoom out of the image. You can select the images in your Adaptive Card that must have this capability.
> [!NOTE]
-> For Teams mobile apps, stage view functionality for images in Adaptive Cards are available by default and users will be able to view Adaptive card images in stage view by simply tapping on the image, irrespective of whether the `allowExpand` attribute is present or not.
+> * Zoom in and zoom out capability applies only to the image elements that is image type in an Adaptive Card.
+> * For Teams mobile apps, stage view functionality for images in Adaptive Cards is available by default. Users can view Adaptive Card images in stage view by simply tapping on the image, irrespective of whether the `allowExpand` attribute is present or not.
-# [**Markdown formatting: O365 Connector Cards**](#tab/connector-md)
+# [Markdown format for O365 Connector cards](#tab/connector-md)
-Connector cards support limited Markdown and HTML formatting. HTML support is described in the last section.
+Connector cards support limited Markdown and HTML formatting.
| Style | Example | Markdown | | | | |
-| bold | **text** | `**text**` |
-| italic | *text* | `*text*` |
-| header (levels 1&ndash;3) | **Text** | `### Text`|
-| strikethrough | ~~text~~ | `~~text~~` |
-| unordered list | <ul><li>text</li><li>text</li></ul> | ```- Item 1\r- Item 2\r- Item 3``` |
-| ordered list | <ol><li>text</li><li>text</li></ol> | ```1. Green\r2. Orange\r3. Blue``` |
-| preformatted text | `text` | ``preformatted text`` |
-| blockquote | >blockquote text | `>blockquote text` |
-| hyperlink | [Bing](https://www.bing.com/) | `[Bing](https://www.bing.com/)` |
-| image link |![Duck on a rock](https://aka.ms/Fo983c) | `![Duck](https://aka.ms/Fo983c)` |
+| Bold | **text** | `**text**` |
+| Italic | *text* | `*text*` |
+| Header (levels 1&ndash;3) | **Text** | `### Text`|
+| Strikethrough | ~~text~~ | `~~text~~` |
+| Unordered list | <ul><li>text</li><li>text</li></ul> | ```- Item 1\r- Item 2\r- Item 3``` |
+| Ordered list | <ol><li>text</li><li>text</li></ol> | ```1. Green\r2. Orange\r3. Blue``` |
+| Preformatted text | `text` | ``preformatted text`` |
+| Blockquote | >blockquote text | `>blockquote text` |
+| Hyperlink | [Bing](https://www.bing.com/) | `[Bing](https://www.bing.com/)` |
+| Image link |![Duck on a rock](https://aka.ms/Fo983c) | `![Duck](https://aka.ms/Fo983c)` |
In connector cards, newlines are rendered for `\n\n`, but not for `\n` or `\r`.
-### Mobile and desktop differences for connector cards using Markdown
+### Mobile and desktop differences for connector cards
-On the desktop, Markdown formatting for connector cards looks like this:
+On the desktop, Markdown formatting for connector cards appears as shown in the following image:
![Markdown formatting for connector cards in the Desktop client](../../assets/images/cards/connector-desktop-markdown-combined.png)
-On iOS, Markdown formatting for connector cards looks like this:
+On iOS, Markdown formatting for connector cards appears as shown in the following image:
![Markdown formatting for connector cards in the iOS client](../../assets/images/cards/connector-iphone-markdown-combined-80.png)
-Issues:
+Connector cards using Markdown for iOS include the following issues:
-* The iOS client for Teams does not render Markdown or HTML inline images in Connector Cards.
+* The iOS client for Teams does not render Markdown or HTML inline images in connector cards.
* Blockquotes are rendered as indented but without a gray background.
-On Android, Markdown formatting for connector cards looks like this:
+On Android, Markdown formatting for connector cards appears as shown in the following image:
![Markdown formatting for connector cards in the Android client](../../assets/images/cards/connector-android-markdown-combined.png)
-### Formatting example for Markdown Connector Cards
+### Format example for Markdown connector cards
+
+The following code shows an example of formatting for Markdown connector cards:
``` json {
On Android, Markdown formatting for connector cards looks like this:
-## Formatting cards with HTML
+## Format cards with HTML
+
+The following card types support HTML formatting in Teams:
-# [**HTML formatting: O365 Connector Cards**](#tab/connector-html)
+* O365 Connector cards: Limited Markdown and HTML formatting is supported in Office 365 Connector cards.
+* Hero and thumbnail cards: HTML tags are supported for simple cards, such as the hero and thumbnail cards.
-Connector cards support limited Markdown and HTML formatting. Markdown is described in the next section.
+Formatting is different between the desktop and the mobile versions of Teams for O365 Connector cards and simple cards. In this section, you can go through the HTML format example for connector cards and simple cards.
+
+# [HTML format for O365 Connector cards](#tab/connector-html)
+
+Connector cards support limited Markdown and HTML formatting.
| Style | Example | HTML | | | | |
-| bold | **text** | `<strong>text</strong>` |
-| italic | *text* | `<em>text</em>` |
-| header (levels 1&ndash;3) | **Text** | `<h3>Text</h3>` |
-| strikethrough | ~~text~~ | `<strike>text</strike>` |
-| unordered list | <ul><li>text</li><li>text</li></ul> | `<ul><li>text</li><li>text</li></ul>` |
-| ordered list | <ol><li>text</li><li>text</li></ol> | `<ol><li>text</li><li>text</li></ol>` |
-| preformatted text | `text` | `<pre>text</pre>` |
-| blockquote | <blockquote>text</blockquote> | `<blockquote>text</blockquote>` |
-| hyperlink | [Bing](https://www.bing.com/) | `<a href="https://www.bing.com/">Bing</a>` |
-| image link | <img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img> | `<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>` |
+| Bold | **text** | `<strong>text</strong>` |
+| Italic | *text* | `<em>text</em>` |
+| Header (levels 1&ndash;3) | **Text** | `<h3>Text</h3>` |
+| Strikethrough | ~~text~~ | `<strike>text</strike>` |
+| Unordered list | <ul><li>text</li><li>text</li></ul> | `<ul><li>text</li><li>text</li></ul>` |
+| Ordered list | <ol><li>text</li><li>text</li></ol> | `<ol><li>text</li><li>text</li></ol>` |
+| Preformatted text | `text` | `<pre>text</pre>` |
+| Blockquote | <blockquote>text</blockquote> | `<blockquote>text</blockquote>` |
+| Hyperlink | [Bing](https://www.bing.com/) | `<a href="https://www.bing.com/">Bing</a>` |
+| Image link | <img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img> | `<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>` |
In connector cards, newlines are rendered in HTML using the `<p>` tag.
-### Mobile and desktop differences for connector cards using HTML
+### Mobile and desktop differences for connector cards
-On the desktop, HTML formatting for connector cards looks like this:
+On the desktop, HTML formatting for connector cards appears as shown in the following image:
-![HTML formatting for connector cards in the Desktop client](../../assets/images/cards/Connector-desktop-html-combined.png)
+![HTML formatting for connector cards in the desktop client](../../assets/images/cards/Connector-desktop-html-combined.png)
-On iOS, HTML formatting looks like this:
+On iOS, HTML formatting appears as shown in the following image:
-![HTML formatting for connector cards in the iOS client](../../assets/images/cards/connector-iphone-html-combined-80.png)
+![HTML formatting for connector cards in the iOS client](../../assets/images/cards/connector-iphone-html-combined-80.png)
-Issues:
+Connector cards using HTML for iOS include the following issues:
-* Inline images are not rendered on iOS using either Markdown or HTML in Connector Cards.
+* Inline images are not rendered on iOS using either Markdown or HTML in connector cards.
* Preformatted text is rendered but does not have a gray background.
-On Android, HTML formatting looks like this:
+On Android, HTML formatting appears as shown in the following image:
![HTML formatting for connector cards in the Android client](../../assets/images/cards/connector-android-html-combined.png)
-### Formatting sample for HTML Connector Cards
+### Format sample for HTML connector cards
+
+The following code shows an example of formatting for HTML connector cards:
``` json {
On Android, HTML formatting looks like this:
```
-# [**HTML Formatting: hero and thumbnail cards**](#tab/simple-html)
+# [HTML format for hero and thumbnail cards](#tab/simple-html)
-HTML tags are supported for simple cards such as the hero and thumbnail card. Markdown is not supported.
+HTML tags are supported for simple cards, such as the hero and thumbnail cards. Markdown is not supported.
| Style | Example | HTML | | | | |
-| bold | **text** | `<strong>text</strong>` |
-| italic | *text* | `<em>text</em>` |
-| header (levels 1&ndash;3) | **Text** | `<h3>Text</h3>` |
-| strikethrough | ~~text~~ | `<strike>text</strike>` |
-| unordered list | <ul><li>text</li><li>text</li></ul> | `<ul><li>text</li><li>text</li></ul>` |
-| ordered list | <ol><li>text</li><li>text</li></ol> | `<ol><li>text</li><li>text</li></ol>` |
-| preformatted text | `text` | `<pre>text</pre>` |
-| blockquote | <blockquote>text</blockquote> | `<blockquote>text</blockquote>` |
-| hyperlink | [Bing](https://www.bing.com/) | `<a href="https://www.bing.com/">Bing</a>` |
-| image link |<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>| `<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>` |
+| Bold | **text** | `<strong>text</strong>` |
+| Italic | *text* | `<em>text</em>` |
+| Header (levels 1&ndash;3) | **Text** | `<h3>Text</h3>` |
+| Strikethrough | ~~text~~ | `<strike>text</strike>` |
+| Unordered list | <ul><li>text</li><li>text</li></ul> | `<ul><li>text</li><li>text</li></ul>` |
+| Ordered list | <ol><li>text</li><li>text</li></ol> | `<ol><li>text</li><li>text</li></ol>` |
+| Preformatted text | `text` | `<pre>text</pre>` |
+| Blockquote | <blockquote>text</blockquote> | `<blockquote>text</blockquote>` |
+| Hyperlink | [Bing](https://www.bing.com/) | `<a href="https://www.bing.com/">Bing</a>` |
+| Image link |<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>| `<img src="https://aka.ms/Fo983c" alt="Duck on a rock"></img>` |
### Mobile and desktop differences for simple cards
-Because of resolution differences between the desktop and mobile platform, formatting is different between the desktop and the mobile version of Teams.
+As there are resolution differences between the desktop and mobile platform, formatting is different between the desktop and the mobile version of Teams.
-On the desktop, HTML formatting appears like this:
+On the desktop, HTML formatting appears as shown in the following image:
-![HTML formatting in the Desktop client](../../assets/images/cards/card-formatting-xml-desktop-v2.png)
+![HTML formatting in the desktop client](../../assets/images/cards/card-formatting-xml-desktop-v2.png)
-On iOS, HTML formatting appears like this:
+On iOS, HTML formatting appears as shown in the following image:
![HTML formatting in the iOS client](../../assets/images/cards/card-formatting-xml-mobile-v2.png)
-Issues:
-
-* Character formatting like bold and italic are not rendered on iOS.
+Character formatting, such as bold and italic are not rendered on iOS.
-On Android, HTML formatting appears like this:
+On Android, HTML formatting appears as shown in the following image:
![HTML formatting in the Android client](../../assets/images/cards/card-formatting-xml-android-60.png)
-Character formatting like bold and italic display correctly on Android.
+Character formatting, such as bold and italic display correctly on Android.
-### Formatting sample for HTML formatting in simple cards
+### Format example for simple cards
-These screenshots were created using Teams AppStudio, where the text property of a hero card was set to the following string. You can test formatting in your own cards by modifying this code.
+The images in the previous section were created using Teams **App Studio**, where the text property of a hero card is set to the following string:
`<p>bold: <strong>Bold Text</strong></p><p>italic: <em>Italic Text</em></p><p>strikethrough: <strike>Strikethrough text</strike></p><h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3><p>bullet list: <ul><li>text</li><li>text</li></ul></p><p>ordered list: <ol><li>text</li><li>text</li></ol></p><pre>preformatted text</pre><blockquote>blockquote text</blockquote></p><p>hyperlink: <a href=\"https://www.bing.com/\">Bing</a></p><p>embedded image: <img src=\"https://aka.ms/Fo983c\" alt=\"Duck on a rock\"></img></p>`
+You can test formatting in your own cards by modifying this code.
+ +
+## See also
+
+* [Card actions](./cards-actions.md)
+* [Task modules](~/task-modules-and-cards/cards/cards-format.md)
platform Cards Reference https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/cards/cards-reference.md
Title: Cards reference
+ Title: Types of cards
description: Describes all the cards and card actions available to bots in Teams localization_priority: Normal keywords: bots cards reference
-# Cards reference
+# Types of cards
-The cards listed in this document are supported in bots for Microsoft Teams. They are based on cards defined by the Bot Framework (BF), but Teams does not support all Bot Framework cards and instead some Teams cards have been added. Differences are called out in the references in this document.
+Adaptive, hero, list, Office 365 Connector, receipt, signin, and thumbnail cards and card collections are supported in bots for Microsoft Teams. They are based on cards defined by the Bot Framework, but Teams does not support all Bot Framework cards and has added some of its own.
+
+Before you identify the different card types, understand how to create a a hero card, thumbnail card, or Adaptive Card.
+
+## Create a hero card, thumbnail card, or Adaptive Card
+
+**To create a hero card, thumbnail card, or Adaptive Card from App Studio**
+
+1. Go to **App Studio** from Teams.
+1. Select **Card editor**.
+1. Select **Create a new card**.
+1. Select **Create** for one of the cards from **Hero Card**, **Thumbnail Card**, or **Adaptive Card**. The metadata details, buttons, and json, csharp, and node code examples are shown for that card.
+
+ ![Hero card details](~/assets/images/Cards/Herocarddetails.png)
+
+1. Select **Send me this card**. The card is sent to you as a chat message.
## Card examples
-You can find additional information on how to use cards in the documentation for the Bot Builder SDK v3. Code samples are also available in the Microsoft/BotBuilder-Samples repository on GitHub.
+You can find additional information on how to use cards in the documentation for the Bot Builder SDK v3. Code samples are also available in the **Microsoft/BotBuilder-Samples** repository on GitHub. Following are a few card examples:
* .NET * [Add cards as attachments to messages](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=csharp#send-an-adaptive-card&preserve-view=true).
You can find additional information on how to use cards in the documentation for
* [Add cards as attachments to messages](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=javascript#send-an-adaptive-card&preserve-view=true). * [Cards sample code Bot Builder v4](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/06.using-cards).
-## Types of cards
+## Card types
-This table shows the types of cards available to you:
+You can identify and use different types of cards based on your application requirements. The following table shows the types of cards available to you:
| Card type | Description | | | |
-| [Adaptive card](#adaptive-card) | This card is highly customizable card that can contain any combination of text, speech, images, buttons, and input fields. |
+| [Adaptive Card](#adaptive-card) | This card is highly customizable and can contain any combination of text, speech, images, buttons, and input fields. |
| [Hero card](#hero-card) | This card typically contains a single large image, one or more buttons, and a small amount of text. |
-| [List card](#list-card) | This card is a scrolling list of items. |
-| [Office 365 connector card](#office-365-connector-card) | This card has a flexible layout with multiple sections, fields, images, and actions. |
+| [List card](#list-card) | This card contains a scrolling list of items. |
+| [Office 365 Connector card](#office-365-connector-card) | This card has a flexible layout with multiple sections, fields, images, and actions. |
| [Receipt card](#receipt-card) | This card provides a receipt to the user. | | [Signin card](#signin-card) | This card enables a bot to request that a user signs in. | | [Thumbnail card](#thumbnail-card) | This card typically contains a single thumbnail image, some short text, and one or more buttons. |
-| [Card collections](#card-collections) | This cards is used to return multiple items in a single response. |
+| [Card collections](#card-collections) | This card collection is used to return multiple items in a single response. |
## Common properties for all cards
+You can go through some common properties that are applicable to all cards.
+ ### Inline card images
-The card can contain an inline image by including a link to the publicly available image. For performance purposes, it is highly recommended you host the image on a public content-delivery network (CDN).
+The card can contain an inline image by including a link to the publicly available image. For performance purposes, it is highly recommended you host the image on a public Content Delivery Network (CDN).
+
+Images are scaled up or down in size to maintain the aspect ratio for covering the image area. Images are then cropped from center to achieve the appropriate aspect ratio for the card.
-Images are scaled up or down in size while maintaining the aspect ratio to cover the image area. Images are then cropped from center to achieve the appropriate aspect ratio for the card.
+Images must be at most 1024×1024 and in PNG, JPEG, or GIF format. Animated GIF is not supported.
-Images must be at most 1024×1024, in PNG, JPEG, or GIF format, and do not support animated GIF.
+The following table provides the properties of inline card images:
| Property | Type | Description | | | | |
Images must be at most 1024×1024, in PNG, JPEG, or GIF format, and do not suppo
| alt | String | Accessible description of the image. | > [!NOTE]
-> If a card includes an image URL that goes through a redirect before the final image, the redirect in image URL is not supported. This occurs for images shared on the public cloud.
+> If a card includes an image URL that is redirected before the final image, the redirect in image URL is not supported. This occurs for images shared on the public cloud.
### Buttons
For more information, see [card actions](~/task-modules-and-cards/cards/cards-ac
For more information on text formatting in cards, see [card formatting](~/task-modules-and-cards/cards/cards-format.md).
-## Adaptive card
+After identifying the common properties for all cards, you can now work with Adaptive Cards, which help you increase engagement and efficiency by adding your actionable content directly into the apps you use.
+
+## Adaptive Card
+
+> [!VIDEO https://www.youtube-nocookie.com/embed/J12lKt717Ws]
-An adaptive card is a customizable card that can contain any combination of text, speech, images, buttons, and input fields. For more information, see [adaptive cards v1.2.0](https://github.com/microsoft/AdaptiveCards/releases/tag/v1.2.0).
+An Adaptive Card is a customizable card that can contain any combination of text, speech, images, buttons, and input fields. For more information, see [Adaptive Cards v1.2.0](https://github.com/microsoft/AdaptiveCards/releases/tag/v1.2.0).
-### Support for adaptive cards
+### Support for Adaptive Cards
+
+The following table provides the features that support Adaptive Cards:
| Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£û | Γ£ö | > [!NOTE]
-> * Teams platform supports v1.2 or earlier of adaptive card features.
+> * Teams platform supports v1.2 or earlier of Adaptive Card features.
> * Positive or destructive action styling is not supported in Adaptive Cards on the Teams platform.
-> * Media elements are currently not supported in Adaptive Cards on the Teams platform.
+> * Media elements are currently not supported in Adaptive Card on the Teams platform.
+
+### Example of Adaptive Card
-### Example of an adaptive card
+![Example of an Adaptive Card](~/assets/images/cards/adaptivecard.png)
-![Example of an adaptive card](~/assets/images/cards/adaptivecard.png)
+The following code shows an example of an Adaptive Card:
```json {
An adaptive card is a customizable card that can contain any combination of text
} ```
-#### Additional information on adaptive cards
+#### Additional information on Adaptive Cards
Bot Framework reference:
-* [Adaptive cards Node.js](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=javascript#send-an-adaptive-card&preserve-view=true)
-* [Adaptive card C#](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=csharp#send-an-adaptive-card&preserve-view=true)
+* [Adaptive Cards Node](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=javascript#send-an-adaptive-card&preserve-view=true)
+* [Adaptive Card C#](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=csharp#send-an-adaptive-card&preserve-view=true)
+
+You can now work with a hero card, which is a multipurpose card used to visually highlight a potential user selection.
## Hero card
A card that typically contains a single large image, one or more buttons, and te
### Support for hero cards
+The following table provides the features that support hero cards:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£û | Γ£ö | ### Properties of a hero card
+The following table provides the properties of a hero card:
+ | Property | Type | Description | | | | |
-| title | Rich text | Title of the card. Maximum 2 lines. |
-| subtitle | Rich text | Subtitle of the card. Maximum 2 lines.|
+| title | Rich text | Title of the card. Maximum two lines. |
+| subtitle | Rich text | Subtitle of the card. Maximum two lines.|
| text | Rich text | Text appears under the subtitle. For formatting options, see [card formatting](~/task-modules-and-cards/cards/cards-format.md). | | images | Array of images | Image displayed at the top of the card. Aspect ratio 16:9. |
-| buttons | Array of action objects | Set of actions applicable to the current card. Maximum 6. |
+| buttons | Array of action objects | Set of actions applicable to the current card. Maximum six. |
| tap | Action object | Activated when the user taps on the card itself. | ### Example of a hero card ![Example of a hero card](~/assets/images/cards/hero.png)
+The following code shows an example of a hero card:
+ ```json { "contentType": "application/vnd.microsoft.card.hero",
The list card has been added by Teams to provide functions beyond what the list
### Support for list cards
+The following table provides the features that support list cards:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£û | Γ£û |Γ£ö | ### Properties of a list card
+The following table provides the properties of a list card:
+ | Property | Type | Description | | | | | | title | Rich text | Title of the card. Maximum 2 lines.|
-| items | Array of list items ||
+| items | Array of list items | Set of items applicable to the card.|
| buttons | Array of action objects | Set of actions applicable to the current card. Maximum 6. | ### Example of a list card
+The following code shows an example of a list card:
+ ```json { "contentType": "application/vnd.microsoft.teams.card.list",
The list card has been added by Teams to provide functions beyond what the list
## Office 365 connector card
-The Office 365 connector card is supported in Teams, not in Bot Framework. This card provides a flexible layout with multiple sections, fields, images, and actions. This card encapsulates a connector card so that it can be used by bots. For differences between connector cards and the O365 card, see [Notes on the Office 365 connector card](#notes-on-the-office-365-connector-card).
+You can work with an Office 365 Connector card that provides a flexible layout and is a great way to get useful information. The Office 365 connector card is supported in Teams, not in Bot Framework. This card provides a flexible layout with multiple sections, fields, images, and actions. This card contains a connector card so that it can be used by bots. For differences between connector cards and the Office 365 Connector card, see [Additional information on the Office 365 Connector card](#additional-information-on-the-office-365-connector-card).
+
+### Support for Office 365 Connector cards
-### Support for Office 365 connector cards
+The following table provides the features that support Office 365 Connector cards:
| Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£ö | Γ£û |
-### Properties of the Office 365 connector card
+### Properties of the Office 365 Connector card
+
+The following table provides the properties of the Office 365 connector card:
| Property | Type | Description | | | | |
-| title | Rich text | Title of the card. Maximum 2 lines. |
-| summary | Rich text | Summary of the card. Maximum 2 lines. |
+| title | Rich text | Title of the card. Maximum two lines. |
+| summary | Rich text | Summary of the card. Maximum two lines. |
| text | Rich text | Text appears under the subtitle. For formatting options, see [card formatting](~/task-modules-and-cards/cards/cards-format.md). |
-| themeColor | HEX string | Color that overrides the accentColor provided from the application manifest. |
+| themeColor | HEX string | Color that overrides the `accentColor` provided from the application manifest. |
-### Notes on the Office 365 connector card
+### Additional information on the Office 365 Connector card
-Office 365 connector cards function properly in Microsoft Teams, including [ActionCard actions](/outlook/actionable-messages/card-reference#actioncard-action).
+Office 365 Connector cards function properly in Microsoft Teams, including [`ActionCard` actions](/outlook/actionable-messages/card-reference#actioncard-action).
-One important difference between using connector cards from a connector and using connector cards in your bot is the handling of card actions.
+The important difference between using connector cards from a connector and using connector cards in your bot is the handling of card actions. The following table lists the difference:
-* For a connector, the endpoint receives the card payload through HTTP POST.
-* For a bot, the `HttpPOST` action triggers an `invoke` activity that sends only the action ID and body to the bot.
+| Connector | Bot |
+| | |
+| The endpoint receives the card payload through HTTP POST. | The `HttpPOST` action triggers an `invoke` activity that sends only the action ID and body to the bot.|
Each connector card can display a maximum of ten sections, and each section can contain a maximum of five images and five actions. > [!NOTE] > Any additional sections, images, or actions in a message do not appear.
-All text fields support markdown and HTML. You can control which sections use markdown or HTML by setting the `markdown` property in a message. By default, `markdown` is set to `true`. If you want to use HTML instead, set `markdown` to `false`.
+All text fields support Markdown and HTML. You can control which sections use Markdown or HTML by setting the `markdown` property in a message. By default, `markdown` is set to `true`. If you want to use HTML instead, set `markdown` to `false`.
If you specify the `themeColor` property, it overrides the `accentColor` property in the app manifest.
-To specify the rendering style for `activityImage`, you can set `activityImageType` as follows:
+To specify the rendering style for `activityImage`, you can set `activityImageType` as shown in the following table:
| Value | Description | | | |
-| `avatar` | Default; `activityImage` is cropped as a circle. |
+| `avatar` | Default, `activityImage` is cropped as a circle. |
| `article` | `activityImage` is displayed as a rectangle and retains its aspect ratio. |
-For all other details about connector card properties, see [actionable message card reference](/outlook/actionable-messages/card-reference). The only connector card properties that Microsoft Teams does not currently support are as follows:
+For all other details about connector card properties, see [actionable message card reference](/outlook/actionable-messages/card-reference). The only connector card properties that Teams does not currently support are as follows:
* `heroImage` * `hideOriginalBody`
For all other details about connector card properties, see [actionable message c
* `originator` * `correlationId`
-### Example of an Office 365 connector card
+### Example of an Office 365 Connector card
+
+The following code shows an example of an Office 365 Connector card:
```json {
Teams supports receipt card. It is a card that enables a bot to provide a receip
### Support for receipt cards
+The following table provides the features that support receipt cards:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£û | Γ£ö |
Teams supports receipt card. It is a card that enables a bot to provide a receip
![Example of a receipt card](~/assets/images/cards/receipt.png)
+The following code shows an example of a receipt card:
+ ```json { "contentType": "application/vnd.microsoft.card.receipt",
Bot Framework reference:
## Signin card
-Signin card enables a bot to request a user to sign in. It is supported in Teams in a slightly different form than is found in the Bot Framework. The signin card in Teams is similar to the signin card in the Bot Framework except that the signin card in Teams only supports two actions: `signin` and `openUrl`.
+The signin card in Teams is similar to the signin card in the Bot Framework except that the signin card in Teams only supports two actions `signin` and `openUrl`.
-The signin action can be used from any card in Teams, not just the signin card. For more information on authentication, see [Microsoft Teams authentication flow for bots](~/bots/how-to/authentication/auth-flow-bot.md).
+The signin action can be used from any card in Teams, not just the signin card. For more information, see [Teams authentication flow for bots](~/bots/how-to/authentication/auth-flow-bot.md).
### Support for signin cards
+The following table provides the features that support signin cards:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£û | Γ£û | Γ£ö |
Bot Framework reference:
## Thumbnail card
-A card that typically contains a single thumbnail image, one or more buttons, and text.
+You can work with a thumbnail card that is used for sending a simple actionable message. A card that typically contains a single thumbnail image, one or more buttons, and text.
### Support for thumbnail cards
+The following table provides the features that support thumbnail cards:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£û | Γ£ö |
A card that typically contains a single thumbnail image, one or more buttons, an
### Properties of a thumbnail card
+The following table provides the properties of a thumbnail card:
+ | Property | Type | Description | | | | | | title | Rich text | Title of the card. Maximum 2 lines.|
A card that typically contains a single thumbnail image, one or more buttons, an
### Example of a thumbnail card
+The following code shows an example of a thumbnail card:
+ ```json { "contentType": "application/vnd.microsoft.card.thumbnail",
Bot Framework reference:
## Card collections
-Teams supports Card collections.
-
-Card collections include `builder.AttachmentLayout.carousel` and `builder.AttachmentLayout.list`. These collections contain adaptive, hero, or thumbnail cards.
+You can work with card collections that include carousel and list collections. Teams supports card collections. Card collections include `builder.AttachmentLayout.carousel` and `builder.AttachmentLayout.list`. These collections contain Adaptive, hero, or thumbnail cards.
-## Carousel collection
+### Carousel collection
The [carousel layout](/azure/bot-service/bot-builder-howto-add-media-attachments?view=azure-bot-service-4.0&tabs=csharp#send-a-carousel-of-cards&preserve-view=true) shows a carousel of cards, optionally with associated action buttons.
-### Support for carousel collections
+#### Support for carousel collections
+
+The following table provides the features that support carousel collections:
| Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | |
The [carousel layout](/azure/bot-service/bot-builder-howto-add-media-attachments
> [!NOTE] > A carousel can display a maximum of ten cards per message.
-### Properties of a carousel card
+#### Properties of a carousel card
-Properties of a carousel card are same as those of the hero and thumbnail cards.
+Properties of a carousel card are same as the hero and thumbnail cards.
-### Example of a carousel collection
+#### Example of a carousel collection
![Example of a carousel of cards](~/assets/images/cards/carousel.png)
+The following code shows an example of a carousel collection:
+ ```json { "attachmentLayout": "carousel",
Properties of a carousel card are same as those of the hero and thumbnail cards.
} ```
-### Syntax for carousel collections
+#### Syntax for carousel collections
`builder.AttachmentLayoutTypes.Carousel` is the syntax for carousel collections.
-## List collection
-
-### Support for list collections
+### List collection
The list layout shows a vertically stacked list of cards, optionally with associated action buttons.
+#### Support for list collections
+
+The following table provides the features that support list collections:
+ | Bots in Teams | Messaging extensions | Connectors | Bot Framework | | | | | | | Γ£ö | Γ£ö | Γ£û | Γ£ö |
-### Example of a list collection
+#### Example of a list collection
![Example of a list of cards](~/assets/images/cards/list.png)
-Properties are the same as for the hero or thumbnail card.
+Properties of list collections are same as the hero or thumbnail cards.
A list can display a maximum of ten cards per message. > [!NOTE] > Some combinations of list cards are not yet supported on iOS and Android.
-### Syntax for list collections
+#### Syntax for list collections
`builder.AttachmentLayout.list` is the syntax for list collections.
The following cards are implemented by the Bot Framework, but are not supported
* Animation cards * Audio cards * Video cards+
+## See also
+
+* [Task modules](~/task-modules-and-cards/what-are-task-modules.md)
+* [Format cards](~/task-modules-and-cards/cards/cards-format.md)
platform Invoking Task Modules https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/task-modules/invoking-task-modules.md
+
+ Title: Invoke and dismiss task modules
+description: Invoke and dismiss task modules.
++
+localization_priority: Normal
++
+# Invoke and dismiss task modules
+
+Task modules can be invoked from tabs, bots, or deep links. The response can be either in HTML, JavaScript, or as an Adaptive Card. There is a lot of flexibility in terms of how task modules are invoked and how to deal with the response of the user's interaction. The following table summarizes how this works:
+
+| Invoked using | Task module with HTML or JavaScript | Task module with Adaptive Card |
+| | | |
+| JavaScript in a tab | 1. Use the Teams client SDK function `tasks.startTask()` with an optional `submitHandler(err, result)` callback function. <br/><br/> 2. In the task module code, when the user has performed the actions, call the Teams SDK function `tasks.submitTask()` with a `result` object as a parameter. If a `submitHandler` callback was specified in `tasks.startTask()`, Teams calls it with `result` as a parameter. If there was an error when invoking `tasks.startTask()`, the `submitHandler` function is called with an `err` string instead. <br/><br/> 3. You can also specify a `completionBotId` when calling `teams.startTask()`. Then the `result` is sent to the bot instead. | 1. Call the Teams client SDK function `tasks.startTask()` with a [TaskInfo object](#the-taskinfo-object) and `TaskInfo.card` containing the JSON for the Adaptive Card to show in the task module pop-up. <br/><br/> 2. If a `submitHandler` callback was specified in `tasks.startTask()`, Teams calls it with an `err` string, if there was an error when invoking `tasks.startTask()` or if the user closes the task module pop-up using the X at the upper right. <br/><br/> 3. If the user presses an `Action.Submit` button then its `data` object is returned as the value of `result`. |
+| Bot card button | 1. Bot card buttons, depending on the type of button, can invoke task modules in two ways, a deep link URL or by sending a `task/fetch` message. <br/><br/> 2. If the button's action `type` is `task/fetch` that is `Action.Submit` button type for Adaptive Cards, a `task/fetch invoke` event that is an HTTP POST is sent to the bot. The bot responds to the POST with HTTP 200 and the response body containing a wrapper around the [TaskInfo object](#the-taskinfo-object). For more information, see [invoking a task module using `task/fetch`](~/task-modules-and-cards/task-modules/task-modules-bots.md#invoke-a-task-module-using-taskfetch). Teams displays the task module. <br/><br/> 3. After the user has performed the actions, call the Teams SDK function `tasks.submitTask()` with a `result` object as a parameter. The bot receives a `task/submit invoke` message that contains the `result` object. <br/><br/> 4. You have three different ways to respond to the `task/submit` message, by doing nothing that is the task completed successfully, by displaying a message to the user in a pop-up window, or by invoking another task module window. For more information, see [detailed discussion on `task/submit`](~/task-modules-and-cards/task-modules/task-modules-bots.md#the-flexibility-of-tasksubmit). | <ul><li> Like buttons on Bot Framework cards, buttons on Adaptive Cards support two ways of invoking task modules, deep link URLs with `Action.openUrl` buttons, and `task/fetch` using `Action.Submit` buttons. </li></ul> <br/><br/> <ul><li> Task modules with Adaptive Cards work very similarly to the HTML or JavaScript case. The major difference is that since there is no JavaScript when you are using Adaptive Cards, there is no way to call `tasks.submitTask()`. Instead, Teams takes the `data` object from `Action.Submit` and returns it as the payload of the `task/submit` event. For more information, see [flexibility of `task/submit`](~/task-modules-and-cards/task-modules/task-modules-bots.md#the-flexibility-of-tasksubmit). </li></ul> |
+| Deep link URL <br/>[URL syntax](#task-module-deep-link-syntax) | 1. Teams invokes the task module that is the URL that appears inside the `<iframe>` specified in the `url` parameter of the deep link. There is no `submitHandler` callback. <br/><br/> 2. Within the JavaScript of the page in the task module, call `tasks.submitTask()` to close it with a `result` object as a parameter, the same as when invoking it from a tab or a bot card button. However, completion logic is slightly different. If your completion logic resides on the client that is if there is no bot, there is no `submitHandler` callback, so any completion logic must be in the code preceding the call to `tasks.submitTask()`. Invocation errors are only reported through the console. If you have a bot, then you can specify a `completionBotId` parameter in the deep link to send the `result` object through a `task/submit` event. | 1. Teams invokes the task module that is the JSON card body of the Adaptive Card that is specified as a URL-encoded value of the `card` parameter of the deep link. <br/><br/> 2. The user closes the task module by selecting the X at the upper right of the task module or by pressing an `Action.Submit` button on the card. Since there is no `submitHandler` to call, the user must have a bot to send the value of the Adaptive Card fields. The user must use the `completionBotId` parameter in the deep link to specify the bot to send the data to using a `task/submit invoke` event. |
+
+> [!NOTE]
+> Invoking a task module from JavaScript is not supported on mobile.
+
+The next section specifies the `TaskInfo` object that defines certain attributes for a task module.
+
+## The TaskInfo object
+
+The `TaskInfo` object contains the metadata for a task module. Define the `url` for an embedded iFrame or `card` for an Adaptive Card. The following table provides the object definition:
+
+| Attribute | Type | Description |
+| | | |
+| `title` | string | This attribute appears below the app name and to the right of the app icon. |
+| `height` | number or string | This attribute can be a number representing the task module's height in pixels, or `small`, `medium`, or `large`. For more information, see [task module sizing](#task-module-sizing). |
+| `width` | number or string | This attribute can be a number representing the task module's width in pixels, or `small`, `medium`, or `large`. For more information, see [task module sizing](#task-module-sizing). |
+| `url` | string | This attribute is the URL of the page loaded as an `<iframe>` inside the task module. The URL's domain must be in the app's [validDomains array](~/resources/schem#validdomains) in your app's manifest. |
+| `card` | Adaptive Card or Adaptive Card bot card attachment | This attribute is the JSON for the Adaptive Card to appear in the task module. If the user is invoking from a bot, use the Adaptive Card JSON in a Bot Framework `attachment` object. From a tab, the user must use an Adaptive Card. For more information, see [Adaptive Card or Adaptive Card bot card attachment](#adaptive-card-or-adaptive-card-bot-card-attachment) |
+| `fallbackUrl` | string | This attribute opens the URL in a browser tab, if a client does not support the task module feature. |
+| `completionBotId` | string | This attribute specifies a bot App ID to send the result of the user's interaction with the task module. If specified, the bot receives a `task/submit invoke` event with a JSON object in the event payload. |
+
+> [!NOTE]
+> The task module feature requires that the domains of any URLs you want to load are included in the `validDomains` array in your app's manifest.
+
+The next section specifies task module sizing that enables the user to set the height and width of the task module.
+
+## Task module sizing
+
+Using integers for `TaskInfo.width` and `TaskInfo.height`, sets the height and width of the task module in pixels. However, depending on the size of the Team's window and screen resolution they are reduced proportionally while maintaining the aspect ratio that is width or height.
+
+If `TaskInfo.width` and `TaskInfo.height` are `"small"`, `"medium"`, or `"large"`, the size of the red rectangle in the following image is a proportion of the available space, 20%, 50%, and 60% for `width` and 20%, 50%, and 66% for `height`:
+
+![Task module example](~/assets/images/task-module/task-module-example.png)
+
+Task modules invoked from a tab can be dynamically resized. After calling `tasks.startTask()` you can call `tasks.updateTask(newSize)` where height and width properties on the newSize object conform to the TaskInfo specification, for example `{ height: 'medium', width: 'medium' }`.
+
+The next section provides examples of embedding task modules in a YouTube video and a PowerApp.
+
+## Task module CSS for HTML or JavaScript task modules
+
+HTML or JavaScript-based task modules have access to the entire area of the task module below the header. While that offers a great deal of flexibility, if you want padding around the edges to align with the header elements and avoid unnecessary scroll bars, the user must provide the right CSS. The next sections provide some examples for a few use cases.
+
+**Example 1: YouTube video**
+
+YouTube offers the ability to embed videos on web pages. It is easy to embed videos on web pages in a task module using a simple stub web page.
+
+![YouTube video](~/assets/images/task-module/youtube-example.png)
+
+The following code provides an example of the HTML for the web page without the CSS:
+
+```html
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ Γï«
+</head>
+<body>
+ <div id="embed-container">
+ <iframe width="1000" height="700" src="https://www.youtube.com/embed/rd0Rd8w3FZ0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe>
+ </div>
+</body>
+</html>
+```
+
+The following code provides an example of the CSS:
+
+```css
+#embed-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 95%;
+ height: 95%;
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ border-style: none;
+}
+```
+
+**Example 2: PowerApp**
+
+The user can use the same approach to embed a PowerApp as well. As the height or width of any individual PowerApp is customizable, the user can adjust the height and width to achieve the desired presentation.
+
+![Asset management PowerApp](~/assets/images/task-module/powerapp-example.png)
+
+The following code provides an example of the HTML for PowerApp:
+
+```html
+<iframe width="720" height="520" src="https://web.powerapps.com/webplayer/iframeapp?source=iframe&screenColor=rgba(104,101,171,1)&appId=/providers/Microsoft.PowerApps/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></iframe>
+```
+
+The following code provides an example of the CSS:
+
+```css
+#embed-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 94%;
+ height: 95%;
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ border-style: none;
+}
+```
+
+The next section provides details on invoking your card using Adaptive Card or Adaptive Card bot card attachment.
+
+## Adaptive Card or Adaptive Card bot card attachment
+
+Depending on how you are invoking your `card`, you must use either an Adaptive Card or an Adaptive Card bot card attachment, which is an Adaptive Card wrapped in an attachment object.
+
+When you are invoking from a tab, the user must use an Adaptive Card.
+
+The following code provides an example of an Adaptive Card:
+
+```json
+{
+ "type": "AdaptiveCard",
+ "body": [
+ {
+ "type": "TextBlock",
+ "text": "Here is a ninja cat:"
+ },
+ {
+ "type": "Image",
+ "url": "http://adaptivecards.io/content/cats/1.png",
+ "size": "Medium"
+ }
+ ],
+ "version": "1.0"
+}
+```
+
+The following code provides an example of an Adaptive Card bot card attachment when you are invoking from a bot:
+
+```json
+{
+ "contentType": "application/vnd.microsoft.card.adaptive",
+ "content": {
+ "type": "AdaptiveCard",
+ "body": [
+ {
+ "type": "TextBlock",
+ "text": "Here is a ninja cat:"
+ },
+ {
+ "type": "Image",
+ "url": "http://adaptivecards.io/content/cats/1.png",
+ "size": "Medium"
+ }
+ ],
+ "version": "1.0"
+ }
+}
+```
+
+The next section provides details on task module deep link syntax including the `TaskInfo` object and `APP_ID` and `BOT_APP_ID`.
+
+## Task module deep link syntax
+
+A task module deep link is a serialization of the TaskInfo object with the following two other details, `APP_ID` and optionally the `BOT_APP_ID`:
+
+`https://teams.microsoft.com/l/task/APP_ID?url=<TaskInfo.url>&height=<TaskInfo.height>&width=<TaskInfo.width>&title=<TaskInfo.title>&completionBotId=BOT_APP_ID`
+
+`https://teams.microsoft.com/l/task/APP_ID?card=<TaskInfo.card>&height=<TaskInfo.height>&width=<TaskInfo.width>&title=<TaskInfo.title>&completionBotId=BOT_APP_ID`
+
+For the data types and allowable values for `<TaskInfo.url>`, `<TaskInfo.card>`, `<TaskInfo.height>`, `<TaskInfo.width>`, and `<TaskInfo.title>`, see [TaskInfo object](#the-taskinfo-object).
+
+> [!TIP]
+> URL encode the deep link when using the `card` parameter, for example, JavaScript's [`encodeURI()` function](https://www.w3schools.com/jsref/jsref_encodeURI.asp).
+
+The following table provides information on `APP_ID` and `BOT_APP_ID`:
+
+| Value | Type | Required | Description |
+| | | | |
+| `APP_ID` | string | Yes | The [ID](~/resources/schem#validdomains) in the manifest for `APP_ID` must contain the domain for `url` if `url` is in the URL. The app ID is already known when a task module is invoked from a tab or a bot, which is why it is not included in `TaskInfo`. |
+| `BOT_APP_ID` | string | No | If a value for `completionBotId` is specified, the `result` object is sent using a `task/submit invoke` message to the specified bot. `BOT_APP_ID` must be specified as a bot in the app's manifest, that is you cannot send it to any bot. |
+
+> [!NOTE]
+> `APP_ID` and `BOT_APP_ID` can be the same in many cases, if an app has a recommended bot to use as an app's ID if there is one.
+
+The next section provides details on using a keyboard with your app's task module.
+
+## Keyboard and accessibility guidelines
+
+With HTML or JavaScript-based task modules, you must ensure your app's task module can be used with a keyboard. Screen reader programs also depend on the ability to navigate using the keyboard. This includes the following two things:
+
+* Using the [tabindex attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) in your HTML tags to control which elements can be focused. Also, use tabindex attribute to identify where it participates in sequential keyboard navigation usually with the <kbd>Tab</kbd> and <kbd>Shift-Tab</kbd> keys.
+* Handling the <kbd>Esc</kbd> key in the JavaScript for your task module. The following code provides an example of how to handle the <kbd>Esc</kbd> key:
+
+ ```javascript
+ // Handle the Esc key
+ document.onkeyup = function(event) {
+ if ((event.key === 27) || (event.key === "Escape")) {
+ microsoftTeams.submitTask(null); // this will return an err object to the completionHandler()
+ }
+ }
+ ```
+
+Microsoft Teams ensures that keyboard navigation works properly from the task module header into your HTML and vice-versa.
+
+## Code sample
+
+|Sample name | Description | .NET | Node.js|
+|-|--|--|-|
+|Task module sample bots-V4 | Samples for creating task modules. |[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/54.teams-task-module)|[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/54.teams-task-module)|
+|Task module sample tabs and bots-V3 | Samples for creating task modules. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/csharp)|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/nodejs)|
+
+## See also
+
+* [Request device permissions](~/concepts/device-capabilities/native-device-permissions.md)
+* [Integrate media capabilities](~/concepts/device-capabilities/mobile-camera-image-permissions.md)
+* [Integrate QR or barcode scanner capability in Teams](~/concepts/device-capabilities/qr-barcode-scanner-capability.md)
+* [Integrate location capabilities in Teams](~/concepts/device-capabilities/location-capability.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Use task modules in tabs](~/task-modules-and-cards/task-modules/task-modules-tabs.md)
platform Task Modules Bots https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/task-modules/task-modules-bots.md
Title: Using Task Modules in Microsoft Teams bots
-description: How to use task modules with Microsoft Teams bots, including Bot Framework cards, Adaptive cards, and deep links
+ Title: Use Task Modules in Microsoft Teams bots
+description: How to use task modules with Microsoft Teams bots, including Bot Framework cards, Adaptive cards, and deep links.
localization_priority: Normal keywords: task modules teams bots
-# Using task modules from Microsoft Teams bots
-Task modules can be invoked from Microsoft Teams bots using buttons on Adaptive cards and Bot Framework cards (Hero, Thumbnail, and Office 365 Connector). Task modules are often a better user experience than multiple conversation steps where you as a developer have to keep track of bot state and allow the user to interrupt/cancel the sequence.
+# Use task modules from bots
+
+Task modules can be invoked from Microsoft Teams bots using buttons on Adaptive Cards and Bot Framework cards that is hero, thumbnail, and Office 365 Connector. Task modules are often a better user experience than multiple conversation steps. Keep track of bot state and allow the user to interrupt or cancel the sequence.
There are two ways of invoking task modules:
-* **A new kind of invoke message `task/fetch`.** Using the `invoke` [card action](~/task-modules-and-cards/cards/cards-actions.md#invoke) for Bot Framework cards, or the `Action.Submit` [card action](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions) for Adaptive cards, with `task/fetch`, the task module (either a URL or an Adaptive card) is fetched dynamically from your bot.
-* **Deep link URLs.** Using the [deep link syntax for task modules](~/task-modules-and-cards/what-are-task-modules.md#task-module-deep-link-syntax), you can use the `openUrl` [card action](~/task-modules-and-cards/cards/cards-actions.md#openurl) for Bot Framework cards or the `Action.OpenUrl` [card action](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions) for Adaptive cards, respectively. With deep link URLs, the task module URL or Adaptive card body is obviously known in advance, avoiding a server round-trip relative to `task/fetch`.
+* A new kind of invoke message `task/fetch`: Using the `invoke` [card action](~/task-modules-and-cards/cards/cards-actions.md#action-type-invoke) for Bot Framework cards, or the `Action.Submit` [card action](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions) for Adaptive cards, with `task/fetch`, task module either a URL or an Adaptive Card, is fetched dynamically from your bot.
+* Deep link URLs: Using the [deep link syntax for task modules](~/task-modules-and-cards/task-modules/invoking-task-modules.md#task-module-deep-link-syntax), you can use the `openUrl` [card action](~/task-modules-and-cards/cards/cards-actions.md#action-type-openurl) for Bot Framework cards or the `Action.OpenUrl` [card action](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions) for Adaptive Cards, respectively. With deep link URLs, the task module URL or Adaptive Card body is already known to avoid a server round-trip relative to `task/fetch`.
+
+> [!IMPORTANT]
+> Each `url` and `fallbackUrl` must implement the HTTPS encryption protocol.
->[!IMPORTANT]
->To ensure secure communications, each `url` and `fallbackUrl` must implement the HTTPS encryption protocol.
+The next section provides details on invoking a task module using `task/fetch`.
-## Invoking a task module through task/fetch
+## Invoke a task module using task/fetch
-When the `value` object of the `invoke` card action or `Action.Submit` is initialized in the proper way (explained in more detail below), when a user presses the button an `invoke` message is sent to the bot. In the HTTP response to the `invoke` message, there's a [TaskInfo object](~/task-modules-and-cards/what-are-task-modules.md#the-taskinfo-object) embedded in a wrapper object, which Teams uses to display the task module.
+When the `value` object of the `invoke` card action or `Action.Submit` is initialized and when a user selects the button, an `invoke` message is sent to the bot. In the HTTP response to the `invoke` message, there is a [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object) embedded in a wrapper object, which Teams uses to display the task module.
-![task/fetch request/response](~/assets/images/task-module/task-module-invoke-request-response.png)
+![task/fetch request or response](~/assets/images/task-module/task-module-invoke-request-response.png)
-Let's look at each step in a bit more detail:
+The following steps provides the invoke task module using task/fetch:
-1. This example shows a Bot Framework Hero card with a "Buy" `invoke` [card action](~/task-modules-and-cards/cards/cards-actions.md#invoke). The value of the `type` property is `task/fetch` - the rest of the `value` object can be whatever you like.
+1. This image shows a Bot Framework hero card with a **Buy** `invoke` [card action](~/task-modules-and-cards/cards/cards-actions.md#action-type-invoke). The value of the `type` property is `task/fetch` and the rest of the `value` object can be of your choice.
1. The bot receives the `invoke` HTTP POST message.
-1. The bot creates a response object and returns it in the body of the POST response with an HTTP 200 response code. The schema for responses is described [below in the discussion on task/submit](#the-flexibility-of-tasksubmit), but the important thing to remember now is that the body of the HTTP response contains a [TaskInfo object](~/task-modules-and-cards/what-are-task-modules.md#the-taskinfo-object) embedded in a wrapper object. For example:
+1. The bot creates a response object and returns it in the body of the POST response with an HTTP 200 response code. For more information on schema for responses, see [the discussion on task/submit](#the-flexibility-of-tasksubmit). The following code provides an example of body of the HTTP response that contains a [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object) embedded in a wrapper object:
```json {
Let's look at each step in a bit more detail:
} ```
- The `task/fetch` event and its response for bots is similar, conceptually, to the `microsoftTeams.tasks.startTask()` function in the client SDK.
+ The `task/fetch` event and its response for bots is similar to the `microsoftTeams.tasks.startTask()` function in the client SDK.
+ 1. Microsoft Teams displays the task module.
-## Submitting the result of a task module
+The next section provides details on submitting the result of a task module.
+
+## Submit the result of a task module
+
+When the user is finished with the task module, submitting the result back to the bot is similar to the way it works with tabs. For more information, see [example of submitting the result of a task module](~/task-modules-and-cards/task-modules/task-modules-tabs.md#example-of-submitting-the-result-of-a-task-module). There are a few differences as follows:
-When the user is finished with the task module, submitting the result back to the bot is similar [to the way it works with tabs](~/task-modules-and-cards/task-modules/task-modules-tabs.md#example-submitting-the-result-of-a-task-module), but there are a few differences, so it's described here too.
+* HTML or JavaScript that is `TaskInfo.url`: Once you have validated what the user has entered, you call the `microsoftTeams.tasks.submitTask()` SDK function referred to hereafter as `submitTask()` for readability purposes. You can call `submitTask()` without any parameters if you want Teams to close the task module, but you must pass an object or a string to your `submitHandler`. Pass it as the first parameter, `result`. Teams invokes `submitHandler`, `err` is `null`, and `result` is the object or string you passed to `submitTask()`. If you call `submitTask()` with a `result` parameter, you must pass an `appId` or an array of `appId` strings. This allows Teams to validate that the app sending the result is the same one which invoked the task module. Your bot receives a `task/submit` message including `result`. For more information, see [payload of `task/fetch` and `task/submit` messages](#payload-of-taskfetch-and-tasksubmit-messages).
+* Adaptive Card that is `TaskInfo.card`: The Adaptive Card body as filled in by the user is sent to the bot through a `task/submit` message when the user selects any `Action.Submit` button.
-* **HTML/JavaScript (`TaskInfo.url`)**. Once you've validated what the user has entered, you call the `microsoftTeams.tasks.submitTask()` SDK function (referred to hereafter as `submitTask()` for readability purposes). You can call `submitTask()` without any parameters if you just want Teams to close the task module, but most of the time you'll want to pass an object or a string to your `submitHandler`. Simply pass it as the first parameter, `result`. Teams will invoke `submitHandler`: `err` will be `null` and `result` will be the object/string you passed to `submitTask()`. If you do call `submitTask()` with a `result` parameter, you **must** pass an `appId` or an array of `appId` strings: this allows Teams to validate that the app sending the result is the same one which invoked the task module. Your bot will receive a `task/submit` message including `result` as described [below](#payload-of-taskfetch-and-tasksubmit-messages).
-* **Adaptive card (`TaskInfo.card`)**. The Adaptive card body (as filled in by the user) will be sent to the bot via a `task/submit` message when the user presses any `Action.Submit` button.
+The next section provides details on the flexibility of `task/submit`.
## The flexibility of task/submit
-In the previous section, you learned that when the user finishes with a task module invoked from a bot, the bot always receives a `task/submit invoke` message. As a developer, you have several options when *responding* to the `task/submit` message:
+When the user finishes with a task module invoked from a bot, the bot always receives a `task/submit invoke` message. You have several options when responding to the `task/submit` message as follows:
-| HTTP Body Response | Scenario |
+| HTTP body response | Scenario |
| | |
-| None (ignore the `task/submit` message) | The simplest response is no response at all. Your bot is not required to respond when the user is finished with the task module. |
-| <pre>{<br/> "task": {<br/> "type": "message",<br/> "value": "Message text"<br/> }<br/>}</pre> | Teams will display the value of `value` in a popup message box. |
-| <pre>{<br/> "task": {<br/> "type": "continue",<br/> "value": &lt;TaskInfo object&gt;<br/> }<br/>}</pre> | Allows you to "chain" sequences of Adaptive cards together in a wizard/multi-step experience. _Note that chaining Adaptive cards into a sequence is an advanced scenario and not documented here. The Node.js sample app supports it, however, and how it works is documented in [its README.md file](https://github.com/OfficeDev/microsoft-teams-sample-task-module-nodejs#implementation-notes)._ |
+| None ignore the `task/submit` message | The simplest response is no response at all. Your bot is not required to respond when the user is finished with the task module. |
+| <pre>{<br/> "task": {<br/> "type": "message",<br/> "value": "Message text"<br/> }<br/>}</pre> | Teams displays the value of `value` in a pop-up message box. |
+| <pre>{<br/> "task": {<br/> "type": "continue",<br/> "value": &lt;TaskInfo object&gt;<br/> }<br/>}</pre> | Allows you to chain sequences of Adaptive Cards together in a wizard or multi-step experience. |
+
+> [!NOTE]
+> Chaining Adaptive Cards into a sequence is an advanced scenario. The Node.js sample app supports it. For more information, see [Microsoft Teams task module Node.js](https://github.com/OfficeDev/microsoft-teams-sample-task-module-nodejs#implementation-notes).
+
+The next section provides details on payload of `task/fetch` and `task/submit` messages.
## Payload of task/fetch and task/submit messages
-This section defines the schema of what your bot receives when it receives a `task/fetch` or `task/submit` Bot Framework `Activity` object. The important top-level appear below:
+This section defines the schema of what your bot receives when it receives a `task/fetch` or `task/submit` Bot Framework `Activity` object. The following table provides the properties of payload of `task/fetch` and `task/submit` messages:
| Property | Description | | -- | |
-| `type` | Will always be `invoke` |
-| `name` | Either `task/fetch` or `task/submit` |
-| `value` | The developer-defined payload. Normally the structure of the `value` object mirrors what was sent from Teams. In this case, however, it's different because we want to support dynamic fetch (`task/fetch`) from both Bot Framework (`value`) and Adaptive card `Action.Submit` actions (`data`), and we need a way to communicate Teams `context` to the bot in addition to what was included in `value`/`data`.<br/><br/>We do this by combining the two into a parent object:<br/><br/><pre>{<br/> "context": {<br/> "theme": "default" &vert; "dark" &vert; "contrast",<br/> },<br/> "data": [value field from Bot Framework card] &vert; [data field from Adaptive Card] <br/>}</pre> |
+| `type` | Is always `invoke`. |
+| `name` | Is either `task/fetch` or `task/submit`. |
+| `value` | Is the developer-defined payload. The structure of the `value` object is the same as what is sent from Teams. In this case, however, it is different. It requires support for dynamic fetch that is `task/fetch` from both Bot Framework, which is `value` and Adaptive Card `Action.Submit` actions, which is `data`. A way to communicate Teams `context` to the bot is required in addition to what is included in `value` or `data`.<br/><br/>Combine 'value' and 'data' into a parent object:<br/><br/><pre>{<br/> "context": {<br/> "theme": "default" &vert; "dark" &vert; "contrast",<br/> },<br/> "data": [value field from Bot Framework card] &vert; [data field from Adaptive Card] <br/>}</pre> |
-## Example: Receiving and responding to task/fetch and task/submit invoke messages - Node.js
+The next section provides an example of receiving and responding to `task/fetch` and `task/submit` invoke messages in Node.js.
-> [!NOTE]
-> The sample code below was modified between Technical Preview and final release of this feature: the schema of the `task/fetch` request changed to follow what was [documented in the previous section](#payload-of-taskfetch-and-tasksubmit-messages). That is, the documentation was correct but the implementation was not. See the `// for Technical Preview [...]` comments below for what changed.
+## Example of task/fetch and task/submit invoke messages in Node.js and C#
+
+# [Node.js](#tab/nodejs)
```typescript
-// Handle requests and responses for a "Custom Form" and an "Adaptive card" task module.
-// Assumes request is coming from an Adaptive card Action.Submit button that has a "taskModule" property indicating what to invoke
-private async onInvoke(event: builder.IEvent, cb: (err: Error, body: any, status?: number) => void): Promise<void> {
- let invokeType = (event as any).name;
- let invokeValue = (event as any).value;
- if (invokeType === undefined) {
- invokeType = null;
- }
- switch (invokeType) {
- case "task/fetch": {
- if (invokeValue !== undefined && invokeValue.data.taskModule === "customform") { // for Technical Preview, was invokeValue.taskModule
- // Return the specified task module response to the bot
- let fetchTemplate: any = {
- "task": {
- "type": "continue",
- "value": {
- "title": "Custom Form",
- "height": 510,
- "width": 430,
- "fallbackUrl": "https://contoso.com/teamsapp/customform",
- "url": "https://contoso.com/teamsapp/customform",
- }
- }
- };
- cb(null, fetchTemplate, 200);
- };
- if (invokeValue !== undefined && invokeValue.data.taskModule === "adaptivecard") { // for Technical Preview, was invokeValue.taskModule
- let adaptiveCard = {
- "type": "AdaptiveCard",
- "body": [
- {
- "type": "TextBlock",
- "text": "Here is a ninja cat:"
- },
- {
- "type": "Image",
- "url": "http://adaptivecards.io/content/cats/1.png",
- "size": "Medium"
- }
- ],
- "version": "1.0"
- };
- // Return the specified task module response to the bot
- let fetchTemplate: any = {
- "task": {
- "type": "continue",
- "value": {
- "title": "Ninja Cat",
- "height": "small",
- "width": "small",
- "card": {
- contentType: "application/vnd.microsoft.card.adaptive",
- content: adaptiveCard,
- }
- }
- }
- };
- cb(null, fetchTemplate, 200);
- };
- break;
- }
- case "task/submit": {
- if (invokeValue.data !== undefined) {
- // It's a valid task module response
- let submitResponse: any = {
- "task": {
- "type": "message",
- "value": "Task complete!",
- }
- };
- cb(null, fetchTemplates.submitMessageResponse, 200)
- }
- }
+handleTeamsTaskModuleFetch(context, taskModuleRequest) {
+ // Called when the user selects an options from the displayed HeroCard or
+ // AdaptiveCard. The result is the action to perform.
+
+ const cardTaskFetchValue = taskModuleRequest.data.data;
+ var taskInfo = {}; // TaskModuleTaskInfo
+
+ if (cardTaskFetchValue === TaskModuleIds.YouTube) {
+ // Display the YouTube.html page
+ taskInfo.url = taskInfo.fallbackUrl = this.baseUrl + '/' + TaskModuleIds.YouTube + '.html';
+ this.setTaskInfo(taskInfo, TaskModuleUIConstants.YouTube);
+ } else if (cardTaskFetchValue === TaskModuleIds.CustomForm) {
+ // Display the CustomForm.html page, and post the form data back via
+ // handleTeamsTaskModuleSubmit.
+ taskInfo.url = taskInfo.fallbackUrl = this.baseUrl + '/' + TaskModuleIds.CustomForm + '.html';
+ this.setTaskInfo(taskInfo, TaskModuleUIConstants.CustomForm);
+ } else if (cardTaskFetchValue === TaskModuleIds.AdaptiveCard) {
+ // Display an AdaptiveCard to prompt user for text, and post it back via
+ // handleTeamsTaskModuleSubmit.
+ taskInfo.card = this.createAdaptiveCardAttachment();
+ this.setTaskInfo(taskInfo, TaskModuleUIConstants.AdaptiveCard);
}+
+ return TaskModuleResponseFactory.toTaskModuleResponse(taskInfo);
}
-```
-## Example: Receiving and responding to task/fetch and task/submit invoke messages - C#
+async handleTeamsTaskModuleSubmit(context, taskModuleRequest) {
+ // Called when data is being returned from the selected option (see `handleTeamsTaskModuleFetch').
-In C# bots, `invoke` messages are processed by an `HttpResponseMessage()` controller processing an `Activity` message. The `task/fetch` and `task/submit` requests and responses are JSON. In C#, it's not as convenient to deal with raw JSON as it is in Node.js, so you need wrapper classes to handle the serialization to and from JSON. There's no direct support for this in the Microsoft Teams [C# SDK](https://www.nuget.org/packages/Microsoft.Bot.Connector.Teams) yet, but you can see an example of what these simple wrapper classes would look like in the [C# sample app](https://github.com/OfficeDev/microsoft-teams-sample-task-module-csharp/blob/master/Microsoft.Teams.Samples.TaskModule.Web/Models/TaskModel.cs).
+ // Echo the users input back. In a production bot, this is where you'd add behavior in
+ // response to the input.
+ await context.sendActivity(MessageFactory.text('handleTeamsTaskModuleSubmit: ' + JSON.stringify(taskModuleRequest.data)));
-Below is example code in C# for handling `task/fetch` and `task/submit` messages using these wrapper classes (`TaskInfo`, `TaskEnvelope`), excerpted from the [sample](https://github.com/OfficeDev/microsoft-teams-sample-task-module-csharp/blob/master/Microsoft.Teams.Samples.TaskModule.Web/Controllers/MessagesController.cs):
+ // Return TaskModuleResponse
+ return {
+ // TaskModuleMessageResponse
+ task: {
+ type: 'message',
+ value: 'Thanks!'
+ }
+ };
+}
-```csharp
-private HttpResponseMessage HandleInvokeMessages(Activity activity)
-{
- var activityValue = activity.Value.ToString();
- if (activity.Name == "task/fetch")
- {
- var action = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.BotFrameworkCardValue<string>>(activityValue);
-
- Models.TaskInfo taskInfo = GetTaskInfo(action.Data);
- Models.TaskEnvelope taskEnvelope = new Models.TaskEnvelope
- {
- Task = new Models.Task()
- {
- Type = Models.TaskType.Continue,
- TaskInfo = taskInfo
- }
- };
- return Request.CreateResponse(HttpStatusCode.OK, taskEnvelope);
- }
- else if (activity.Name == "task/submit")
- {
- ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
- Activity reply = activity.CreateReply("Received = " + activity.Value.ToString());
- connector.Conversations.ReplyToActivity(reply);
- }
- return new HttpResponseMessage(HttpStatusCode.Accepted);
+setTaskInfo(taskInfo, uiSettings) {
+ taskInfo.height = uiSettings.height;
+ taskInfo.width = uiSettings.width;
+ taskInfo.title = uiSettings.title;
}
+```
-// Helper function for building the TaskInfo object based on the incoming request
-private static Models.TaskInfo GetTaskInfo(string actionInfo)
+# [C#](#tab/csharp)
+
+```csharp
+protected override Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
- Models.TaskInfo taskInfo = new Models.TaskInfo();
- switch (actionInfo)
+ var asJobject = JObject.FromObject(taskModuleRequest.Data);
+ var value = asJobject.ToObject<CardTaskFetchValue<string>>()?.Data;
+
+ var taskInfo = new TaskModuleTaskInfo();
+ switch (value)
{ case TaskModuleIds.YouTube:
- taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.YouTube;
+ taskInfo.Url = taskInfo.FallbackUrl = _baseUrl + "/" + TaskModuleIds.YouTube;
SetTaskInfo(taskInfo, TaskModuleUIConstants.YouTube); break;
- case TaskModuleIds.PowerApp:
- taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.PowerApp;
- SetTaskInfo(taskInfo, TaskModuleUIConstants.PowerApp);
- break;
case TaskModuleIds.CustomForm:
- taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.CustomForm;
+ taskInfo.Url = taskInfo.FallbackUrl = _baseUrl + "/" + TaskModuleIds.CustomForm;
SetTaskInfo(taskInfo, TaskModuleUIConstants.CustomForm); break; case TaskModuleIds.AdaptiveCard:
- taskInfo.Card = AdaptiveCardHelper.GetAdaptiveCard();
+ taskInfo.Card = CreateAdaptiveCardAttachment();
SetTaskInfo(taskInfo, TaskModuleUIConstants.AdaptiveCard); break; default: break; }
- return taskInfo;
+
+ return Task.FromResult(taskInfo.ToTaskModuleResponse());
+}
+
+protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
+{
+ var reply = MessageFactory.Text("OnTeamsTaskModuleSubmitAsync Value: " + JsonConvert.SerializeObject(taskModuleRequest));
+ await turnContext.SendActivityAsync(reply, cancellationToken);
+
+ return TaskModuleResponseFactory.CreateResponse("Thanks!");
+}
+
+private static void SetTaskInfo(TaskModuleTaskInfo taskInfo, UISettings uIConstants)
+{
+ taskInfo.Height = uIConstants.Height;
+ taskInfo.Width = uIConstants.Width;
+ taskInfo.Title = uIConstants.Title.ToString();
} ```
-Not shown in the above example is the `SetTaskInfo()` function, which sets the `height`, `width`, and `title` properties of the `TaskInfo` object for each case. Here's the [source code for SetTaskInfo()](https://github.com/OfficeDev/microsoft-teams-sample-task-module-csharp/blob/master/Microsoft.Teams.Samples.TaskModule.Web/Controllers/MessagesController.cs).
+
-### Bot Framework card actions vs. Adaptive card Action.Submit actions
+### Bot Framework card actions vs. Adaptive Card Action.Submit actions
-The schema for Bot Framework card actions is slightly different from Adaptive card `Action.Submit` actions. As a result, the way to invoke task modules is slightly different too: the `data` object in `Action.Submit` contains an `msteams` object so it won't interfere with other properties in the card. The following table shows an example of each:
+The schema for Bot Framework card actions is different from Adaptive Card `Action.Submit` actions and the way to invoke task modules is also different. The `data` object in `Action.Submit` contains an `msteams` object so it does not interfere with other properties in the card. The following table shows an example of each card action:
-| Bot Framework card action | Adaptive card Action.Submit action |
+| Bot Framework card action | Adaptive Card Action.Submit action |
| | | | <pre>{<br/> "type": "invoke",<br/> "title": "Buy",<br/> "value": {<br/> "type": "task/fetch",<br/> &lt;...&gt;<br/> }<br/>}</pre> | <pre>{<br/> "type": "Action.Submit",<br/> "id": "btnBuy",<br/> "title": "Buy",<br/> "data": {<br/> &lt;...&gt;,<br/> "msteams": {<br/> "type": "task/fetch"<br/> }<br/> }<br/>}</pre> |
+## Code sample
+
+|Sample name | Description | .NET | Node.js|
+|-|--|--|-|
+|Task module sample bots-V4 | Samples for creating task modules. |[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/54.teams-task-module)|[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/54.teams-task-module)|
+ ## See also
-* [Microsoft Teams task module sample code ΓÇö nodejs](https://github.com/OfficeDev/microsoft-teams-sample-task-module-nodejs/blob/master/src/TeamsBot.ts)
-* [Bot Framework samples](https://github.com/Microsoft/BotBuilder-Samples/blob/master/README.md).
+* [Microsoft Teams task module sample code in Node.js](https://github.com/OfficeDev/microsoft-teams-sample-task-module-nodejs/blob/master/src/TeamsBot.ts)
+* [Bot Framework samples](https://github.com/Microsoft/BotBuilder-Samples/blob/master/README.md)
platform Task Modules Tabs https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/task-modules/task-modules-tabs.md
Title: Using Task Modules in Microsoft Teams tabs
-description: Explains how to invoke task modules from Teams tabs using the Microsoft Teams client SDK
+ Title: Use Task Modules in Microsoft Teams tabs
+description: Explains how to invoke task modules from Teams tabs using the Microsoft Teams client SDK.
localization_priority: Normal keywords: task modules teams tabs client sdk
-# Using task modules in tabs
+# Use task modules in tabs
-Adding a task module to your tab can greatly simplify your user's experience for any workflows that require data input. Task modules allow you to gather their input in a Teams-aware popup. A good example of this is editing Planner cards; you can use task modules to create a similar experience.
+Add a task module to your tab to simplify your user's experience for any workflows that require data input. Task modules allow you to gather their input in a Microsoft Teams-Aware pop-up. A good example of this is editing Planner cards. You can use task modules to create a similar experience.
-To support the task module feature, two new functions were added to the [Microsoft Teams client SDK](/javascript/api/overview/msteams-client):
+To support the task module feature, two new functions are added to the [Teams client SDK](/javascript/api/overview/msteams-client). The following code shows an example of these two functions:
```typescript microsoftTeams.tasks.startTask(
microsoftTeams.tasks.submitTask(
): void; ```
-Let's see how each of them work.
+You can see how invoking a task module from a tab and submitting the result of a task module works.
-## Invoking a task module from a tab
+## Invoke a task module from a tab
-To invoke a task module from a tab use `microsoftTeams.tasks.startTask()` passing a [TaskInfo object](~/task-modules-and-cards/what-are-task-modules.md#the-taskinfo-object) and an optional `submitHandler` callback function. As described earlier, there are two cases to consider:
+To invoke a task module from a tab use `microsoftTeams.tasks.startTask()` passing a [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object) and an optional `submitHandler` callback function. There are two cases to consider:
-1. The value of `TaskInfo.url` is set to a URL. The task module window appears and `TaskModule.url` is loaded as an `<iframe>` inside it. JavaScript on that page should call `microsoftTeams.initialize()`. If there is a `submitHandler` function on the page and there is an error when invoking `microsoftTeams.tasks.startTask()`, then `submitHandler` is invoked with `err` set to the error string indicating the error as described [below](#task-module-invocation-errors).
-1. The value of `taskInfo.card` is the [JSON for an Adaptive card](~/task-modules-and-cards/what-are-task-modules.md#adaptive-card-or-adaptive-card-bot-card-attachment). In this case there's obviously not any JavaScript `submitHandler` function to call when the user closes or presses a button on the Adaptive card; the only way to receive what the user entered is by passing the result to a bot. To use an Adaptive card task module from a tab your app must include a bot to get any information back from the user. This is explained below.
+* The value of `TaskInfo.url` is set to a URL. The task module window appears and `TaskModule.url` is loaded as an `<iframe>` inside it. JavaScript on that page calls `microsoftTeams.initialize()`. If there is a `submitHandler` function on the page and there is an error when invoking `microsoftTeams.tasks.startTask()`, then `submitHandler` is invoked with `err` set to the error string indicating the same. For more information, see [task module invocation errors](#task-module-invocation-errors).
+* The value of `taskInfo.card` is the [JSON for an Adaptive Card](~/task-modules-and-cards/task-modules/invoking-task-modules.md#adaptive-card-or-adaptive-card-bot-card-attachment). There is no JavaScript `submitHandler` function to call when the user closes or presses a button on the Adaptive Card. The only way to receive what the user entered is by passing the result to a bot. To use an Adaptive Card task module from a tab, your app must include a bot to get any response from the user.
-## Example: Invoking a task module
+The next section gives an example of invoking a task module.
-The code below is adapted from [the task module sample](~/task-modules-and-cards/what-are-task-modules.md#code-sample). Here's what the task module looks like:
+## Example of invoking a task module
+
+The following image displays the task module:
![Task Module - Custom Form](~/assets/images/task-module/task-module-custom-form.png)
-The `submitHandler` is very simple; it just echoes the value of `err` or `result` to the console:
+The following code is adapted from [the task module sample](~/task-modules-and-cards/task-modules/invoking-task-modules.md#code-sample):
```javascript let taskInfo = {
submitHandler = (err, result) => {
microsoftTeams.tasks.startTask(taskInfo, submitHandler); ```
-## Submitting the result of a task module
+The `submitHandler` is very simple and it echoes the value of `err` or `result` to the console.
+
+## Submit the result of a task module
+
+The `submitHandler` function resides in the `TaskInfo.url` web page and is used with `TaskInfo.url`. If there is an error when invoking the task module, your `submitHandler` function is immediately invoked with an `err` string indicating what [error occurred](#task-module-invocation-errors). The `submitHandler` function is also called with an `err` string when the user selects X at the upper right of the task module to close it.
-The `submitHandler` function is used with `TaskInfo.url`. The `submitHandler` function resides in the `TaskInfo.url` web page. If there's an error when invoking the task module your `submitHandler` function will be immediately invoked with an `err` string indicating which [error occurred](#task-module-invocation-errors). The `submitHandler` function is also called with an `err` string when the user presses the X at the upper right of task module.
+If there is no invocation error and the user does not select X to dismiss it, the user chooses a button when finished. Depending on whether it is a URL or an Adaptive Card in the task module, the next sections provide details on what occurs.
-If there's no invocation error and the user doesn't press X to dismiss it, the user presses a button when finished. Depending on whether it's a URL or an Adaptive card in the task module, here's what happens:
+### HTML or JavaScript `TaskInfo.url`
-### HTML/JavaScript (`TaskInfo.url`)
+After validating the user's inputs, call the `microsoftTeams.tasks.submitTask()` SDK function referred to as `submitTask()`. Call `submitTask()` without any parameters if you just want Teams to close the task module. You can pass an object or a string to your `submitHandler`.
-Once you've validated what the user has entered you call the `microsoftTeams.tasks.submitTask()` SDK function (referred to hereafter as `submitTask()` for readability purposes). You can call `submitTask()` without any parameters if you just want Teams to close the task module, but most of the time you'll want to pass an object or a string to your `submitHandler`.
+Pass your result as the first parameter. Teams invokes `submitHandler` where `err` is `null` and `result` is the object or string you passed to `submitTask()`. If you call `submitTask()` with a `result` parameter, you must pass an `appId` or an array of `appId` strings. This permits Teams to validate that the app sending the result is same as the invoked task module.
-Pass your result as the first parameter. Teams will invoke `submitHandler` where `err` will be `null` and `result` will be the object/string you passed to `submitTask()`. If you do call `submitTask()` with a `result` parameter, you **must** pass an `appId` or an array of `appId` strings: this allows Teams to validate that the app sending the result is the same one which invoked the task module.
+### Adaptive Card `TaskInfo.card`
-### Adaptive card (`TaskInfo.card`)
+When you invoke the task module with a `submitHandler` and the user selects an `Action.Submit` button, the values in the card are returned as the value of `result`. If the user selects the Esc key or X at the top right, `err` is returned instead. If your app contains a bot in addition to a tab, you can simply include the `appId` of the bot as the value of `completionBotId` in the `TaskInfo` object. The Adaptive Card body as filled in by the user is sent to the bot using a `task/submit invoke` message when the user selects an `Action.Submit` button. The schema for the object you receive is very similar to [the schema you receive for task/fetch and task/submit messages](~/task-modules-and-cards/task-modules/task-modules-bots.md#payload-of-taskfetch-and-tasksubmit-messages). The only difference is that the schema of the JSON object is an Adaptive Card object as opposed to an object containing an Adaptive Card object as [when Adaptive cards are used with bots](~/task-modules-and-cards/task-modules/task-modules-bots.md#payload-of-taskfetch-and-tasksubmit-messages).
-If you invoked the task module with a `submitHandler`, when the user presses an `Action.Submit` button the values in the card will be returned as the value of `result`. If the user presses the Esc button or presses the X, `err` will be returned instead. Alternatively, if your app contains a bot in addition to a tab you can simply include the `appId` of the bot as the value of `completionBotId` in the `TaskInfo` object. The Adaptive card body (as filled in by the user) will be sent to the bot via a `task/submit invoke` message when the user presses an `Action.Submit` button. The schema for the object you receive is very similar to [the schema you receive for task/fetch and task/submit messages](~/task-modules-and-cards/task-modules/task-modules-bots.md#payload-of-taskfetch-and-tasksubmit-messages); the only difference is that the schema of the JSON object is an Adaptive card object as opposed to an object *containing* an Adaptive card object as [when Adaptive cards are used with bots](~/task-modules-and-cards/task-modules/task-modules-bots.md#payload-of-taskfetch-and-tasksubmit-messages).
+The next section gives an example of submitting the result of a task module.
-## Example: submitting the result of a task module
+## Example of submitting the result of a task module
-Recall the [form in the task module above](#example-invoking-a-task-module) with an HTML form. Here's where the form is defined:
+For more information, see the [HTML form in the task module](#example-of-invoking-a-task-module). The following code gives an example of where the form is defined:
```html <form method="POST" id="customerForm" action="/register" onSubmit="return validateForm()"> ```
-There are five fields on this form but we're only interested in the values of three of them for this example: `name`, `email`, and `favoriteBook`.
+There are five fields on this form but for this example only three values are required, `name`, `email`, and `favoriteBook`.
-Here's the `validateForm()` function that calls `submitTask()`:
+The following code gives an example of the `validateForm()` function that calls `submitTask()`:
```javascript function validateForm() {
function validateForm() {
} ```
+The next section provides task module invocation problems and their error messages.
+ ## Task module invocation errors
-Here are the possible values of `err` that can be received by your `submitHandler`:
+The following table provides the possible values of `err` that can be received by your `submitHandler`:
-| Problem | Error message (value of `err`) |
+| Problem | Error message that is value of `err` |
| - | |
-| Values for both `TaskInfo.url` and `TaskInfo.card` were specified. | "Values for both card and url were specified. One or the other, but not both, are allowed." |
-| Neither `TaskInfo.url` nor `TaskInfo.card` specified. | "You must specify a value for either card or url." |
-| Invalid `appId`. | "Invalid appId." |
-| User pressed X button, closing it. | "User cancelled/closed the task module." |
+| Values for both `TaskInfo.url` and `TaskInfo.card` were specified. | Values for both card and URL were specified. One or the other, but not both, are allowed. |
+| Neither `TaskInfo.url` nor `TaskInfo.card` specified. | You must specify a value for either card or URL. |
+| Invalid `appId`. | Invalid app ID. |
+| User selected X button, closing it. | User cancelled or closed the task module. |
+
+## Code sample
+
+|Sample name | Description | .NET | Node.js|
+|-|--|--|-|
+|Task module sample tabs and bots-V3 | Samples for creating task modules. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/csharp)|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/nodejs)|
+
+## See also
+
+[Invoke and dismiss task modules](~/task-modules-and-cards/task-modules/invoking-task-modules.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Using task modules from bots](~/task-modules-and-cards/task-modules/task-modules-bots.md)
platform What Are Cards https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/what-are-cards.md
Title: Introducing cards
-description: Describes cards and how they are used in bots, connectors and messaging extensions
+ Title: Cards
+description: Describes cards and how they are used in bots, connectors, and messaging extensions
localization_priority: Normal- keywords: connectors bots cards messaging+ # Cards
-A *card* is a user-interface (UI) container for short or related pieces of information. Cards can have multiple properties and attachments. Cards can include buttons which can trigger [Card actions](~/task-modules-and-cards/cards/cards-actions.md).
+A card is a user interface (UI) container for short or related pieces of information. Cards can have multiple properties and attachments and can include buttons, which trigger [card actions](~/task-modules-and-cards/cards/cards-actions.md). Using cards, you can organize information into groups and give users the opportunity to interact with specific parts of the information.
-## Adaptive cards
-
-[Adaptive cards](~/task-modules-and-cards/cards/cards-reference.md#adaptive-card) are a new cross product specification for cards in Microsoft products including Bots, Cortana, Outlook, and Windows. They are the recommended card type for new Teams development. For general information from the Adaptive cards team see [Adaptive Cards Overview](/adaptive-cards). You can use adaptive cards anywhere you can use existing Hero cards, Office365 cards, and Thumbnail cards.
-
-In addition to Adaptive Cards, Teams supports two other types of cards:
-
-* Connector Cards, used as part of Office 365 connectors.
-* Simple cards from the bot framework, such as the thumbnail and hero cards.
-
-These card types are described more fully in the [Teams Card Reference](~/task-modules-and-cards/cards/cards-reference.md).
+The bots for Teams support the following types of cards: Adaptive Card, hero card, list card, Office 365 Connector card, receipt card, signin card, thumbnail card, and card collections. You can add rich text formatting to your cards using either Markdown or HTML, depending on the card type. Cards used by bots and messaging extensions in Microsoft Teams, add and respond to these card actions, `openUrl`, `messageBack`, `imBack`, `invoke`, and `signin`.
Teams uses cards in three different places:
Teams uses cards in three different places:
* Bots * Messaging extensions
-## Adaptive cards and incoming webhooks
+## Cards in connectors
-> [!NOTE]
->
-> Γ£ö All native adaptive card schema elements, except `Action.Submit`, are fully supported.
->
-> Γ£ö The supported actions are [**Action.OpenURL**](https://adaptivecards.io/explorer/Action.OpenUrl.html), [**Action.ShowCard**](https://adaptivecards.io/explorer/Action.ShowCard.html), [**Action.ToggleVisibility**](https://adaptivecards.io/explorer/Action.ToggleVisibility.html) and [**Action.Execute**](https://docs.microsoft.com/adaptive-cards/authoring-cards/universal-action-model#actionexecute).
+Cards were first defined as part of Outlook and Office 365 and are now used as part of Office 365 Connectors. Like many Office 365 applications, Teams supports connectors. For more information, see [Office 365 Connectors for Teams](~/webhooks-and-connectors/what-are-webhooks-and-connectors.md). You can find the specification for cards in connectors in [actionable message card reference](/outlook/actionable-messages/card-reference).
+
+## Cards in bots
+
+The Microsoft Bot Framework extends the cards specification by adding a set of predefined cards that bots can use as part of bot messages. Teams supports bots using the Bot Framework, but it supports a different set of these cards. General information on cards in Bot Framework can be found in [add rich card attachments to messages](/bot-framework/nodejs/bot-builder-nodejs-send-rich-cards). These cards are called simple cards in Teams.
+
+Bots in Teams can use simple cards, connector cards, or Adaptive Cards. [Types of cards](~/task-modules-and-cards/cards/cards-reference.md) provides information on cards, supported by bots in Teams.
+
+## Cards in messaging extensions
-## Cards in Connectors
+[Messaging extensions](~/messaging-extensions/what-are-messaging-extensions.md) can also return a card. Messaging extensions can use simple cards, connector cards, or Adaptive Cards. These cards are found in [types of cards](~/task-modules-and-cards/cards/cards-reference.md).
-Cards were first defined as part of Outlook and Office 365, and are used as part of Office 365 Connectors. Like many Office 365 applications, Teams supports Connectors. You can learn more about Connectors in [Office 365 Connectors for Microsoft Teams](~/webhooks-and-connectors/what-are-webhooks-and-connectors.md), and find the specification for cards in connectors in [Actionable message card reference](/outlook/actionable-messages/card-reference).
+## Types of cards
-## Cards in Bots
+All cards used by Teams are listed in [types of cards](~/task-modules-and-cards/cards/cards-reference.md). This reference also describes differences between Bot Framework cards and cards in Teams.
-The Microsoft Bot Framework extended the cards specification by adding a set of predefined cards that bots could use as part of bot messages. Teams supports bots using the Bot Framework but it supports a slightly different set of these cards. General information on cards in Bot Framework can be found in [Add rich card attachments to messages](/bot-framework/nodejs/bot-builder-nodejs-send-rich-cards). These cards are called *simple cards* in Teams.
+## Adaptive Cards
+
+> [!VIDEO https://www.youtube-nocookie.com/embed/J12lKt717Ws]
+
+[Adaptive Cards](~/task-modules-and-cards/cards/cards-reference.md#adaptive-card) are a new cross product specification for cards in Microsoft products including bots, Cortana, Outlook, and Windows. They are the recommended card type for new Teams development. For general information from the Adaptive Cards team, see [Adaptive Cards overview](/adaptive-cards). You can use Adaptive Cards anywhere you use existing hero cards, Office 365 cards, and thumbnail cards.
+
+In addition to Adaptive Cards, Teams supports two other types of cards:
+
+* Connector cards: Used as part of Office 365 Connectors.
+* Simple cards: Used from the Bot Framework, such as the thumbnail and hero cards.
+
+### Adaptive Cards and Incoming Webhooks
+
+> [!VIDEO https://www.youtube-nocookie.com/embed/y5pbJI43Zvg]
+
+> [!NOTE]
+> * All native Adaptive Card schema elements, except `Action.Submit`, are fully supported.
+> * The supported actions are [**Action.OpenURL**](https://adaptivecards.io/explorer/Action.OpenUrl.html), [**Action.ShowCard**](https://adaptivecards.io/explorer/Action.ShowCard.html), [**Action.ToggleVisibility**](https://adaptivecards.io/explorer/Action.ToggleVisibility.html), and [**Action.Execute**](/adaptive-cards/authoring-cards/universal-action-model#actionexecute).
-Bots in Teams can use any type of card: simple, connector or adaptive. Cards that are supported by bots in Teams are detailed in [Teams Card Reference](~/task-modules-and-cards/cards/cards-reference.md).
+Adaptive Cards with Incoming Webhooks enables you to use the rich and flexible capabilities of Adaptive Cards. It sends data using Incoming Webhooks in Teams from their web service.
-## Cards in Messaging Extensions
+## See also
-[Messaging Extensions](~/messaging-extensions/what-are-messaging-extensions.md) can also return a card. Messaging extensions can use any type of card: simple, connector or adaptive. These cards are found in the [Teams Card Reference](~/task-modules-and-cards/cards/cards-reference.md).
+* [Format cards in Teams](~/task-modules-and-cards/cards/cards-format.md)
+* [Design Adaptive Cards](~/task-modules-and-cards/cards/design-effective-cards.md)
-## Card reference
+## Next step
-All cards used by Teams are listed in the [Teams Card Reference](~/task-modules-and-cards/cards/cards-reference.md). This reference also describes differences between Bot Framework cards and cards in Teams.
+> [!div class="nextstepaction"]
+> [Types of cards](~/task-modules-and-cards/cards/cards-reference.md)
platform What Are Task Modules https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/task-modules-and-cards/what-are-task-modules.md
Title: What are task modules?
+ Title: Task modules
description: Add modal popup experiences to collect or display information to your users from your Microsoft Teams apps localization_priority: Normal + # Task modules
-Task modules allow you to create modal popup experiences in your Teams application. Inside the popup you can run your own custom HTML/JavaScript code, show an `<iframe>`-based widget such as a YouTube or Microsoft Stream video or display an [Adaptive card](/adaptive-cards/). They are especially useful for initiating and completing tasks or displaying rich information like videos or Power BI dashboards. A popup experience is often more natural for users initiating and completing tasks compared to a tab or a conversation-based bot experience.
+Task modules permit you to create modal pop-up experiences in your Teams application. In the pop-up, you can:
+
+* Run your own custom HTML or JavaScript code.
+* Show an `<iframe>`-based widget such as a YouTube or Microsoft Stream video.
+* Display an [Adaptive Card](/adaptive-cards/).
+
+Task modules are useful for initiating and completing tasks or displaying rich information, such as videos or Power Business Intelligence (BI) dashboards. A pop-up experience is often more natural for users initiating and completing tasks compared to a tab or a conversation-based bot experience.
-Task modules build on the foundation of Microsoft Teams tabs; they are essentially a tab inside a popup window. They use the same SDK, so if you've built a tab you are already 90% of the way to being able to create a task module.
+Task modules build on the foundation of Microsoft Teams tabs. They are essentially a tab inside a pop-up window. They use the same SDK, so if you have built a tab you are already familiar with creating a task module.
Task modules can be invoked in three ways:
-* **Channel or personal tabs**: Using the Microsoft Teams Tabs SDK you can invoke task modules from buttons, links or menus on your tab. [This is covered in detail here.](~/task-modules-and-cards/task-modules/task-modules-tabs.md)
-* **Bots**: Buttons on [cards](~/task-modules-and-cards/cards/cards-reference.md) sent from your bot. This is particularly useful when you don't need everyone in a channel to see what you are doing with a bot. For example, when having users respond to a poll in a channel it's not terribly useful to see a record of that poll being created. [This is covered in detail here.](~/task-modules-and-cards/task-modules/task-modules-bots.md)
-* **Outside of Teams from a deep link**: You can also create URLs to invoke a task module from anywhere. [This is covered in detail here.](#task-module-deep-link-syntax)
+* Channel or personal tabs: Using the Microsoft Teams Tabs SDK, you can invoke task modules from buttons, links, or menus on your tab. For more information, see [using task modules in tabs](~/task-modules-and-cards/task-modules/task-modules-tabs.md).
+* Bots: Using buttons on [cards](~/task-modules-and-cards/cards/cards-reference.md) sent from your bot. This is useful when you do not require everyone in a channel to see what you are doing with a bot. For example, when having users respond to a poll in a channel it is not useful to see a record of that poll being created. For more information, see [using task modules from Teams bots](~/task-modules-and-cards/task-modules/task-modules-bots.md).
+* Outside of Teams from a deep link: You can also create URLs to invoke a task module from anywhere. For more information, see [task module deep link syntax](~/task-modules-and-cards/task-modules/invoking-task-modules.md#task-module-deep-link-syntax).
-## Task module looks like
+## Components of a task module
-Here's what a task module looks like when invoked from a bot (without the colored rectangles and numbered circles, of course):
+Here is what a task module looks like when invoked from a bot:
-![Task Module Example](~/assets/images/task-module/task-module-example.png)
+![Task module example](~/assets/images/task-module/task-module-example.png)
-Let's walk through it:
+A task module includes the following as shown in the previous image:
1. Your app's [`color` icon](~/resources/schem#icons).
-1. Your app's [`short` name](~/resources/schem#name).
-1. The task module's title specified in the `title` property of the [TaskInfo object](#the-taskinfo-object).
-1. The task module's close/cancel button. If the user presses this, your app will receive an `err` event as described [here](~/task-modules-and-cards/task-modules/task-modules-tabs.md#example-submitting-the-result-of-a-task-module).
- > [!Note]
- > It is currently not possible to detect this event when a task module is invoked from a bot.
-1. The blue rectangle is the where your web page appears if you are loading your own web page using the `url` property of the [TaskInfo object](#the-taskinfo-object). More detail is in the [task module sizing](#task-module-sizing) section below.
-1. If you are displaying an Adaptive card via the `card` property of the [TaskInfo object](#the-taskinfo-object) the padding is added for you, otherwise you'll need to [handle this yourself](#task-module-css-for-htmljavascript-task-modules).
-1. Adaptive card buttons will render here. If you're using your own page you must create your own buttons.
-
-## Overview of invoking and dismissing task modules
-
-Task modules can be invoked from tabs, bots or deep links and what appears in one can be either HTML or an Adaptive card, so there's a lot of flexibility in terms of how they are invoked and how to deal with the result of a user's interaction. The table below summarizes how this works:
-
-| **Invoked via...** | **Task module is HTML/JavaScript** | **Task module is Adaptive card** |
-| | | |
-| **JavaScript in a tab** | 1. Use the Teams client SDK function `tasks.startTask()` with an optional `submitHandler(err, result)` callback function. <br/><br/> 2. In the task module code, when the user is finished, call the Teams SDK function `tasks.submitTask()` with a `result` object as a parameter. If a `submitHandler` callback was specified in `tasks.startTask()`, Teams calls it with `result` as a parameter.<br/><br/> 3. If there was an error when invoking `tasks.startTask()`, the `submitHandler` function is called with an `err` string instead. <br/><br/> 4. You can also specify a `completionBotId` when calling `teams.startTask()` - in that case `result` is sent to the bot instead. | 1. Call the Teams client SDK function `tasks.startTask()` with a [TaskInfo object](#the-taskinfo-object) and `TaskInfo.card` containing the JSON for the Adaptive card to show in the task module popup. <br/><br/> 2. If a `submitHandler` callback was specified in `tasks.startTask()`, Teams calls it with an `err` string if there was an error when invoking `tasks.startTask()` or if the user closes the task module popup using the X at the upper right. <br/><br/> 3. If the user presses an Action.Submit button then its `data` object is returned as the value of `result`. |
-| **Bot card button** | 1. Bot card buttons, depending on the type of button, can invoke task modules in two ways: a deep link URL or by sending a `task/fetch` message. See below for how deep link URLs work. <br/><br/> 2. If the button's action `type` is `task/fetch` (`Action.Submit` button type for Adaptive cards), a `task/fetch invoke` event (an HTTP POST under the covers) is sent to the bot, and the bot responds to the POST with HTTP 200 and the response body containing a wrapper around the [TaskInfo object](#the-taskinfo-object). This is explained in detail in [invoking a task module via task/fetch](~/task-modules-and-cards/task-modules/task-modules-bots.md#invoking-a-task-module-through-taskfetch).<br/><br/> 3. Teams displays the task module; when the user is finished, call the Teams SDK function `tasks.submitTask()` with a `result` object as a parameter. <br/><br/> 4. The bot receives a `task/submit invoke` message that contains the `result` object. You have three different ways to respond to the `task/submit` message: by doing nothing (the task completed successfully), by displaying a message to the user in a popup window, or by invoking another task module window (i.e. creating a wizard-like experience). These three options are discussed more [in the detailed discussion on task/submit](~/task-modules-and-cards/task-modules/task-modules-bots.md#the-flexibility-of-tasksubmit). | 1. Like buttons on Bot Framework cards, buttons on Adaptive cards support two ways of invoking task modules: deep link URLs with `Action.openUrl` buttons, and via `task/fetch` using `Action.Submit` buttons. <br/><br/> 2. Task modules with Adaptive cards work very similarly to the HTML/JavaScript case (see left). The major difference is that since there's no JavaScript when you're using Adaptive cards, there's no way to call `tasks.submitTask()`. Instead, Teams takes the `data` object from `Action.Submit` and returns it as the payload of in the `task/submit` event, as described [here](~/task-modules-and-cards/task-modules/task-modules-bots.md#the-flexibility-of-tasksubmit). |
-| **Deep link URL** <br/>[URL syntax](#task-module-deep-link-syntax) | 1. Teams invokes the task module; the URL that appears inside the `<iframe>` specified in the `url` parameter of the deep link. There is no `submitHandler` callback. <br/><br/> 2. Within the JavaScript of the page in the task module, call `tasks.submitTask()` to close it with a `result` object as a parameter, the same as when invoking it from a tab or a bot card button. Completion logic is slightly different, however. If your completion logic resides on the client (i.e. if there is no bot) there is no `submitHandler` callback, so any completion logic must be in the code preceding the call to `tasks.submitTask()`. Invocation errors are only reported via the console. If you have a bot, then you can specify a `completionBotId` parameter in the deep link to send the `result` object via a `task/submit` event. | 1. Teams invokes the task module; the JSON card body of the Adaptive card is specified as a URL-encoded value of the `card` parameter of the deep link. <br/><br/> 2. The user closes the task module by clicking on the X at the upper right of the task module or by pressing an `Action.Submit` button on the card. Since there is no `submitHandler` to call, you must have a bot to send the value of the Adaptive card fields to. You use the `completionBotId` parameter in the deep link to specify the bot to send the data to via a `task/submit invoke` event. |
+2. Your app's [`short` name](~/resources/schem#name).
+3. The task module's title specified in the `title` property of the [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object).
+4. The task module's close or cancel button. If the user selects this button, your app receives an `err` event. For more information, see [example for submitting the result of a task module](~/task-modules-and-cards/task-modules/task-modules-tabs.md#example-of-submitting-the-result-of-a-task-module).
-## The TaskInfo object
+ > [!NOTE]
+ > It is currently not possible to detect the `err` event when a task module is invoked from a bot.
-The `TaskInfo` object contains the metadata for a task module. The object definition is below. You **must** define either `url` for an embedded iFrame or `card` for an Adaptive Card.
-
-| Attribute | Type | Description |
-| | | |
-| `title` | string | Appears below the app name and to the right of the app icon. |
-| `height` | number or string | This can be a number representing the task module's height in pixels, or `small`, `medium`, or `large`. [See below for how height and width are handled](#task-module-sizing). |
-| `width` | number or string | This can be a number representing the task module's width in pixels, or `small`, `medium`, or `large`. [See below for how height and width are handled](#task-module-sizing). |
-| `url` | string | The URL of the page loaded as an `<iframe>` inside the task module. The URL's domain must be in the app's [validDomains array](~/resources/schem#validdomains) in your app's manifest. |
-| `card` | Adaptive card or an Adaptive card bot card attachment | The JSON for the Adaptive card to appear in the task module. If you're invoking from a bot, you'll need to use the Adaptive card JSON in a Bot Framework `attachment` object. From a tab you'll use just an Adaptive Card. [Here's an example.](#adaptive-card-or-adaptive-card-bot-card-attachment) |
-| `fallbackUrl` | string | If a client does not support the task module feature, this URL is opened in a browser tab. |
-| `completionBotId` | string | Specifies a bot App ID to send the result of the user's interaction with the task module to. If specified, the bot will receive a `task/submit invoke` event with a JSON object in the event payload. |
-
-> [!NOTE]
-> The task module feature requires that the domains of any URLs you want to load are included in the `validDomains` array in your app's manifest.
-
-## Task module sizing
-
-Using integers for `TaskInfo.width` and `TaskInfo.height` will set the height and width in pixels. However, depending on the size of the Team's window and screen resolution they will be reduced proportionally while maintaining the aspect ratio (width/height).
-
-If `TaskInfo.width` and `TaskInfo.height` are `"small"`, `"medium"` or `"large"` the size of the red rectangle in the picture above is a proportion of the available space: 20%, 50%, 60% for `width` and 20%, 50%, 66% for `height`.
-
-Task modules invoked from a tab can be dynamically resized. After calling `tasks.startTask()` you can call `tasks.updateTask(newSize)` where height and width properties on the newSize object conform to the TaskInfo spec (ex. `{ height: 'medium', width: 'medium' }`).
-
-## Task module CSS for HTML/JavaScript task modules
-
-HTML/JavaScript-based task modules have access to the entire area of the task module below the header. While that offers a great deal of flexibility, if you want padding around the edges to align with the header elements and avoid unnecessary scrollbars you'll need to provide the right CSS. Here are some examples for a few use cases.
-
-### Example 1 - YouTube video
-
-YouTube offers the ability to embed videos on web pages. Using a simple stub web page it's easy to show this in a task module:
-
-![YouTube video](~/assets/images/task-module/youtube-example.png)
-
-Here's the HTML for this page, without the CSS:
-
-```html
-<!DOCTYPE html>
-<html lang="en">
-<head>
- Γï«
-</head>
-<body>
- <div id="embed-container">
- <iframe width="1000" height="700" src="https://www.youtube.com/embed/rd0Rd8w3FZ0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe>
- </div>
-</body>
-</html>
-```
-
-The CSS looks like this:
-
-```css
-#embed-container iframe {
- position: absolute;
- top: 0;
- left: 0;
- width: 95%;
- height: 95%;
- padding-left: 20px;
- padding-right: 20px;
- padding-top: 10px;
- padding-bottom: 10px;
- border-style: none;
-}
-```
-
-### Example 2 - PowerApp
-
-You can use the same approach to embed a PowerApp as well. As the height/width of any individual PowerApp is customizable, you may need to adjust the height and width to achieve your desired presentation.
-
-![Asset Management PowerApp](~/assets/images/task-module/powerapp-example.png)
-
-```html
-<iframe width="720" height="520" src="https://web.powerapps.com/webplayer/iframeapp?source=iframe&screenColor=rgba(104,101,171,1)&appId=/providers/Microsoft.PowerApps/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></iframe>
-```
-
-And the CSS is:
-
-```css
-#embed-container iframe {
- position: absolute;
- top: 0;
- left: 0;
- width: 94%;
- height: 95%;
- padding-left: 20px;
- padding-right: 20px;
- padding-top: 10px;
- padding-bottom: 10px;
- border-style: none;
-}
-```
-
-## Adaptive card or Adaptive card bot card attachment
-
-As we noted above, depending on how you're invoking your `card` you'll need to use either an Adaptive card, or an Adaptive card bot card attachment (which is just an Adaptive card wrapped in an attachment object).
-
-When you're invoking from a tab, you'll need to use an adaptive card. Here's a very simple example:
-
-```json
-{
- "type": "AdaptiveCard",
- "body": [
- {
- "type": "TextBlock",
- "text": "Here is a ninja cat:"
- },
- {
- "type": "Image",
- "url": "http://adaptivecards.io/content/cats/1.png",
- "size": "Medium"
- }
- ],
- "version": "1.0"
-}
-```
-
-When you're invoking from a bot you'll need to use an Adaptive card bot card attachment as in the example below:
-
-```json
-{
- "contentType": "application/vnd.microsoft.card.adaptive",
- "content": {
- "type": "AdaptiveCard",
- "body": [
- {
- "type": "TextBlock",
- "text": "Here is a ninja cat:"
- },
- {
- "type": "Image",
- "url": "http://adaptivecards.io/content/cats/1.png",
- "size": "Medium"
- }
- ],
- "version": "1.0"
- }
-}
-```
-
-You'll need to remember whether you are invoking a task module containing an Adaptive card from a bot or a tab.
-
-## Task module deep link syntax
-
-A task module deep link is just a serialization of the [TaskInfo object](#the-taskinfo-object) with two other pieces of information, `APP_ID` and optionally the `BOT_APP_ID`:
-
-`https://teams.microsoft.com/l/task/APP_ID?url=<TaskInfo.url>&height=<TaskInfo.height>&width=<TaskInfo.width>&title=<TaskInfo.title>&completionBotId=BOT_APP_ID`
-
-`https://teams.microsoft.com/l/task/APP_ID?card=<TaskInfo.card>&height=<TaskInfo.height>&width=<TaskInfo.width>&title=<TaskInfo.title>&completionBotId=BOT_APP_ID`
-
-See [TaskInfo object](#the-taskinfo-object) for the data types and allowable values for `<TaskInfo.url>`, `<TaskInfo.card>`, `<TaskInfo.height>`, `<TaskInfo.width>`, and `<TaskInfo.title>`.
-
-> [!TIP]
-> Be sure to URL encode the deep link, especially when using the `card` parameter (for example, JavaScript's [`encodeURI()` function](https://www.w3schools.com/jsref/jsref_encodeURI.asp)).
-
-Here's the information on `APP_ID` and `BOT_APP_ID`:
-
-| Value | Type | Required? | Description |
-| | | | |
-| `APP_ID` | string | Yes | The [id](~/resources/schem#validdomains) in the manifest for `APP_ID` must contain the domain for `url` if `url` is in the URL. (The app ID is already known when a task module is invoked from a tab or a bot, which is why it's not included in `TaskInfo`.) |
-| `BOT_APP_ID` | string | No | If a value for `completionBotId` is specified, the `result` object is sent via a a `task/submit invoke` message to the specified bot. `BOT_APP_ID` must be specified as a bot in the app's manifest, i.e. you can't just send it to any bot. |
-
-Note that it's valid for `APP_ID` and `BOT_APP_ID` to be the same, and in many cases will be if an app has a bot since it's recommended to use that as an app's ID if there is one.
-
-## Keyboard and accessibility guidelines
-
-With HTML/JavaScript-based task modules it is your responsibility to ensure your app's task module can be used with a keyboard. Screen reader programs also depend on the ability to navigate using the keyboard. As a practical matter this means two things:
-
-1. Using the [tabindex attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) in your HTML tags to control which elements can be focused and if/where it participates in sequential keyboard navigation (usually with the <kbd>Tab</kbd> and <kbd>Shift-Tab</kbd> keys).
-2. Handling the <kbd>Esc</kbd> key in the JavaScript for your task module. Here's a code sample showing how to do this:
-
- ```javascript
- // Handle the Esc key
- document.onkeyup = function(event) {
- if ((event.key === 27) || (event.key === "Escape")) {
- microsoftTeams.submitTask(null); // this will return an err object to the completionHandler()
- }
- }
- ```
-
-Microsoft Teams will ensure that keyboard navigation works properly from the task module header into your HTML and vice-versa.
-
-## Code sample
-|**Sample name** | **Description** | **.NET** | **Node.js**|
-|-|--|--|-|
-|Task module sample (Bots-V4) | Samples for creating task modules. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/csharp)|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-task-module/nodejs)|
-|Task module sample (Tabs + Bots-V3) | Samples for creating task modules. |[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/54.teams-task-module)|[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/54.teams-task-module)|
+5. The blue rectangle is where your web page appears if you are loading your own web page using the `url` property of the [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object). For more information, see [task module sizing](~/task-modules-and-cards/task-modules/invoking-task-modules.md#task-module-sizing).
+6. If you are displaying an Adaptive Card using the `card` property of the [TaskInfo object](~/task-modules-and-cards/task-modules/invoking-task-modules.md#the-taskinfo-object) the padding is added for you. For more information, see [task module CSS for HTML or JavaScript task modules](~/task-modules-and-cards/task-modules/invoking-task-modules.md#task-module-css-for-html-or-javascript-task-modules).
+7. Adaptive Card buttons render after you select **Sign up**. When using your own page, create your own buttons.
## See also
-* [Request device permissions](../concepts/device-capabilities/native-device-permissions.md)
-* [Integrate media capabilities](../concepts/device-capabilities/mobile-camera-image-permissions.md)
-* [Integrate QR or barcode scanner capability in Teams](../concepts/device-capabilities/qr-barcode-scanner-capability.md)
-* [Integrate location capabilities in Teams](../concepts/device-capabilities/location-capability.md)
+[Cards](~/task-modules-and-cards/what-are-cards.md)
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Invoke and dismiss task modules](~/task-modules-and-cards/task-modules/invoking-task-modules.md)
platform Add Incoming Webhook https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/webhooks-and-connectors/how-to/add-incoming-webhook.md
Title: Post external requests to Microsoft Teams with incoming webhooks-
-description: how to add incoming webhook to Teams app
+ Title: Create an Incoming Webhook
+
+description: describes how to add Incoming Webhook to Teams app and post external requests to Teams with incoming webhooks
keywords: teams tabs outgoing webhook localization_priority: Normal
-# Post external requests to Teams with incoming webhooks
-## What are incoming webhooks in Teams?
+# Create Incoming Webhook
-Incoming webhooks are special type of Connector in Teams that provide a simple way for an external app to share content in team channels and are often used as tracking and notification tools. Teams provides a unique URL to which you send a JSON payload with the message that you want to POST, typically in a card format. Cards are user-interface (UI) containers that contain content and actions related to a single topic and are a way to present message data in a consistent way. Teams uses cards within three capabilities:
+Incoming Webhook allows any external apps to share content in Teams channels. These webhooks are used as tracking and notifying tools. They provide a unique URL, to which you send a JSON payload with a message in card format. Cards are user interface containers that include content and actions related to a single topic. Teams use cards within the following capabilities:
* Bots * Messaging extensions * Connectors
-## Incoming webhook key features
+## Key features of Incoming Webhook
-| Feature | Description |
+The following table provides the features and description of Incoming Webhook:
+
+| Features | Description |
| - | -- |
-|Scoped Configuration|Incoming webhooks are scoped and configured at the channel level. For example, outgoing webhooks are scoped and configured at the team level.|
-|Secure resource definitions|Messages are formatted as JSON payloads. This declarative messaging structure prevents the injection of malicious code as there is no code execution on the client.|
-|Actionable messaging support|If you choose to send messages via cards, you must use the **actionable message card** format. Actionable message cards are supported in all Office 365 groups including Teams. Here are links to the [Legacy actionable message card reference](/outlook/actionable-messages/message-card-reference) and the [Message card playground](https://messagecardplayground.azurewebsites.net).|
-|Independent HTTPS messaging support| Cards are a great way to present information in a clear and consistent way. Any tool or framework that can send HTTPS POST requests can send messages to Teams via an incoming webhook.|
-|Markdown support|All text fields in actionable messaging cards support basic Markdown. **Don't use HTML markup in your cards**. HTML is ignored and treated as plain text.|
+|Adaptive Cards using an Incoming Webhook|Adaptive Cards can be sent through Incoming Webhooks. For more information, see [Send Adaptive Cards using Incoming Webhooks](../../webhooks-and-connectors/how-to/connectors-using.md#send-adaptive-cards-using-an-incoming-webhook).|
+|Actionable messaging support|Actionable message cards are supported in all Office 365 groups including Teams. If you send messages through cards, you must use the actionable message card format. For more information, see [legacy actionable message card reference](/outlook/actionable-messages/message-card-reference) and [message card playground](https://messagecardplayground.azurewebsites.net).|
+|Independent HTTPS messaging support|Cards provide information clearly and consistently. Any tool or framework that can send HTTPS POST requests, can send messages to Teams through an Incoming Webhook.|
+|Markdown support|All text fields in actionable messaging cards support basic Markdown. Do not use HTML markup in your cards. HTML is ignored and treated as plain text.|
+|Scoped configuration|Incoming Webhook is scoped and configured at the channel level.|
+|Secure resource definitions|Messages are formatted as JSON payloads. This declarative messaging structure prevents the insertion of malicious code.|
+
+> [!NOTE]
+> * Teams bots, messaging extensions, Incoming Webhook, and the Bot Framework support Adaptive Cards, an open cross card platform framework. Currently, [Teams connectors](../../webhooks-and-connectors/how-to/connectors-creating.md) do not support Adaptive Cards. However, it is possible to create a [flow](https://flow.microsoft.com/blog/microsoft-flow-in-microsoft-teams/) that posts Adaptive Cards to a Teams channel.
+> * For more information on cards and webhooks, see [Adaptive cards and Incoming Webhooks](~/task-modules-and-cards/what-are-cards.md#adaptive-cards-and-incoming-webhooks).
+
+## Create Incoming Webhook
+
+**To add an Incoming Webhook to a Teams channel**
+
+1. Go to the channel where you want to add the webhook and select &#8226;&#8226;&#8226; **More options** from the top navigation bar.
+1. Select **Connectors** from the dropdown menu:
+
+ ![Select Connector](~/assets/images/connectors.png)
+
+1. Search for **Incoming Webhook** and select **Add**.
+1. Select **Configure**, provide a name, and upload an image for your webhook if required:
+
+ ![Configure button](~/assets/images/configure.png)
+
+1. The dialog window presents a unique URL that maps to the channel. Copy and save the webhook URL, to send information to Microsoft Teams and select **Done**:
+
+ ![Unique URL](~/assets/images/url.png)
+
+The webhook is available in the Teams channel.
+
+> [!NOTE]
+> In Teams, select **Settings** > **Member permissions** > **Allow members to create, update, and remove connectors**, so that any team member can add, modify, or delete a connector.
+
+## Remove Incoming Webhook
+
+**To remove an Incoming Webhook from a Teams channel**
-> [!Note]
-> Teams bots, messaging extensions, incoming webhooks, and the Bot Framework support Adaptive Cards, an open cross-card platform framework. [Teams connectors](../../webhooks-and-connectors/how-to/connectors-creating.md) do not currently support Adaptive Cards. However, it is possible to create a [flow](https://flow.microsoft.com/blog/microsoft-flow-in-microsoft-teams/) that posts Adaptive Cards to a Teams channel.
+1. Go to the channel.
+1. Select &#8226;&#8226;&#8226; **More options** from the top navigation bar.
+1. Select **Connectors** from the dropdown menu.
+1. On the left, under **Manage**, select **Configured**.
+1. Select the **<*1*> Configured** to see a list of your current connectors:
-## Add an incoming webhook to a Teams channel
+ ![Configured webhook](~/assets/images/configured.png)
-> [!Important]
-> If your team's **Settings** => **Member permissions** => **Allow members to create, update, and remove connectors** is selected, any team member can add, modify, or delete a connector.
+1. Select **Manage** next to the connector that you want to remove:
-**To add an incoming webhook**
+ ![Manage webhook](~/assets/images/manage.png)
-1. Navigate to the channel where you want to add the webhook and select (&#8226;&#8226;&#8226;) *More Options* from the top navigation bar.
-1. Choose **Connectors** from the drop-down menu and search for **Incoming Webhook**.
-1. Select the **Configure** button, provide a name, and, optionally, upload an image avatar for your webhook.
-1. The dialog window will present a unique URL that will map to the channel. Make sure that you **copy and save the URL**ΓÇöyou will need to provide it to the outside service.
-1. Select the **Done** button. The webhook will be available in the team channel.
+1. Select **Remove**:
-## Remove an incoming webhook from a Teams channel
+ ![Remove webhook](~/assets/images/remove.png)
-**To remove an incoming webhook**
+ The **Remove Configuration** dialog box appears:
-1. Navigate to the channel where the webhook was added and select (&#8226;&#8226;&#8226;) *More Options* from the top navigation bar.
-1. Choose **Connectors** from the drop-down menu.
-1. On the left, under **Manage**, choose **Configured**.
-1. Select the *number Configured* to see a list of your current connectors.
-1. Select **Manage** next to the connector that you want to delete.
-1. Select the **Remove** button and you will be presented with a *Remove Configuration* dialog box.
-1. Optionally, complete the dialog box fields and checkboxes prior to selecting the **Remove** button. The webhook will be deleted from the team channel.
+ ![Remove Configuration](~/assets/images/removeconfiguration.png)
-## Distribution
+1. Complete the dialog box fields and checkboxes and select **Remove**:
-You have three options for distributing your incoming webhook:
+ ![Final Remove](~/assets/images/finalremove.png)
-* Set up an incoming webhook directly for your team.
-* Add a configuration page and wrap your incoming webhook in a [O365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md)
-* Package and publish your Connector as part of your [AppSource](~/concepts/deploy-and-publish/office-store-guidance.md) submission.
+ The webhook is removed from the Teams channel.
## See also
-[Sending messages to Connectors and Webhooks](~/webhooks-and-connectors/how-to/connectors-using.md)
+* [Create an Outgoing Webhook](~/webhooks-and-connectors/how-to/add-outgoing-webhook.md)
+* [Create an Office 365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md)
+* [Create and send messages](~/webhooks-and-connectors/how-to/connectors-using.md)
platform Add Outgoing Webhook https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/webhooks-and-connectors/how-to/add-outgoing-webhook.md
Title: Add custom bots to Microsoft Teams with outgoing webhooks
-description: describes how to add an outgoing webhook
+ Title: Create an Outgoing Webhook
+
+description: describes how to create an Outgoing Webhook
- localization_priority: Normal+ keywords: teams tabs outgoing webhook actionable message verify webhook
-# Add custom bots to Teams with outgoing webhooks
-## Outgoing webhooks in Teams
+# Create Outgoing Webhook
-Webhooks are an eminent way for Teams to integrate with external apps. A webhook is essentially a POST request sent to a callback URL. Outgoing webhooks allow users to send messages to your web service without going through the full process of creating bots via the [Microsoft Bot Framework](https://dev.botframework.com/).
+The Outgoing Webhook acts as a bot and search for messages in channels using **@mention**. It sends notifications to external web services and responds with rich messages, which include cards and images. It helps to skip the process of creating bots through the [Microsoft Bot Framework](https://dev.botframework.com/).
-Outgoing webhook sends data from Teams to any chosen service capable of accepting a JSON payload. After adding the outgoing webhooks to a team, it acts as a bot and looks for messages in channels using **\@mention**. It sends notifications to external web services and responds with rich messages, which include cards and images.
+## Key features of Outgoing Webhook
-## Outgoing webhook key features
+The following table provides the features and description of Outgoing Webhooks:
-| Feature | Description |
+| Features | Description |
| - | -- |
-| Scoped configuration| Webhooks are scoped at the team level. You must go through the setup process for each team where you want to add your outgoing webhook. |
-| Reactive messaging| Users must use @mention for the webhook to receive messages. Currently, users can only message an outgoing webhook in public channels and not within the personal or private scope. |
-|Standard HTTP message exchange|Responses appear in the same chain as the original request message and can include any bot framework message content, for example, rich text, images, cards, and emojis. Although outgoing webhooks can use cards, they cannot use any card actions except for `openURL`.|
-| Teams API method support|Outgoing webhook sends an HTTP POST to a web service and process a response back. They cannot access any other APIs like retrieve the roster or list of channels in a team.|
+| Scoped configuration| Webhooks are scoped at the team level. Mandatory set up process for each adds an Outgoing Webhook. |
+| Reactive messaging| Users must use @mention for the webhook to receive messages. Currently, users can only message an Outgoing Webhook in public channels and not within the personal or private scope. |
+|Standard HTTP message exchange|Responses appear in the same chain as the original request message and can include any Bot Framework message content, for example, rich text, images, cards, and emojis. Although Outgoing Webhooks can use cards, they cannot use any card actions except for `openURL`.|
+| Teams API method support|Outgoing Webhooks sends an HTTP POST to a web service and gets a response. They cannot access any other APIs, such as retrieve the roster or list of channels in a team.|
-## Creating actionable messages
+## Create Outgoing Webhooks
-The connector cards include three visible buttons on the card. Each button is defined in the `potentialAction` property of the message by using `ActionCard` actions. Each `ActionCard` contains an input type; a text field, a date picker, or a multi-choice list. Each `ActionCard` action has an associated action, for example, `HttpPOST`.
+Create Outgoing Webhooks and add custom bots to Teams.
-Connector cards support three types of actions:
+**To create an Outgoing Webhook**
-| Action | Description |
-| - | -- |
-| `ActionCard` |Presents one or more input types and associated actions.|
-| `HttpPOST` | Sends a POST request to a URL. |
-| `OpenUri` | Opens a URI in a separate browser or app, optionally targets different URIs based on operating systems.|
+1. Select **Teams** from the left pane. The **Teams** page appears:
-The `ActionCard` action supports three input types:
+ ![Teams channel](~/assets/images/teamschannel.png)
-| Input type | Description |
-| - | -- |
-| `TextInput` | A single-line or multiline text field with an optional length limit. |
-| `DateInput` | A date selector with an optional time selector. |
-| `MultichoiceInput` | A specified list of choices, offering either a single selection or multiple selections.|
+1. In the **Teams** page, select the required team to create an Outgoing Webhook and select the &#8226;&#8226;&#8226;. In the dropdown menu, select **Manage team**:
-`MultichoiceInput` supports a `style` property that controls the display of a fully expanded list. The default value of `style` depends on the `isMultiSelect` value.
+ ![Create Outgoing Webhook](~/assets/images/outgoingwebhook1.png)
-| `isMultiSelect` value | `style` default value |
-| | |
-| `false` or not specified | The default style is `compact`|
-| `true` | The default style is `expanded` |
+1. Select the **Apps** tab on the channel page:
-> [!NOTE]
-> * Enter both `"isMultiSelect": true` and `"style": true`, if you want the multi-select list to be displayed in a compact style.
-> * Selecting `compact` for the `style` property in Teams is the same as selecting `normal` for the `style` property in Microsoft Outlook.
-> * Webhooks support only Office 365 message back cards and adaptive cards.
+ ![Create an Outgoing Webhook](~/assets/images/outgoingwebhook2.png)
+
+1. Select **Create an Outgoing Webhook**:
+
+ ![Create Outgoing Webhooks](~/assets/images/outgoingwebhook3.png)
+
+1. Type the following details in the **Create an Outgoing Webhook** page:
-For all other details about connector card actions, see **[Actions](/outlook/actionable-messages/card-reference#actions)** in the actionable message card reference.
+ * **Name**: The webhook title and @mention tab.
+ * **Callback URL**: The HTTPS endpoint that accepts JSON payloads and receives POST requests from Teams.
+ * **Description**: A detailed string that appears in the profile card and the team-level App dashboard.
+ * **Profile Picture**: An app icon for your webhook, which is optional.
-## Adding outgoing webhooks to your app
+1. Select **Create**. The Outgoing Webhook is added to the current team's channel:
-**Scenario**: Push change status notifications on a Teams channel database server to your app.
-**Example**: You have a line-of-business app that tracks all CRUD operations made to employee records by Teams channel HR users across an Office 365 tenancy.
+ ![create Outgoing Webhook](~/assets/images/outgoingwebhook.png)
-### 1. Create a URL on your app's server to accept and process a POST request with a JSON payload
+A [Hash-based Message Authentication Code (HMAC)](https://security.stackexchange.com/questions/20129/how-and-when-do-i-use-hmac/20301) dialogue box appears. It is a security token used to authenticate calls between Teams and the designated outside service.
-Your service receives messages in a standard Azure bot service messaging schema. The bot framework connector is a RESTful service that empowers your service to process the interchange of JSON formatted messages via HTTPS protocols as documented in the [Azure Bot Service API](/bot-framework/rest-api/bot-framework-rest-connector-api-reference). Alternatively, you can follow the [Microsoft Bot Framework SDK] to process and parse messages. See also [About Azure Bot Service](/azure/bot-service/bot-service-overview-introduction).
+>[!NOTE]
+> The Outgoing Webhook is available to the team's users, only if the URL is valid and the server and client authentication tokens are equal. For example, an HMAC handshake.
+The following scenario provides the details to add an Outgoing Webhook:
-Outgoing webhooks are scoped to the `team` level and are visible to all the team members. Just like a bot, users need to **\@mention** the name of the outgoing webhook to invoke it in the channel.
+* Scenario: Push change status notifications on a Teams channel database server to your app.
+* Example: You have a line of business app that tracks all CRUD operations, such as create, read, update, and delete. These operations are made to the employee records by Teams channel HR users across an Office 365 tenancy.
-### 2. Create a method to verify the outgoing webhook HMAC token
+# [URL JSON payload](#tab/urljsonpayload)
+**Create a URL on your app's server to accept and process a POST request with a JSON payload**
-#### HMAC signature for testing with code example
+Your service receives messages in a standard Azure bot service messaging schema. The Bot Framework connector is a RESTful service that empowers to process the interchange of JSON formatted messages through HTTPS protocols as documented in the [Azure Bot Service API](/bot-framework/rest-api/bot-framework-rest-connector-api-reference). Alternatively, you can follow the Microsoft Bot Framework SDK to process and parse messages. For more information, see [overview of Azure Bot Service](/azure/bot-service/bot-service-overview-introduction).
-Using example of inbound message and id: "contoso" of SigningKeyDictionary of {"contoso", "vqF0En+Z0ucuRTM/01o2GuhMH3hKKk/N2bOmlM31zaA=" }.
+Outgoing Webhooks are scoped to the `team` level and are visible to all the team members. Users need to **\@mention** the name of the Outgoing Webhook to invoke it in the channel.
+
+# [Verify HMAC token](#tab/verifyhmactoken)
+**Create a method to verify the Outgoing Webhook HMAC token**
+
+Using example of inbound message and ID: "contoso" of SigningKeyDictionary of {"contoso", "vqF0En+Z0ucuRTM/01o2GuhMH3hKKk/N2bOmlM31zaA=" }.
Use the value "HMAC 03TCao0i55H1eVKUusZOTZRjtvYTs+mO41mPL+R1e1U=" in the authorization of request header.
-To ensure that your service is receiving calls only from actual Teams clients, Teams provides an HMAC code in the HTTP `hmac` header. Always included the code in your authentication protocol.
+To ensure that your service is receiving calls only from actual Teams clients, Teams provides an HMAC code in the HTTP `hmac` authorization header. Always include the code in your authentication protocol.
-Your code must always validate the HMAC signature included in the request:
+Your code must always validate the HMAC signature included in the request as follows:
-* Generate the HMAC token from the request body of the message. There are standard libraries to do this on most platforms (see [Crypto](https://nodejs.org/api/crypto.html#crypto_crypto) for Node.js or see [Teams Webhook Sample](https://github.com/OfficeDev/microsoft-teams-sample-outgoing-webhook/blob/23eb61da5a18634d51c5247944843da9abed01b6/WebhookSampleBot/Models/AuthProvider.cs) for C\#). Microsoft Teams uses standard SHA256 HMAC cryptography. You need to convert the body to a byte array in UTF8.
-* Compute the hash from the byte array of the security token **provided by Teams** when you registered the outgoing webhook in the Teams client]. See [Create an outgoing webhook](#create-an-outgoing-webhook).
+* Generate the HMAC token from the request body of the message. There are standard libraries to do this on most platform, such as [Crypto](https://nodejs.org/api/crypto.html#crypto_crypto) for Node.js and [Teams webhook sample](https://github.com/OfficeDev/microsoft-teams-sample-outgoing-webhook/blob/23eb61da5a18634d51c5247944843da9abed01b6/WebhookSampleBot/Models/AuthProvider.cs) for C\#). Microsoft Teams uses standard SHA256 HMAC cryptography. You must convert the body to a byte array in UTF8.
+* Compute the hash from the byte array of the security token provided by Teams when you registered the Outgoing Webhook in the Teams client. See [create an Outgoing Webhook](#create-outgoing-webhook).
* Convert the hash to a string using UTF-8 encoding. * Compare the string value of the generated hash with the value provided in the HTTP request.
-### 3. Create a method to send a success or failure response
+# [Method to respond](#tab/methodtorespond)
+**Create a method to send a success or failure response**
-Responses from your outgoing webhooks appear in the same reply chain as the original message. When the user performs a query, Microsoft Teams issues a synchronous HTTP request to your service and your code gets five seconds to respond to the message before the connection times out and terminates.
+Responses from your Outgoing Webhooks appear in the same reply chain as the original message. When the user performs a query, Microsoft Teams issues a synchronous HTTP request to your service and your code gets five seconds to respond to the message before the connection times out and terminates.
### Example response
Responses from your outgoing webhooks appear in the same reply chain as the orig
"text": "This is a reply!" } ```+ > [!NOTE]
-> * You can send Adaptive Card, Hero card, and text messages as attachment with outgoing webhook.
-> * Cards support formatting. For more information, see [format cards with markdown](~/task-modules-and-cards/cards/cards-format.md?tabs=adaptive-md%2Cconnector-html#formatting-cards-with-markdown).
+> * You can send Adaptive Card, Hero card, and text messages as attachment with Outgoing Webhook.
+> * Cards support formatting. For more information, see [format cards with markdown](~/task-modules-and-cards/cards/cards-format.md?tabs=adaptive-md%2Cconnector-html#format-cards-with-markdown).
Following codes are examples of an Adaptive Card response:
var responseMsg = JSON.stringify({
* * *
-## Create an outgoing webhook
-
-1. Select the appropriate team and choose **Manage team** from the (&#8226;&#8226;&#8226;) drop-down menu.
-1. Choose the **Apps** tab from the navigation bar.
-1. From the window's lower right corner select **Create an outgoing webhook**.
-1. In the resulting popup window complete the required fields:
-
->* **Name**: The webhook title and @mention tap
->* **Callback URL**: The HTTPS endpoint that accepts JSON payloads and receives POST requests from Teams
->* **Description**: A detailed string that appear in the profile card and the team-level App dashboard
->* **Profile Picture**: An optional app icon for your webhook
->* Select the **Create** button from the lower right corner of the pop-up window and the outgoing webhook are added to the current team's channels.
->* The next dialog window displays an [Hash-based Message Authentication Code (HMAC)](https://security.stackexchange.com/questions/20129/how-and-when-do-i-use-hmac/20301) security token that is used to authenticate calls between Teams and the designated outside service.
->* The outgoing webhook is available to the team's users, only if the URL is valid and the server and client authentication tokens are equal for example, an HMAC handshake.
- ## Code sample+ |**Sample name** | **Description** | **.NET** | **Node.js** | |-||--|-|
-| Outgoing webhooks | Samples to create **Custom Bots** to be used in Microsoft Teams.| [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/outgoing-webhook/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/outgoing-webhook/nodejs)|
+| Outgoing Webhooks | Samples to create custom bots to be used in Microsoft Teams.| [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/outgoing-webhook/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/outgoing-webhook/nodejs)|
+## See also
+* [Create an Incoming Webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md)
+* [Create an Office 365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md)
+* [Create and send messages](~/webhooks-and-connectors/how-to/connectors-using.md)
platform Connectors Creating https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/webhooks-and-connectors/how-to/connectors-creating.md
Title: Office 365 Connectors
+ Title: Create Office 365 Connectors
+ description: Describes how to get started with Office 365 Connectors in Microsoft Teams keywords: teams o365 connector localization_priority: Normal Previously updated : 04/19/2019 Last updated : 06/16/2021
-# Creating Office 365 Connectors for Microsoft Teams
+# Create Office 365 Connectors
-With Microsoft Teams apps, you can add your existing Office 365 Connector or build a new one to include in Microsoft Teams. See [Build your own Connector](/outlook/actionable-messages/connectors-dev-dashboard#build-your-own-connector) for more information.
+With Microsoft Teams apps, you can add your existing Office 365 Connector or build a new one within Teams. For more information, see [build your own connector](/outlook/actionable-messages/connectors-dev-dashboard#build-your-own-connector).
-## Adding a Connector to your Teams App
+## Add a connector to Teams app
-You can distribute your registered Connector as part of your Teams app package. Whether as a standalone solution, or one of several [capabilities](~/concepts/extensibility-points.md) that your experience enables in Teams, you can [package](~/concepts/build-and-test/apps-package.md) and [publish](~/concepts/deploy-and-publish/apps-publish.md) your Connector as part of your AppSource submission, or you can provide it to users directly for uploading within Teams.
+You can [package](~/concepts/build-and-test/apps-package.md) and [publish](~/concepts/deploy-and-publish/apps-publish.md) your connector as part of your AppSource submission. You can distribute your registered connector as part of your Teams app package. For information on entry points for Teams app, see [capabilities](~/concepts/extensibility-points.md). You can also provide the package to users directly for uploading within Teams.
-To distribute your Connector, you need to register by using the [Connectors Developer Dashboard](https://outlook.office.com/connectors/home/login/#/publish). By default, once a Connector is registered, it's assumed that your Connector will work in all Office 365 products that support them, including Outlook and Teams. If that is _not_ the case and you need to create a Connector that only works in Microsoft Teams, contact us directly at [Microsoft Teams App Submissions](mailto:teamsubm@microsoft.com).
+To distribute your connector, you must register through [Connectors Developer Dashboard](https://outlook.office.com/connectors/home/login/#/publish). When a connector is registered, it is assumed that it works in all Office 365 products that support applications, including Outlook and Teams. If that is not the case and you must create a connector that only works in Microsoft Teams, contact: [Microsoft Teams App Submissions email](mailto:teamsubm@microsoft.com).
> [!IMPORTANT]
-> After you choose **Save** in the Connectors Developer Dashboard, your Connector is registered. If you want to publish your Connector in AppSource, follow the instructions in [Publish your Microsoft Teams app to AppSource](~/concepts/deploy-and-publish/apps-publish.md). If you do not wish to publish your app in AppSource, and rather simply distribute it directly to your organization only, you can do so by [publishing to your organization](#publish-connectors-for-your-organization). If you only want to publish to your organization, no further action is necessary on the Connector dashboard.
+> Your connector is registered after you select **Save** in the Connectors Developer Dashboard. If you want to publish your connector in AppSource, follow the instructions in [publish your Microsoft Teams app to AppSource](~/concepts/deploy-and-publish/apps-publish.md). If you do not want to publish your app in AppSource, distribute it directly to the organization. After [publishing connectors for your organization](/connectors-creating.md), no further action is required on the Connector Dashboard.
-### Integrating the configuration experience
+### Integrate the configuration experience
-Your users will complete the entire Connector configuration experience without having to leave the Teams client. To achieve this experience, Teams will embed your configuration page directly within an iframe. The sequence of operations is as follows:
+Users can complete the entire connector configuration experience without having to leave the Teams client. To get the experience, Teams can embed your configuration page directly within an iframe. The sequence of operations is as follows:
-1. The user clicks on your connector to begin the configuration process.
-2. Teams will load your configuration experience in line.
-3. The user interacts with your web experience to complete the configuration.
-4. The user presses "Save", which triggers a callback in your code.
-5. Your code will process the save event by retrieving the webhook settings (documented below). Your code should then store the webhook to post events later.
+1. The user selects the connector to begin the configuration process.
+1. The user interacts with the web experience to complete the configuration.
+1. The user selects **Save**, which triggers a callback in code.
-You can reuse your existing web configuration experience or create a separate version to be hosted specifically in Teams. Your code should:
+ > [!NOTE]
+ > * The code can process the save event by retrieving the webhook settings. Your code stores the webhook to post events later.
+ > * The configuration experience is loaded inline within Teams.
-1. Include the Microsoft Teams JavaScript SDK. This gives your code access to APIs to perform common operations like getting the current user/channel/team context and initiating authentication flows. Initialize the SDK by calling `microsoftTeams.initialize()`.
-2. Call `microsoftTeams.settings.setValidityState(true)` when you want to enable the Save button. You should do this as a response to valid user input, such as a selection or field update.
-3. Register a `microsoftTeams.settings.registerOnSaveHandler()` event handler, which gets called when the user clicks Save.
-4. Call `microsoftTeams.settings.setSettings()` to save the connector settings. What's saved here is also what will be shown in the configuration dialog if the user tries to update an existing configuration for your connector.
-5. Call `microsoftTeams.settings.getSettings()` to fetch webhook properties, including the URL itself. You should call this In addition to during the save event, you should also call this when your page is first loaded in the case of a re-configuration.
-6. (Optional) Register a `microsoftTeams.settings.registerOnRemoveHandler()` event handler, which gets called when the user removes your connector. This event gives your service an opportunity to perform any cleanup actions.
+You can reuse your existing web configuration experience or create a separate version to be hosted specifically in Teams. Your code must include the Microsoft Teams JavaScript SDK. This gives your code access to APIs to perform common operations, such as getting the current user, channel, or team context and initiate authentication flows.
-Here's a sample HTML to create a Connector configuration page without the CSS:
+**To integrate the configuration experience**
+
+1. Initialize the SDK by calling `microsoftTeams.initialize()`.
+1. Call `microsoftTeams.settings.setValidityState(true)` to enable **Save**.
+
+ > [!NOTE]
+ > You must call `microsoftTeams.settings.setValidityState(true)` as a response to user selection or field update.
+
+1. Register `microsoftTeams.settings.registerOnSaveHandler()` event handler, which is called when the user selects **Save**.
+1. Call `microsoftTeams.settings.setSettings()` to save the connector settings. The saved settings are also shown in the configuration dialog if the user tries to update an existing configuration for your connector.
+1. Call `microsoftTeams.settings.getSettings()` to fetch webhook properties, including the URL.
+
+ > [!NOTE]
+ > You must call `microsoftTeams.settings.getSettings()` when your page is first loaded in case of reconfiguration.
+
+1. Register `microsoftTeams.settings.registerOnRemoveHandler()` event handler, which is called when the user removes connector.
+
+This event gives your service an opportunity to perform any cleanup actions.
+
+The following code provides a sample HTML to create a connector configuration page without the customer service and support:
```html <h2>Send notifications when tasks are:</h2>
Here's a sample HTML to create a Connector configuration page without the CSS:
</script> ```
-#### `GetSettings()` response properties
+To authenticate the user as part of loading your page, see [authentication flow for tabs](~/tabs/how-to/authentication/auth-flow-tab.md) to integrate sign in when your page is embedded.
+
+> [!NOTE]
+> Due to cross client compatibility reasons, your code must call `microsoftTeams.authentication.registerAuthenticationHandlers()` with the URL and success or failure callback methods before calling `authenticate()`.
+
+#### `GetSettings` response properties
+
+>[!NOTE]
+>The parameters returned by the `getSettings` call are different when you invoke this method from a tab and differ from those documented in [js settings](/javascript/api/%40microsoft/teams-js/settings.settings?view=msteams-client-js-latest&preserve-view=true).
->[!Note]
->The parameters returned by the `getSettings` call here are different than if you were to invoke this method from a tab, and differ from those documented [here](/javascript/api/@microsoft/teams-js/microsoftteams.settings.settings?view=msteams-client-js-latest&preserve-view=true).
+The following table provides the parameters and the details of `GetSetting` response properties:
-| Parameter | Details |
+| Parameters | Details |
|-|| | `entityId` | The entity ID, as set by your code when calling `setSettings()`. | | `configName` | The configuration name, as set by your code when calling `setSettings()`. | | `contentUrl` | The URL of the configuration page, as set by your code when calling `setSettings()`. |
-| `webhookUrl` | The webhook URL created for this connector. Persist the webhook URL and use it to POST structured JSON to send cards to the channel. The `webhookUrl` is returned only when application returns successfully. |
-| `appType` | The values returned can be `mail`, `groups` or `teams` corresponding to the Office 365 Mail, Office 365 Groups or Microsoft Teams respectively. |
-| `userObjectId` | This is the unique id corresponding to the Office 365 user who initiated setup of the connector. It should be secured. This value can be used to associate the user in Office 365 who set up the configuration to the user in your service. |
+| `webhookUrl` | The webhook URL created for the connector. Use the webhook URL to POST structured JSON to send cards to the channel. The `webhookUrl` is returned only when the application returns data successfully. |
+| `appType` | The values returned can be `mail`, `groups`, or `teams` corresponding to the Office 365 Mail, Office 365 Groups, or Microsoft Teams respectively. |
+| `userObjectId` | The unique ID corresponding to the Office 365 user who initiated the set up of the connector. It must be secured. This value can be used to associate the user in Office 365, who has set up the configuration in your service. |
-If you need to authenticate the user as part of loading your page in step 2 above, refer to [this link](~/tabs/how-to/authentication/auth-flow-tab.md) for details on how you can integrate login when your page is embedded.
+#### Handle edits
-> [!NOTE]
-> Due to cross-client compatibility reasons, your code will need to call `microsoftTeams.authentication.registerAuthenticationHandlers()` with the URL and success/failure callback methods before calling `authenticate()`.
+Your code must handle users who return to edit an existing connector configuration. To do this, call `microsoftTeams.settings.setSettings()` during the initial configuration with the following parameters:
-#### Handling edits
+- `entityId` is the custom ID that represents what the user has configured and understood by your service.
+- `configName` is a name that configuration code can retrieve.
+- `contentUrl` is a custom URL that gets loaded when a user edits an existing connector configuration.
-Your code should handle users returning to edit an existing connector configuration. To do this, call `microsoftTeams.settings.setSettings()` during the initial configuration with the following parameters:
+This call is made as part of your save event handler. Then, when the `contentUrl` is loaded, your code must call `getSettings()` to pre populate any settings or forms in your configuration user interface.
-- `entityId` is the custom ID that is understood by your service and represents what the user has configured.-- `configName` is a friendly name that your configuration code can retrieve-- `contentUrl` is a custom URL that gets loaded when a user edits an existing connector configuration. You can use this URL to make it easier for your code to handle the edit case.
+#### Handle removals
-Typically, this call is made as part of your save event handler. Then, when the `contentUrl` above is loaded, your code should call `getSettings()` to prepopulate any settings or forms in your configuration UI.
+You can execute an event handler when the user removes an existing connector configuration. You register this handler by calling `microsoftTeams.settings.registerOnRemoveHandler()`. This handler is used to perform cleanup operations, such as removing entries from a database.
-#### Handling removals
+### Include the connector in your Manifest
-You can optionally execute an event handler when the user removes an existing connector configuration. You register this handler by calling `microsoftTeams.settings.registerOnRemoveHandler()`. This handler can be used to perform cleanup operations such as removing entries from a database.
+Download the auto generated `Teams app manifest` from the portal. Perform the following steps, before testing or publishing the app:
-### Including the Connector in your Manifest
+1. [Include two icons](../../concepts/build-and-test/apps-package.md#app-icons).
+1. Modify the `icons` portion of the manifest to include the file names of the icons instead of URLs.
-You can download the auto-generated Teams app manifest from the portal. Before you can use it to test or publish your app, though, you must do the following:
--- [Include two icons](../../concepts/build-and-test/apps-package.md#app-icons).-- Modify the `icons` portion of the manifest to refer to the file names of the icons instead of URLs.-
-The following manifest.json file contains the basic elements needed to test and submit your app.
+The following manifest.json file contains the elements needed to test and submit the app:
> [!NOTE]
-> Replace `id` and `connectorId` in the following example with the GUID of your Connector.
+> Replace `id` and `connectorId` in the following example with the GUID of the connector.
-#### Example manifest.json with Connector
+#### Example of manifest.json with connector
```json {
The following manifest.json file contains the basic elements needed to test and
"termsOfUseUrl": "https://www.microsoft.com" }, "description": {
- "full": "This is a sample manifest for an app with a connector with an inline configuration experience.",
- "short": "This is a sample manifest for an app with a connector."
+ "full": "This is a small sample app we made for you! This app has samples of all capabilities Microsoft Teams supports.",
+ "short": "This is a small sample app we made for you!"
}, "icons": { "outline": "sampleapp-outline.png",
The following manifest.json file contains the basic elements needed to test and
"connectors": [ { "connectorId": "e9343a03-0a5e-4c1f-95a8-263a565505a5",
- "configurationUrl": "https://teamstodoappconnectorwithinlineconfig.azurewebsites.net/Connector/Setup",
"scopes": [ "team" ]
The following manifest.json file contains the basic elements needed to test and
], "name": { "short": "Sample App",
- "full": "Sample App Long Name"
+ "full": "Sample App"
},
- "accentColor": "#FFFFFF"
+ "accentColor": "#FFFFFF",
+ "needsIdentity": "true"
} ```
-## Disable or enable connectors in Teams
+## Enable or disable connectors in Teams
-The Exchange Online PowerShell V2 module uses modern authentication and works with multi-factor authentication (MFA) for connecting to all Exchange-related PowerShell environments in Microsoft 365. Admins can use Exchange Online PowerShell to disable connectors for an entire tenant or a specific group mailbox, affecting all users in that tenant or mailbox. It is not possible to disable for some and not others. Also, connectors are disabled by default for GCC tenants.
+The Exchange Online PowerShell V2 module uses modern authentication and works with multi factor authentication, called MFA for connecting to all Exchange related PowerShell environments in Microsoft 365. Admins can use Exchange Online PowerShell to disable connectors for an entire tenant or a specific group mailbox, affecting all users in that tenant or mailbox. It is not possible to disable for some and not others. Also, connectors are disabled by default for Government Community Cloud, called GCC tenants.
-The tenant-level setting overrides the group-level setting. For example, if an admin enables connectors for the group and disables them on the tenant, connectors for the group will be disabled. To enable a connector in Teams, [connect to Exchange Online PowerShell](/powershell/exchange/connect-to-exchange-online-powershell?view=exchange-ps#connect-to-exchange-online-powershell-using-modern-authentication-with-or-without-mfa&preserve-view=true) using modern authentication with or without MFA.
+The tenant level setting overrides the group level setting. For example, if an admin enables connectors for the group and disables them on the tenant, connectors for the group is disabled. To enable a connector in Teams, [connect to Exchange Online PowerShell](/powershell/exchange/connect-to-exchange-online-powershell?view=exchange-ps#connect-to-exchange-online-powershell-using-modern-authentication-with-or-without-mfa&preserve-view=true) using modern authentication with or without MFA.
-### Commands to disable or enable connectors
+### Commands to enable or disable connectors
-**Run the command in Exchange Online PowerShell**
+Run the following commands in Exchange Online PowerShell:
* To disable connectors for the tenant: `Set-OrganizationConfig -ConnectorsEnabled:$false`. * To disable actionable messages for the tenant: `Set-OrganizationConfig -ConnectorsActionableMessagesEnabled:$false`. * To enable connectors for Teams, run the following commands:
- * `Set-OrganizationConfig -ConnectorsEnabled:$true `
- * `Set-OrganizationConfig -ConnectorsEnabledForTeams:$true`
- * `Set-OrganizationConfig -ConnectorsActionableMessagesEnabled:$true`
+ * `Set-OrganizationConfig -ConnectorsEnabled:$true `
+ * `Set-OrganizationConfig -ConnectorsEnabledForTeams:$true`
+ * `Set-OrganizationConfig -ConnectorsActionableMessagesEnabled:$true`
For more information on PowerShell module exchange, see [Set-OrganizationConfig](/powershell/module/exchange/Set-OrganizationConfig?view=exchange-ps&preserve-view=true). To enable or disable Outlook connectors, [connect apps to your groups in Outlook](https://support.microsoft.com/topic/connect-apps-to-your-groups-in-outlook-ed0ce547-038f-4902-b9b3-9e518ae6fbab?ui=en-us&rs=en-us&ad=us).
-## Testing your Connector
+## Test your connector
+
+To test your connector, upload it to a team with any other app. You can create a .zip package using the manifest file from the two icon files and connectors Developer Dashboard, modified as directed in [Include the connector in your Manifest](#include-the-connector-in-your-manifest).
-To test your Connector, upload it to a team as you would with any other app. You can create a .zip package using the manifest file from the Connectors Developer Dashboard (modified as directed in the preceding section) and the two icon files.
+After you upload the app, open the connectors list from any channel. Scroll to the bottom to see your app in the **Uploaded** section:
+
+![Screenshot of an uploaded section in connector dialog box](~/assets/images/connectors/connector_dialog_uploaded.png)
+
+> [!NOTE]
+> The flow occurs entirely within Microsoft Teams as a hosted experience.
-After you upload the app, open the Connectors list from any channel. Scroll to the bottom to see your app in the **Uploaded** section.
+To verify that `HttpPOST` action is working correctly, [send messages to your connector](~/webhooks-and-connectors/how-to/connectors-using.md).
-![Screenshot of uploaded section in Connector dialog box](~/assets/images/connectors/connector_dialog_uploaded.png)
+## Publish connectors for the organization
-You can now launch the configuration experience. Be aware that this flow occurs entirely within Microsoft Teams as a hosted experience.
+If you want the connector to be available only to the users in your organization, you can upload your custom connector app to your [organization's app catalog](~/concepts/deploy-and-publish/apps-publish.md).
-To verify that an `HttpPOST` action is working correctly, [send messages to your connector](~/webhooks-and-connectors/how-to/connectors-using.md).
+After uploading the app package to configure and use the connector in a team, install the connector from the organization's app catalog.
-## Publish Connectors for your organization
+**To set up a connector**
-Sometimes, you may not want to publish your connector app to the public AppSource/Store but would like it to be available only to the users in your organization. In such cases, you can upload your custom connector app to your [organization's App Catalog](~/concepts/deploy-and-publish/apps-publish.md). This way, your connector app will be available only to that organization, and you will not need to publish your connector to the public store.
+1. Select **Apps** from the left navigation bar.
+1. In the **Apps** section, select **Connectors**.
+1. Select the connector that you want to add. A pop up dialog window appears.
+1. From the dropdown menu, select **Add to a team**.
+1. In the search box, type a team or channel name.
+1. Select **Set up a Connector** from the dropdown menu in the bottom right corner of the dialog window.
-Once you've uploaded your app package, to configure and use the connector in a Team it can be installed from the organization's app catalog by following these steps:
+The connector is available in the section &#9679;&#9679;&#9679; > **More options** > **Connectors** > **All** > **Connectors for your team** for that team. You can navigate by scrolling to this section or search for the connector app. To configure or modify the connector, select **Configure**.
-1. Select the apps icon from the far left vertical navigation bar.
-1. In the **Apps** window select **Connectors**.
-1. Select the connector that you want to add and a pop-up dialog window will display.
-1. Select the **Add to a team** bar.
-1. In the next dialog window type a team or channel name.
-1. Select the **Set up a connector** bar from the bottom right corner of dialog window.
-1. The connector will be available in the section &#9679;&#9679;&#9679; => *More options* => *Connectors* => *All* => *Connectors for you team* for that team. You can navigate by scrolling to this section or search for the connector app.
-1. To configure or modify the connector select the **Configure** bar.
+## Distribute webhook and connector
+
+1. [Set up an Incoming Webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md?branch=pr-en-us-3076#create-incoming-webhook) directly for your team.
+1. Add a [configuration page](~/webhooks-and-connectors/how-to/connectors-creating.md?branch=pr-en-us-3076#integrate-the-configuration-experience) and [publish your Incoming Webhook](~/webhooks-and-connectors/how-to/connectors-creating.md?branch=pr-en-us-3076#publish-connectors-for-the-organization) in a O365 Connector.
+1. Package and publish your connector as part of your [AppSource](~/concepts/deploy-and-publish/office-store-guidance.md) submission.
## Code sample+
+The following table provides the sample name and its description:
+ |**Sample name** | **Description** | **.NET** | **Node.js** | |-||--|-|
-| Connectors | Sample Office 365 Connector generating notifications to teams channel.| [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-todo-notification/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-github-notification/nodejs)|
-| Generic connectors sample |Sample code for a generic connector that's easy to customize for any system which supports webhooks.| | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-generic/nodejs)|
+| Connectors | Sample Office 365 Connector generating notifications to Teams channel.| [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-todo-notification/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-github-notification/nodejs)|
+| Generic connectors sample |Sample code for a generic connector that is easy to customize for any system that supports webhooks.| | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/connector-generic/nodejs)|
+
+## See also
+
+* [Create and send messages](~/webhooks-and-connectors/how-to/connectors-using.md)
+* [Create an Incoming Webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md)
+* [Create an Office 365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md)
platform Connectors Using https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/webhooks-and-connectors/how-to/connectors-using.md
Title: Sending messages to Connectors and Webhooks
+ Title: Create and send messages
+ description: Describes how to use Office 365 Connectors in Microsoft Teams localization_priority: Normal keywords: teams o365 connector
-# Sending messages to connectors and webhooks
+# Create and send messages
-To send a message through your Office 365 Connector or incoming webhook, you post a JSON payload to the webhook URL. Typically this payload will be in the form of an [Office 365 Connector Card](~/task-modules-and-cards/cards/cards-reference.md#office-365-connector-card).
+You can create actionable messages and send it through Incoming Webhook or Office 365 Connector.
-You can also use this JSON to create cards containing rich inputs, such as text entry, multi-select, or picking a date and time. The code that generates the card and posts to the webhook URL can be running on any hosted service. These cards are defined as part of actionable messages, and are also supported in [cards](~/task-modules-and-cards/what-are-cards.md) used in Teams bots and Messaging extensions.
+## Create actionable messages
-### Example connector message
+The actionable messages include three visible buttons on the card. Each button is defined in the `potentialAction` property of the message by using `ActionCard` actions, each with an input type, a text field, a date picker, or a multi-choice list. Each `ActionCard` has an associated action, for example `HttpPOST`.
+
+The connector cards support the following actions:
+
+- `ActionCard`: Presents one or more input types and associated actions.
+- `HttpPOST`: Sends POST request to a URL.
+- `OpenUri`: Opens URI in a separate browser or app, optionally targets different URIs based on operating systems.
+
+The `ActionCard` action supports three input types:
+
+- `TextInput`: A single line or multiline text field with an optional length limit.
+- `DateInput`: A date selector with an optional time selector.
+- `MultichoiceInput`: An enumerated list of choices offering either a single selection or multiple selections.
+
+`MultichoiceInput` supports a `style` property that controls whether the list initially appears fully expanded. The default value of `style` depends on the value of `isMultiSelect` as follows:
+
+| `isMultiSelect` | `style` default |
+| | |
+| `false` or not specified | `compact` |
+| `true` | `expanded` |
+
+To display the multiselect list in the compact style, you must specify both `"isMultiSelect": true` and `"style": true`.
+
+For more information on connector card actions, see [Actions](/outlook/actionable-messages/card-reference#actions).
+
+> [!NOTE]
+> * Specifying `compact` for the `style` property in Microsoft Teams is the same as specifying `normal` for the `style` property in Microsoft Outlook.
+> * For the HttpPOST action, the bearer token is included with the requests. This token includes the Azure AD identity of the Office 365 user who took the action.
+
+## Send a message through Incoming Webhook or Office 365 Connector
+
+To send a message through your Incoming Webhook or Office 365 Connector, post a JSON payload to the webhook URL. This payload must be in the form of an [Office 365 connector card](~/task-modules-and-cards/cards/cards-reference.md#office-365-connector-card).
+
+You can also use this JSON to create cards containing rich inputs, such as text entry, multiselect, or selecting date and time. The code that generates the card and posts it to the webhook URL can run on any hosted service. These cards are defined as part of actionable messages and are also supported in [cards](~/task-modules-and-cards/what-are-cards.md), used in Teams bots and messaging extensions.
+
+### Example of connector message
+
+An example of connector message is as follows:
```json {
You can also use this JSON to create cards containing rich inputs, such as text
} ```
-This message produces the following card in the channel:
-
-![Screenshot of a Connector card](~/assets/images/connectors/connector_message.png)
+This message provides the following card in the channel:
-## Creating actionable messages
+![Screenshot of a connector card](~/assets/images/connectorcard.png)
-The example in the preceding section includes three visible buttons on the card. Each button is defined in the `potentialAction` property of the message by using `ActionCard` actions, each containing an input type: a text field, a date picker, or a multi-choice list. Each `ActionCard` action has an associated action, for example `HttpPOST`.
+## Send messages using cURL and PowerShell
-Connector cards support three types of actions:
+# [cURL](#tab/cURL)
-- `ActionCard` Presents one or more input types and associated actions-- `HttpPOST` Sends a POST request to a URL-- `OpenUri` Opens a URI in a separate browser or app; optionally targets different URIs based on operating systems-
-The `ActionCard` action supports three input types:
--- `TextInput` A single-line or multiline text field with an optional length limit-- `DateInput` A date selector with an optional time selector-- `MultichoiceInput` A enumerated list of choices offering either a single selection or multiple selections-
-`MultichoiceInput` supports a `style` property that controls whether the list initially appears fully expanded. The default value of `style` depends on the value of `isMultiSelect`.
-
-| `isMultiSelect` | `style` default |
-| | |
-| `false` or not specified | `compact` |
-| `true` | `expanded` |
+**To post a message in the webhook with cURL**
-If you want a multiselect list initially displayed in the compact style, you must specify both `"isMultiSelect": true` and `"style": true`.
-
-For more information on Connector card actions, see **[Actions]**(/outlook/actionable-messages/card-reference#actions) in the actionable message card reference.
-
-> [!NOTE]
-> Specifying `compact` for the `style` property in Microsoft Teams is the same as specifying `normal` for the `style` property in Microsoft Outlook.
->
-> For the HttpPOST action, the bearer token is included with the requests. This token includes the Azure AD identity of the Office 365 user who took the action.
-
-## Setting up a custom incoming webhook
-
-Follow these steps to see how to send a simple card to a Connector:
-
-1. In Microsoft Teams, choose **More options** (**&#8943;**) next to the channel name and then choose **Connectors**.
-1. Scroll through the list of Connectors to **Incoming Webhook**, and choose **Add**.
-1. Enter a name for the webhook, upload an image to associate with data from the webhook, and choose **Create**.
-1. Copy the webhook to the clipboard and save it. You'll need the webhook URL for sending information to Microsoft Teams.
-1. Choose **Done**.
-
-### Post a message to the webhook using cURL
-
-The following steps use [cURL](https://curl.haxx.se/). We assume that you have this installed and are familiar with its basic usage.
+1. Install cURL using: https://curl.haxx.se/.
1. From the command line, enter the following cURL command:
The following steps use [cURL](https://curl.haxx.se/). We assume that you have t
curl.exe -H "Content-Type:application/json" -d "{'text':'Hello World'}" <YOUR WEBHOOK URL> ```
-1. If the POST succeeds, you should see a simple **1** output by `curl`.
-1. Check the Microsoft Team client. You should see the new card posted to the team.
+ > [!NOTE]
+ > If the POST succeeds, you must see a simple **1** output by `curl`.
-### Post a message to the webhook using PowerShell
+1. Check the Microsoft Teams client for the new card posted.
-The following steps use PowerShell. We assume that you have this installed and are familiar with its basic usage.
+# [PowerShell](#tab/PowerShell)
+
+ Prerequisite: Installation of PowerShell and familiarization with its basic usage.
+
+**To post a message to the webhook with PowerShell**
1. From the PowerShell prompt, enter the following command:
The following steps use PowerShell. We assume that you have this installed and a
Invoke-RestMethod -Method post -ContentType 'Application/Json' -Body '{"text":"Hello World!"}' -Uri <YOUR WEBHOOK URL> ```
-1. If the POST succeeds, you should see a simple **1** output by `Invoke-RestMethod`.
-1. Check the Microsoft Teams channel associated with the webhook URL. You should see the new card posted to the channel.
+ > [!NOTE]
+ > If the POST succeeds, you must see a simple **1** output by `Invoke-RestMethod`.
-- [Include two icons](../../concepts/build-and-test/apps-package.md#app-icons).-- Modify the `icons` portion of the manifest to refer to the file names of the icons instead of URLs.
+1. Check the Microsoft Teams channel associated with the webhook URL. You can see the new card posted to the channel. Before you use the connector to test or publish your app, you must do the following:
-The following manifest.json file contains the basic elements needed to test and submit your app:
-
-> [!NOTE]
-> Replace `id` and `connectorId` in the following example with the GUID of your Connector.
+ - [Include two icons](../../concepts/build-and-test/apps-package.md#app-icons).
+ - Modify the `icons` portion of the manifest to the file names of the icons instead of URLs.
-#### Example manifest.json with connector
-
-```json
-{
- "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.8/MicrosoftTeams.schema.json",
- "manifestVersion": "1.5",
- "id": "e9343a03-0a5e-4c1f-95a8-263a565505a5",
- "version": "1.0",
- "packageName": "com.sampleapp",
- "developer": {
- "name": "Publisher",
- "websiteUrl": "https://www.microsoft.com",
- "privacyUrl": "https://www.microsoft.com",
- "termsOfUseUrl": "https://www.microsoft.com"
- },
- "description": {
- "full": "This is a small sample app we made for you! This app has samples of all capabilities Microsoft Teams supports.",
- "short": "This is a small sample app we made for you!"
- },
- "icons": {
- "outline": "sampleapp-outline.png",
- "color": "sampleapp-color.png"
- },
- "connectors": [
- {
- "connectorId": "e9343a03-0a5e-4c1f-95a8-263a565505a5",
- "scopes": [
- "team"
- ]
- }
- ],
- "name": {
- "short": "Sample App",
- "full": "Sample App"
- },
- "accentColor": "#FFFFFF",
- "needsIdentity": "true"
-}
-```
+
-## Send adaptive cards using an incoming webhook
+## Send Adaptive Cards using an Incoming Webhook
> [!NOTE]
->
-> Γ£ö All native adaptive card schema elements, except `Action.Submit`, are fully supported.
->
-> Γ£ö The supported Actions are [**Action.OpenURL**](https://adaptivecards.io/explorer/Action.OpenUrl.html), [**Action.ShowCard**](https://adaptivecards.io/explorer/Action.ShowCard.html), and [**Action.ToggleVisibility**](https://adaptivecards.io/explorer/Action.ToggleVisibility.html).
+> * All native Adaptive Card schema elements, except `Action.Submit`, are fully supported.
+> * The supported actions are [**Action.OpenURL**](https://adaptivecards.io/explorer/Action.OpenUrl.html), [**Action.ShowCard**](https://adaptivecards.io/explorer/Action.ShowCard.html), and [**Action.ToggleVisibility**](https://adaptivecards.io/explorer/Action.ToggleVisibility.html).
-### The flow for sending [adaptive cards](../../task-modules-and-cards/cards/cards-reference.md#adaptive-card) via an incoming webhook is as follows:
+**To send Adaptive Cards through an Incoming Webhook**
-1. [Setup a custom webhook](#setting-up-a-custom-incoming-webhook) in Teams.
-1. Create your adaptive card JSON file:
+1. [Setup a custom webhook](/add-incoming-webhook.md) in Teams.
+1. Create Adaptive Card JSON file using the following code:
```json {
The following manifest.json file contains the basic elements needed to test and
} ```
- > [!div class="checklist"]
- >
- > - The `"type"` field must be `"message"`.
- > - The `"attachments"` array contains a set of card objects.
- > - The `"contentType"` field must be set to adaptive card type.
- > - The `"content"` object is the card formatted in JSON.
-
-1. Test your adaptive card with Postman.
-
-You can test your adaptive card using [Postman](https://www.postman.com) to send a POST request to the URL that you created when you setup your incoming webhook. Paste your JSON file in the body of the request and view your adaptive card message in Teams.
+ The properties for Adaptive Card JSON file are as follows:
->[!TIP]
-> You can use adaptive card code [Samples and Templates](https://adaptivecards.io/samples) for the body of your test Post request.
+ * The `"type"` field must be `"message"`.
+ * The `"attachments"` array contains a set of card objects.
+ * The `"contentType"` field must be set to Adaptive Card type.
+ * The `"content"` object is the card formatted in JSON.
-## Testing your connector
+1. Test your Adaptive Card with Postman:
-To test your Connector, upload it to a team as you would with any other app. You can create a .zip package using the manifest file from the Connectors Developer Dashboard which was modified as directed in the preceding section and the two icon files.
+ * Test the Adaptive Card using [Postman](https://www.postman.com) to send a POST request to the URL, created to set up Incoming Webhook.
+ * Paste the JSON file in the body of the request and view the Adaptive Card message in Teams.
-After you upload the app, open the Connectors list from any channel. Scroll to the bottom to see your app in the **Uploaded** section:
-
-![Screenshot of uploaded section in Connector dialog box](~/assets/images/connectors/connector_dialog_uploaded.png)
-
-You can now launch the configuration experience. Be aware that this flow occurs entirely within Microsoft Teams through a pop-up window. Currently, this behavior differs from the configuration experience in Connectors that we created; we are working on unifying the experiences.
-
-To verify that an `HttpPOST` action is working correctly, use your [custom incoming webhook](#setting-up-a-custom-incoming-webhook).
+> [!TIP]
+> Use Adaptive Card [code samples and templates](https://adaptivecards.io/samples) to test the body of POST request.
## Rate limiting for connectors
-Application rate limits control the traffic that a connector or an incoming webhook is allowed to generate on a channel. Teams tracks requests via a fixed-rate window and incremental counter measured in seconds. If too many requests are made, the client connection will be throttled until the window refreshes, i.e., for the duration of the fixed rate.
+Application rate limits control the traffic that a connector or an Incoming Webhook is permitted to generate on a channel. Teams track requests using a fixed rate window and incremental counter measured in seconds. If more than four requests are made in a second, the client connection is throttled until the window refreshes for the duration of the fixed rate.
+
+### Transactions per second thresholds
-### **Transactions per second thresholds**
+The following table provides the time based transaction details:
-| Time (seconds) | Maximum allowed requests |
+| Time in seconds | Maximum allowed requests |
||| | 1 | 4 | | 30 | 60 |
Application rate limits control the traffic that a connector or an incoming webh
| 7200 | 150 | | 86400 | 1800 |
-A [retry logic with exponential back-off](/azure/architecture/patterns/retry) like below would mitigate rate limiting for cases where requests are exceeding the limits within a second. Refer [HTTP 429 responses](../../bots/how-to/rate-limit.md#handle-http-429-responses) to avoid hitting the rate limits.
+A [retry logic with exponential back-off](/azure/architecture/patterns/retry) can mitigate rate limiting for cases where requests are exceeding the limits within a second. Follow [best practices](../../bots/how-to/rate-limit.md) to avoid hitting the rate limits.
+
+> [!NOTE]
+> A [retry logic with exponential back-off](/azure/architecture/patterns/retry) can mitigate rate limiting for cases where requests are exceeding the limits within a second. Refer [HTTP 429 responses](../../bots/how-to/rate-limit.md#handle-http-429-responses) to avoid hitting the rate limits.
```csharp // Please note that response body needs to be extracted and read
try
} } ```
-
-These limits are in place to reduce spamming a channel by a connector and ensures an optimal experience to your end users.
+
+These limits are in place to reduce spamming a channel by a connector and ensures an optimal experience to users.
## See also
-[Office 365 Connectors ΓÇö Microsoft Teams](/connectors/teams/)
+* [Office 365 Connectors for Microsoft Teams](~/webhooks-and-connectors/how-to/connectors-creating.md)
+* [Create an Incoming Webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md)
+* [Create an Outgoing Webhook](~/webhooks-and-connectors/how-to/add-outgoing-webhook.md)
platform What Are Webhooks And Connectors https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/webhooks-and-connectors/what-are-webhooks-and-connectors.md
Title: What are webhooks and connectors?-
+ Title: Webhooks and connectors
+ description: Understand how webhooks and connectors can connect your web services to the Teams client. localization_priority: Normal
-# What are webhooks and connectors?
-Webhooks and connectors are a simple way to connect your web services to channels and teams inside Microsoft Teams.
+# Webhooks and connectors
-## Outgoing webhooks
+Webhooks and connectors help to connect the web services to channels and teams in Microsoft Teams. Webhooks are user defined HTTP callback that notifies users about any action that has taken place in the Microsoft Teams channel. It is a way for an app to get real time data. Connectors allow users to subscribe to receive notifications and messages from your web services. They expose an HTTPS endpoint for your service to post messages in the form of cards.
-Outgoing webhooks allow your users to send text messages from a channel to your web services. Once configured, your users will be able to @mention your outgoing webhook and send a message to your service. Your service will have five seconds to send a response to the message, potentially containing text or a card.
+## Outgoing Webhooks
-Outgoing webhooks are configured on a per-team basis, cannot be included as part of a normal Teams app. They are best suited for completing team-specific workloads that don't require large amounts of information to be collected or exchanged.
+Webhooks help Teams to integrate with external apps. With Outgoing Webhooks, you can send text messages from a channel to the web services. After configuring the Outgoing Webhooks, users can @mention Outgoing Webhook and send a message to web services. The service responds within ten seconds to the message with a text or a card.
-For more information, see [Create an outgoing webhook](~/webhooks-and-connectors/how-to/add-outgoing-webhook.md).
+> [!NOTE]
+> Outgoing Webhooks are configured on a per team basis and cannot be included as part of a normal Teams app.
## Connectors
-Connectors allow users to subscribe to receive notifications and messages from your web services. They expose an HTTPS endpoint for your service to post messages to - typically in the form of cards.
+Connectors allow users to subscribe to receive notifications and messages from the web services. They expose the HTTPS endpoint for the service to post messages to Teams channels, typically in the form of cards.
-### Incoming webhooks
+### Incoming Webhooks
-Incoming webhooks are the simplest type of connector. For any channel in team (if they are enabled for that team) you can choose to expose an HTTPS endpoint that will accept correctly formatted JSON and insert messages into that channel. They are a quick and easy way to connect a channel to your service, and are best used for scenarios that are unique to a particular team. For example, you could create an incoming webhook in your DevOps channel and configure your build, deployment and monitoring services to send alerts.
-
-For more information, see [Create an incoming webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md).
+Incoming Webhooks help in posting messages from apps to Teams. If Incoming Webhooks are enabled for a team in any channel, it exposes the HTTPS endpoint, which accepts correctly formatted JSON and inserts the messages into that channel. For example, you can create an Incoming Webhook in your DevOps channel, configure your build, and simultaneously deploy and monitor services to send alerts.
### Office 365 Connectors
-Office 365 Connectors allow you to create a custom configuration page for your incoming webhook, and package them as part of a Teams app. You can then distribute that app more broadly, or even to our app store. You send messages primarily using Office 365 Connector cards, and have the ability to add a limited set of card actions to them as well. A good example of this is a weather connector that allows users to choose a location and time of day to receive updates about tomorrow's weather. They are configured on a channel level, but are installed at a team level.
+Office 365 Connectors allow you to create a custom configuration page for your Incoming Webhook and package them as part of a Teams app. You send messages primarily using Office 365 Connector cards and have the ability to add a limited set of card actions to them. For example, a weather connector that allows users to select a location and time of day, to receive updates about tomorrow's weather. They are configured on a channel level but are installed at a team level.
+
+> [!NOTE]
+> You can distribute the Office 365 Connector Teams app to our AppStore.
+
+## Create and send messages
+
+Actionable messages allow users to take action without leaving their email client, increasing user engagement. With Office 365 and Incoming Webhooks, you can send messages by posting a JSON payload to the webhook URL.
+
+## See also
+
+* [Create an Incoming Webhook](~/webhooks-and-connectors/how-to/add-incoming-webhook.md)
+* [Create an Office 365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md)
+* [Create and send messages](~/webhooks-and-connectors/how-to/connectors-using.md)
+
+## Next step
-For more information, see [Create an Office 365 Connector](~/webhooks-and-connectors/how-to/connectors-creating.md).
+> [!div class="nextstepaction"]
+> [Create an Outgoing Webhook](~/webhooks-and-connectors/how-to/add-outgoing-webhook.md)
platform Whats New https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/whats-new.md
Microsoft Teams platform features that are available to all app developers.
| **Date** | **Notes** | **Changed topics** | | -- | | |
+|06/25/2021| Introduced step-by-step guide to send proactive messages. | [Step-by-step guide to send proactive messages](sbs-send-proactive.yml) |
|06/09/2021| Stage view for images in Adaptive Cards with `allowExpand` attribute. | [Stage view for images in Adaptive Cards](~/task-modules-and-cards/cards/cards-format.md) | |05/31/2021| Conversational tabs. | [Start and continue conversations about content in your tabs](~/tabs/how-to/conversational-tabs.md) | |05/24/2021| Updated Teams app design guidelines with mobile patterns and more.|[Designing your Teams app](~/concepts/design/design-teams-app-overview.md)
Microsoft Teams platform features that are available to all app developers.
|03/18/2021|Notice: Update to version 4.10 or above of the Bot Framework SDK, as we've started with the deprecation process for `TeamsInfo.getMembers` and `TeamsInfo.GetMembersAsync`. | [Bot API Changes for Team/Chat Members](resources/team-chat-member-api-changes.md) | |03/05/2021|Notice: Tabs will no longer have margins surrounding their experiences. Tab developers should review and update their apps. | [Removing tab margins](resources/removing-tab-margins.md) | |03/05/2021|Default install scope and group capability.| [Default install scope and group capability](concepts/deploy-and-publish/add-default-install-scope.md) |
-|03/05/2021|Reorder personal app tabs.|[Reorder the chat tab in personal apps](tabs/how-to/create-tab-pages/content-page.md#reorder-static-personal-tabs)|
-|03/04/2021|Information masking in Adaptive Cards.| [Information masking in Adaptive Cards](task-modules-and-cards/cards/cards-format.md#information-masking-in-adaptive-cards) |
+|03/05/2021|Reorder personal app tabs.|[Reorder the chat tab in personal apps](tabs/how-to/create-personal-tab.md#reorder-static-personal-tabs)|
+|03/04/2021|Information masking in Adaptive cards.| [Information masking in Adaptive cards](task-modules-and-cards/cards/cards-format.md#information-masking-in-adaptive-cards) |
|02/19/2021|Added location capabilities. <br/> Location capabilities information is added in the device capabilities overview, native device permissions, integrate media capabilities, and QR or barcode scanner capability files.|[Overview](concepts/device-capabilities/device-capabilities-overview.md), [Request device permissions](concepts/device-capabilities/native-device-permissions.md), [Integrate media capabilities](concepts/device-capabilities/mobile-camera-image-permissions.md), [Integrate QR or barcode scanner capability](concepts/device-capabilities/qr-barcode-scanner-capability.md), [Integrate location capabilities](concepts/device-capabilities/location-capability.md) | |02/18/2021|Added QR or barcode scanner capability. <br/> QR or barcode scanner capability information is added in the device capabilities overview, native device permissions, and integrate media capabilities files.|[Overview](concepts/device-capabilities/device-capabilities-overview.md), [Request device permissions](concepts/device-capabilities/native-device-permissions.md), [Integrate media capabilities](concepts/device-capabilities/mobile-camera-image-permissions.md), [Integrate QR or barcode scanner capability](concepts/device-capabilities/qr-barcode-scanner-capability.md) | |02/09/2021|Added device capabilities overview. <br/> Microphone capability information is added in the native device permissions and integrate media capabilities files.|[Overview](concepts/device-capabilities/device-capabilities-overview.md), [Request device permissions](concepts/device-capabilities/native-device-permissions.md), [Integrate media capabilities](concepts/device-capabilities/mobile-camera-image-permissions.md)|
Microsoft Teams platform features that are available to all app developers.
| 10/31/2019 | Conversational bots and messaging extension documentation updated to reflect the 4.6 Bot Framework SDK. Documentation for the v3 SDK is available in the Resources section. | All bot and messaging extension documentation. | | 10/31/2019 | New documentation structure, and major article refactoring. Please report any dead links or 404's by creating a GitHub Issue. | All of them! | | 09/13/2019 | Request bot is installed from action-based messaging extension. | [Initiate actions with messaging extensions](resources/messaging-extension-v3/create-extensions.md#request-to-install-your-conversational-bot)
-| 08/28/2019 | Support for private channels in tabs and Connectors. | [Get context for your tab](tabs/how-to/access-teams-context.md#retrieving-context-in-private-channels) |
+| 08/28/2019 | Support for private channels in tabs and Connectors. | [Get context for your tab](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) |
| 06/20/2019 | Share an external website, from an external website, into a Teams channel. | [Share to Teams](~/share-to-teams.md) | | 05/25/2019 | Respond with bot message from task module. | [Respond with bot message from task module](resources/messaging-extension-v3/create-extensions.md#respond-with-an-adaptive-card-message-sent-from-a-bot) | | 05/25/2019 | Bots in group chats. | [Interact with a bot in group chat or channel](~/concepts/bots/bot-conversations/bots-conv-channel.md) |