diff --git a/docs/assets/MultiplyDialog.cs b/docs/assets/MultiplyDialog.cs
new file mode 100644
index 0000000000..3b3b46177c
--- /dev/null
+++ b/docs/assets/MultiplyDialog.cs
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using AdaptiveExpressions.Properties;
+using Microsoft.Bot.Builder.Dialogs;
+using Newtonsoft.Json;
+
+namespace CustomAction.MultiplyDialog
+{
+ ///
+ /// Custom command which takes takes 2 data bound arguments (arg1 and arg2) and multiplies them returning that as a databound result.
+ ///
+ public class MultiplyDialog : Dialog
+ {
+ [JsonConstructor]
+ public MultiplyDialog([CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
+ : base()
+ {
+ // enable instances of this command as debug break point
+ this.RegisterSourceLocation(sourceFilePath, sourceLineNumber);
+ }
+
+ ///
+ /// Gets the unique name of this Adaptive Dialog.
+ ///
+ [JsonProperty("$kind")]
+ public const string Kind = "MultiplyDialog";
+
+ ///
+ /// Gets or sets memory path to bind to arg1 (ex: action.arg1).
+ ///
+ ///
+ /// Memory path to bind to arg1 (ex: action.arg1).
+ ///
+ [JsonProperty("arg1")]
+ public NumberExpression Arg1 { get; set; }
+
+ ///
+ /// Gets or sets memory path to bind to arg2 (ex: action.arg2).
+ ///
+ ///
+ /// Memory path to bind to arg2 (ex: action.arg2).
+ ///
+ [JsonProperty("arg2")]
+ public NumberExpression Arg2 { get; set; }
+
+ ///
+ /// Gets or sets caller's memory path to store the result of this step in (ex: dialog.result).
+ ///
+ ///
+ /// Caller's memory path to store the result of this step in (ex: dialog.result).
+ ///
+ ///
+ /// This is where the result of the Dialog is stored and accessible in Composer.
+ ///
+ [JsonProperty("resultProperty")]
+ public StringExpression ResultProperty { get; set; }
+
+ ///
+ /// Override BeginDialogAsync to provide the custom action functionality. The inputs, in this case,
+ /// are define in Arg1 and Arg2. The result of the the dialog is stored in ResultProperty.
+ ///
+ public override Task BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var arg1 = Arg1.GetValue(dc.State);
+ var arg2 = Arg2.GetValue(dc.State);
+
+ var result = Convert.ToInt32(arg1) * Convert.ToInt32(arg2);
+ if (this.ResultProperty != null)
+ {
+ dc.State.SetValue(this.ResultProperty.GetValue(dc.State), result);
+ }
+
+ return dc.EndDialogAsync(result: result, cancellationToken: cancellationToken);
+ }
+ }
+}
diff --git a/docs/assets/MultiplyDialog.csproj b/docs/assets/MultiplyDialog.csproj
new file mode 100644
index 0000000000..d59836c631
--- /dev/null
+++ b/docs/assets/MultiplyDialog.csproj
@@ -0,0 +1,27 @@
+
+
+
+ Library
+ netcoreapp3.1
+ CustomAction.MultiplyDialog
+ This library implements .NET support for the MultiplyDialog custom action sample BotComponent.
+ This library implements .NET support for the MultiplyDialog custom action sample BotComponent.
+ content
+
+ msbot-component;msbot-action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/assets/MultiplyDialog.schema b/docs/assets/MultiplyDialog.schema
new file mode 100644
index 0000000000..f2928a25aa
--- /dev/null
+++ b/docs/assets/MultiplyDialog.schema
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
+ "$role": "implements(Microsoft.IDialog)",
+ "title": "Multiply",
+ "description": "This will return the result of arg1*arg2",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "arg1": {
+ "$ref": "schema:#/definitions/integerExpression",
+ "title": "Arg1",
+ "description": "Value from callers memory to use as arg 1"
+ },
+ "arg2": {
+ "$ref": "schema:#/definitions/integerExpression",
+ "title": "Arg2",
+ "description": "Value from callers memory to use as arg 2"
+ },
+ "resultProperty": {
+ "$ref": "schema:#/definitions/stringExpression",
+ "title": "Result",
+ "description": "Value from callers memory to store the result"
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/assets/MultiplyDialogBotComponent.cs b/docs/assets/MultiplyDialogBotComponent.cs
new file mode 100644
index 0000000000..2d5903e7dd
--- /dev/null
+++ b/docs/assets/MultiplyDialogBotComponent.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Bot.Builder;
+using Microsoft.Bot.Builder.Dialogs.Declarative;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace CustomAction.MultiplyDialog
+{
+ ///
+ /// Definition of a that allows registration of
+ /// services, custom actions, memory scopes and adapters.
+ ///
+ /// To make your components available to the system you derive from BotComponent and register services to add functionality.
+ /// These components then are consumed in appropriate places by the systems that need them. When using Composer, Startup gets called
+ /// automatically on the components by the bot runtime, as long as the components are registered in the configuration.
+ public class MultiplyDialogBotComponent : BotComponent
+ {
+ ///
+ /// Entry point for bot components to register types in resource explorer, consume configuration and register services in the
+ /// services collection.
+ ///
+ /// Services collection to register dependency injection.
+ /// Configuration for the bot component.
+ public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
+ {
+ // Anything that could be done in Startup.ConfigureServices can be done here.
+ // In this case, the MultiplyDialog needs to be added as a new DeclarativeType.
+ services.AddSingleton(sp => new DeclarativeType(MultiplyDialog.Kind));
+ }
+ }
+}
diff --git a/docs/extending-with-code.md b/docs/extending-with-code.md
index 504a45bee7..30672bad5b 100644
--- a/docs/extending-with-code.md
+++ b/docs/extending-with-code.md
@@ -1,24 +1,160 @@
# Extending your bot with code
-> Note: You should be familiar with the existing documentation on [custom actions](https://docs.microsoft.com/en-us/composer/how-to-add-custom-action) and [declarative dialogs](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-dialogs-declarative?view=azure-bot-service-4.0). This page is supplemental to those existing resources.
+# Add custom actions in C#
-Extending your bot with code is very similar to the currently published documentation (linked above). It differs from that documentation in the following ways:
+## In this article
-1. There is no need to eject your runtime & app code, as we do this for you at creation time.
-1. The bot project we create for you on disk does not include the sample code as indicated in the documentation, you'll need to create the files from.
- 1. You also don't add a reference to another project - just create the .cs and .schema files yourself, directly in your .sln that was created for you.
-1. You'll probably need to manually run `dialog:merge` rather than use the PowerShell script. The command is below, execute from in the `/schemas` folder.
+In Bot Framework Composer, [actions](concept-dialog#action) are the main
+contents of a [trigger](concept-dialog#trigger). Actions help maintain
+conversation flow and instruct bots on how to fulfill user requests.
+Composer provides different types of actions, such as **Send a
+response**, **Ask a question**, and **Create a condition**. Besides
+these built-in actions, you can create and customize your own actions in
+Composer.
-```bash
-bf dialog:merge "*.schema" "!**/sdk-backup.schema" "*.uischema" "!**/sdk-backup.uischema" "!**/sdk.override.uischema" "../*.csproj" "../package.json" -o sdk.schema
-```
+This article shows you how to include a custom action named
+`MultiplyDialog`.
-You can also take a look at the [Graph package](/packages/Graph) for another example.
+#### Note
+
+Composer currently supports the C\# runtime and JavaScript (preview)
+Adaptive Runtimes.
+
+## Prerequisites
+
+- A basic understanding of [actions](concept-dialog#action) in Composer.
+- [A basic bot built using Composer](quickstart-create-bot).
+- [Bot Framework CLI 4.10](https://botbuilder.myget.org/feed/botframework-cli/package/npm/@microsoft/botframework-cli) or later.
+
+## Setup the Bot Framework CLI tool
+----------------------
+
+The Bot Framework CLI tools include the *bf-dialog* tool which will
+create a *schema file* that describes the built-in and custom
+capabilities of your bot project. It does this by merging partial schema
+files included with each component with the root schema provided by Bot
+Framework.
+
+Open a command line and run the following command to install the Bot
+Framework tools:
+
+ npm i -g @microsoft/botframework-cli
+
+## About this custom action
+----------------------
+
+This C\# custom action consists of the following:
+
+- A Composer project targeted for Dotnet. This can be any Composer project. One that already exists, or a new one you create. If you want to experiment risk free, create a new Blank Bot in Composer. This document assumes you create a Blank Bot named "MyBlankBot".
+
+- The custom action code [MultiplyDialog.cs](assets/MultiplyDialog.cs) class, which defines the business logic of the custom action. In this example, two numbers passed as inputs are multiplied, and the result is the output.
+
+- The custom action schema [MultiplyDialog.schema](assets/MultiplyDialog.schema), which describes the operations available.
+
+ [Bot Framework Schemas](https://github.com/microsoft/botframework-sdk/tree/master/schemas)
+ are specifications for JSON data. They define the shape of the data
+ and can be used to validate JSON. All of Bot Framework's [adaptive
+ dialogs](/en-us/azure/bot-service/bot-builder-adaptive-dialog-introduction)
+ are defined using this JSON schema. The schema files tell Composer
+ what capabilities the bot runtime supports. Composer uses the schema
+ to help it render the user interface when using the action in a
+ dialog. Read the section about [creating schema files in adaptive
+ dialogs](/en-us/azure/bot-service/bot-builder-dialogs-declarative)
+ for more information.
+
+- A BotComponent, [MultiplyDialogBotComponent.cs](assets/MultiplyDialogBotComponent.cs) code file for component registration. BotComponents are loaded by your bot (specifically by Adaptive Runtime), and made available to Composer.
+
+ **Note** You can create a custom action without implementing BotComponent. However, the Component Model in Bot Framework allows for easier reuse and is only slightly more work. In a BotComponent, you add the needed services and objects via Dependency Injection, just as you would in Startup.cs.
+
+## Adding the custom action to your bot project
+------------------------------
+
+1. Navigate to your Composer bot project folder (eg. C:\MyBlankBot) and create a new folder for the custom action project. For example, C:\MyBlankBot\MultiplyDialog.
+
+1. Save [MultiplyDialog.cs](assets/MultiplyDialog.cs), [MultiplyDialog.schema](assets/MultiplyDialog.schema), [MultiplyDialog.csproj](assets/MultiplyDialog.csproj), and [MultiplyDialogBotComponent.cs](assets/MultiplyDialogBotComponent.cs) to this new folder.
+
+1. Open your Blank Bot solution (C:\MyBlankBot) in Visual Studio.
+
+1. Add Existing project to the solution.
+
+1. In the MyBlankBot project, add a project reference to the MultiplyDialog project. Alternatively, you can add `` to the appropriate `ItemGroup` in MyBlankBot.csproj.
+
+1. Run the command `dotnet build` on the project to
+ verify if it passes build after adding custom actions to it. You
+ should be able to see the "Build succeeded" message after this
+ command.
+
+1. Edit MyBlankBot\settings\appsettings.json to include the MultiplyDialogBotComponent in the `runtimeSettings/components` list.
+
+ ```json
+ "runtimeSettings": {
+ "components": [
+ {
+ "name": "CustomAction.MultiplyDialog"
+ }
+ ]
+ }
+ ```
+
+## Update the schema file
+----------------------
+
+Now you have customized your bot, the next step is to update the
+`sdk.schema` file to include the `MultiplyDialog.Schema` file. This makes your custom action available for use in Composer.
+
+**You only need to perform these steps when adding new code extensions, or when the Schema for a component changes.**
+
+1) Navigate to the `C:\MyBlankBot\MyBlankBot\schemas` folder. This
+folder contains a PowerShell script and a bash script. Run either one of
+the following commands:
+
+ ./update-schema.ps1
+
+ **Note**
+
+ The above steps should generate a new `sdk.schema` file inside the
+ `schemas` folder.
+
+1) Search for `MultiplyDialog` inside the `MyBlankBot\schemas\sdk.schema` file and
+ validate that the partial schema for [MultiplyDialog.schema](assets/MultiplyDialog.schema) is included in `sdk.schema`.
+
+### Tip
+
+Alternatively, you can select the `update-schema.sh` file inside the
+`MyBlankBot\schemas` folder to run the bash script. You can't click and run the
+`powershell` file directly.
+
+## Test
+----
+
+Open the bot project in Composer and you should be able to test your
+added custom action. If the project is already loaded, return to `Home` in Composer, and reload the project.
+
+1. Open your bot in Composer. Select a trigger you want to associate this custom action with.
+
+2. Select **+** under the trigger node to see the actions menu. You
+ will see **Custom Actions** added to the menu. Select **Multiply**
+ from the menu.
+
+3. On the **Properties** panel on the right side, enter two numbers in
+ the argument fields: **Arg1** and **Arg2**. Enter **dialog.result**
+ in the **Result** property field. For example, enter `99` for each field.
+
+4. Add a **Send a response** action. Enter `99*99=${dialog.result}` in the Language Generation editor.
+
+5. Select **Restart Bot** to test the bot in the Emulator. Your bot
+ will respond with the test result.
+
+## Additional information
+----------------------
+
+- [Bot Framework SDK Schemas](https://github.com/microsoft/botframework-sdk/tree/master/schemas)
+- [Create schema files](/en-us/azure/bot-service/bot-builder-dialogs-declarative)
## Docs table of contents
1. [Overview](/docs/overview.md)
2. [Extending your bot using packages](/docs/extending-with-packages.md)
-3. [Extending your bot with code](/docs/extending-with-code.md)
+3. Extending your bot with code (this document)
4. [Creating your own packages](/docs/creating-packages.md)
5. [Creating your own templates](/docs/creating-templates.md)