├── CSharp
├── .gitignore
├── AzureSql-CreateTable.sql
├── Library
│ ├── Microsoft.Bot.Builder.Azure.Logging
│ │ ├── AzureQueueActivityLogger.cs
│ │ ├── AzureQueueReader.cs
│ │ ├── IQueueReader.cs
│ │ ├── LargeMessageMode.cs
│ │ ├── Microsoft.Bot.Builder.Azure.Logging.csproj
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── QueueActivityModule.cs
│ │ ├── QueueLoggerSettings.cs
│ │ ├── ServiceBusActivityLogger.cs
│ │ ├── ServiceBusQueueReader.cs
│ │ ├── app.config
│ │ └── packages.config
│ └── Microsoft.Bot.Builder.Azure
│ │ ├── AzureBot.cs
│ │ ├── AzureModule.cs
│ │ ├── BotDataStoreBridge.cs
│ │ ├── BotService.cs
│ │ ├── DocumentDbBotDataStore.cs
│ │ ├── Extensions.cs
│ │ ├── Microsoft.Bot.Builder.Azure.csproj
│ │ ├── Microsoft.Bot.Builder.Azure.nuspec
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── SqlBotDataStore.cs
│ │ ├── TableBotDataStore.cs
│ │ ├── TableBotDataStore2.cs
│ │ ├── TableLogger.cs
│ │ ├── Utils.cs
│ │ ├── app.config
│ │ ├── createpackage.cmd
│ │ └── packages.config
├── Microsoft.Bot.Builder.Azure.sln
├── Samples
│ ├── AzureSql
│ │ ├── Controllers
│ │ │ └── MessagesController.cs
│ │ ├── Dialogs
│ │ │ └── EchoDialog.cs
│ │ ├── Global.asax
│ │ ├── Global.asax.cs
│ │ ├── Microsoft.Bot.Sample.AzureSql.csproj
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── README.md
│ │ ├── Web.Debug.config
│ │ ├── Web.Release.config
│ │ ├── Web.config
│ │ ├── default.htm
│ │ └── packages.config
│ ├── AzureTable
│ │ ├── Controllers
│ │ │ └── MessagesController.cs
│ │ ├── Dialogs
│ │ │ └── EchoDialog.cs
│ │ ├── Global.asax
│ │ ├── Global.asax.cs
│ │ ├── Microsoft.Bot.Sample.AzureTable.csproj
│ │ ├── Microsoft.Bot.Sample.AzureTable.csproj.user
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── README.md
│ │ ├── Web.Debug.config
│ │ ├── Web.Release.config
│ │ ├── Web.config
│ │ └── packages.config
│ └── DocumentDb
│ │ ├── Controllers
│ │ └── MessagesController.cs
│ │ ├── Dialogs
│ │ └── EchoDialog.cs
│ │ ├── Global.asax
│ │ ├── Global.asax.cs
│ │ ├── Microsoft.Bot.Sample.DocumentDb.csproj
│ │ ├── Microsoft.Bot.Sample.DocumentDb.csproj.user
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── README.md
│ │ ├── Web.Debug.config
│ │ ├── Web.Release.config
│ │ ├── Web.config
│ │ └── packages.config
├── SimpleEchoBot
│ ├── .gitignore
│ ├── EchoBot.cs
│ ├── EchoDialog.cs
│ ├── SimpleEchoBot.csproj
│ └── host.json
├── Tests
│ └── Microsoft.Bot.Builder.Azure.Tests
│ │ ├── BotDataStoreBridgeTests.cs
│ │ ├── BotServiceTests.cs
│ │ ├── DataStoreTests.cs
│ │ ├── DialogTestBase.cs
│ │ ├── DocumentDbDataStoreTests.cs
│ │ ├── DocumentDbDeleter.cs
│ │ ├── LoggerTestBase.cs
│ │ ├── LoggerTests.cs
│ │ ├── Microsoft.Bot.Builder.Azure.Tests.csproj
│ │ ├── MockConnectorFactory.cs
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── QueueLoggerTest.cs
│ │ ├── StorageEmulatorRunner.cs
│ │ ├── TableDataStore2Tests.cs
│ │ ├── TableDataStoreTests.cs
│ │ ├── app.config
│ │ └── packages.config
├── buildtools
│ ├── 35MSSharedLib1024.snk
│ ├── SetVersionInAssemblyInfoCsFiles.ps1
│ └── updateAssemblyInfo.ps1
└── readme.md
├── Contributing.md
├── LICENSE
├── Node
├── .gitignore
├── .npmignore
├── docs
│ ├── botframework
│ │ ├── assets
│ │ │ ├── css
│ │ │ │ ├── main.css
│ │ │ │ └── main.css.map
│ │ │ ├── images
│ │ │ │ ├── icons.png
│ │ │ │ ├── icons@2x.png
│ │ │ │ ├── widgets.png
│ │ │ │ └── widgets@2x.png
│ │ │ └── js
│ │ │ │ ├── main.js
│ │ │ │ └── modernizr.js
│ │ ├── layouts
│ │ │ └── default.hbs
│ │ ├── partials
│ │ │ ├── analytics.hbs
│ │ │ ├── breadcrumb.hbs
│ │ │ ├── comment.hbs
│ │ │ ├── docs-header.hbs
│ │ │ ├── footer.hbs
│ │ │ ├── header.hbs
│ │ │ ├── hierarchy.hbs
│ │ │ ├── index.hbs
│ │ │ ├── member.declaration.hbs
│ │ │ ├── member.getterSetter.hbs
│ │ │ ├── member.hbs
│ │ │ ├── member.signature.body.hbs
│ │ │ ├── member.signature.title.hbs
│ │ │ ├── member.signatures.hbs
│ │ │ ├── member.sources.hbs
│ │ │ ├── members.group.hbs
│ │ │ ├── members.hbs
│ │ │ ├── ms-footer.hbs
│ │ │ ├── navigation.hbs
│ │ │ ├── parameter.hbs
│ │ │ ├── toc.hbs
│ │ │ ├── toc.root.hbs
│ │ │ ├── type.hbs
│ │ │ ├── typeAndParent.hbs
│ │ │ └── typeParameters.hbs
│ │ └── templates
│ │ │ ├── index.hbs
│ │ │ └── reflection.hbs
│ └── build-docs.cmd
├── examples
│ ├── feature-azureSql
│ │ └── app.js
│ ├── feature-azureTable
│ │ └── app.js
│ └── feature-documentDb
│ │ └── app.js
├── lib
│ ├── AzureBotStorage.js
│ ├── AzureSqlClient.js
│ ├── AzureTableClient.js
│ ├── BotServiceConnector.js
│ ├── Consts.js
│ ├── DocumentDbClient.js
│ ├── IStorageClient.js
│ ├── botbuilder-azure.d.ts
│ └── botbuilder-azure.js
├── npm-debug.log
├── package-lock.json
├── package.json
├── readme.md
├── src
│ ├── AzureBotStorage.ts
│ ├── AzureSqlClient.ts
│ ├── AzureTableClient.ts
│ ├── BotServiceConnector.ts
│ ├── Consts.ts
│ ├── DocumentDbClient.ts
│ ├── IStorageClient.ts
│ ├── botbuilder-azure.d.ts
│ ├── botbuilder-azure.ts
│ └── tsconfig.json
└── test
│ ├── .vscode
│ ├── launch.json
│ └── tasks.json
│ ├── AzureTableClientTest.js
│ ├── DocumentDbClientTest.js
│ ├── Readme.md
│ ├── TableBotStorageFaultTest.js
│ ├── TableBotStorageTest.js
│ ├── lib
│ └── FaultyAzureTableClient.js
│ └── src
│ ├── FaultyAzureTableClient.ts
│ └── tsconfig.json
└── README.md
/CSharp/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 | ecf/
25 | rcf/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | *.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opensdf
80 | *.sdf
81 | *.cachefile
82 |
83 | # Visual Studio profiler
84 | *.psess
85 | *.vsp
86 | *.vspx
87 |
88 | # TFS 2012 Local Workspace
89 | $tf/
90 |
91 | # Guidance Automation Toolkit
92 | *.gpState
93 |
94 | # ReSharper is a .NET coding add-in
95 | _ReSharper*/
96 | *.[Rr]e[Ss]harper
97 | *.DotSettings.user
98 |
99 | # JustCode is a .NET coding add-in
100 | .JustCode
101 |
102 | # TeamCity is a build add-in
103 | _TeamCity*
104 |
105 | # DotCover is a Code Coverage Tool
106 | *.dotCover
107 |
108 | # NCrunch
109 | _NCrunch_*
110 | .*crunch*.local.xml
111 |
112 | # MightyMoose
113 | *.mm.*
114 | AutoTest.Net/
115 |
116 | # Web workbench (sass)
117 | .sass-cache/
118 |
119 | # Installshield output folder
120 | [Ee]xpress/
121 |
122 | # DocProject is a documentation generator add-in
123 | DocProject/buildhelp/
124 | DocProject/Help/*.HxT
125 | DocProject/Help/*.HxC
126 | DocProject/Help/*.hhc
127 | DocProject/Help/*.hhk
128 | DocProject/Help/*.hhp
129 | DocProject/Help/Html2
130 | DocProject/Help/html
131 |
132 | # Click-Once directory
133 | publish/
134 |
135 | # Publish Web Output
136 | *.[Pp]ublish.xml
137 | ## TODO: Comment the next line if you want to checkin your
138 | ## web deploy settings but do note that will include unencrypted
139 | ## passwords
140 | #*.pubxml
141 |
142 | ## ignore imporeted publish xml files
143 | *intercom-botdirectory-scratch\ -\ FTP.pubxml
144 | *intercom-botdirectory-scratch\ -\ Web\ Deploy.pubxml
145 |
146 | *.publishproj
147 |
148 | # NuGet Packages
149 | *.nupkg
150 | # The packages folder can be ignored because of Package Restore
151 | **/packages/*
152 | # except build/, which is used as an MSBuild target.
153 | !**/packages/build/
154 | # Uncomment if necessary however generally it will be regenerated when needed
155 | #!**/packages/repositories.config
156 |
157 | # Windows Azure Build Output
158 | csx/
159 | *.build.csdef
160 |
161 | # Windows Store app package directory
162 | AppPackages/
163 |
164 | # Visual Studio cache files
165 | # files ending in .cache can be ignored
166 | *.[Cc]ache
167 | # but keep track of directories ending in .cache
168 | !*.[Cc]ache/
169 |
170 | # Others
171 | ClientBin/
172 | [Ss]tyle[Cc]op.*
173 | ~$*
174 | *~
175 | *.dbmdl
176 | *.dbproj.schemaview
177 | *.pfx
178 | *.publishsettings
179 | node_modules/
180 | orleans.codegen.cs
181 |
182 | # RIA/Silverlight projects
183 | Generated_Code/
184 |
185 | # Backup & report files from converting an old project file
186 | # to a newer Visual Studio version. Backup files are not needed,
187 | # because we have git ;-)
188 | _UpgradeReport_Files/
189 | Backup*/
190 | UpgradeLog*.XML
191 | UpgradeLog*.htm
192 |
193 | # SQL Server files
194 | *.mdf
195 | *.ldf
196 |
197 | # Business Intelligence projects
198 | *.rdl.data
199 | *.bim.layout
200 | *.bim_*.settings
201 |
202 | # Microsoft Fakes
203 | FakesAssemblies/
204 |
205 | # Node.js Tools for Visual Studio
206 | .ntvs_analysis.dat
207 |
208 | # Visual Studio 6 build log
209 | *.plg
210 |
211 | # Visual Studio 6 workspace options file
212 | *.opt
213 |
214 | # LightSwitch generated files
215 | GeneratedArtifacts/
216 | _Pvt_Extensions/
217 | ModelManifest.xml
218 | /Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll
219 | /Microsoft.CodeDom.Providers.DotNetCompilerPlatform.xml
220 | /PublishScripts/Scripts/Deploy-AzureResourceGroup-5.ps1
221 | /PublishScripts
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 | # User-specific files
232 | Documentation/Doxygen_warnings.txt
233 |
234 | # Build results
235 | Documentation/docs/
236 |
237 | # Azure publish profiles
238 | *.pubxml
239 | PublishProfiles/
240 |
--------------------------------------------------------------------------------
/CSharp/AzureSql-CreateTable.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/BotBuilder-Azure/51fa832dc243ffbfb34f741fb929f349e903ec06/CSharp/AzureSql-CreateTable.sql
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/AzureQueueActivityLogger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Threading.Tasks;
4 | using Microsoft.Bot.Builder.History;
5 | using Microsoft.Bot.Builder.Internals.Fibers;
6 | using Microsoft.Bot.Connector;
7 | using Microsoft.WindowsAzure.Storage.Queue;
8 | using Newtonsoft.Json;
9 |
10 | namespace Microsoft.Bot.Builder.Azure
11 | {
12 | ///
13 | /// Log activities to Azure Storage Queue.
14 | ///
15 | ///
16 | /// Activities are limited to size of Azure Storage queue payload. Disposition of larger messages is controlled by QueueLoggerSettings.
17 | /// for more information on limits see https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-azure-and-service-bus-queues-compared-contrasted
18 | ///
19 | public class AzureQueueActivityLogger : IActivityLogger
20 | {
21 | private readonly JsonSerializerSettings _jsonSerializerSettings;
22 | private readonly CloudQueue _cloudQueue;
23 | private readonly QueueLoggerSettings _queueLoggerSettings;
24 |
25 | private readonly float _cutCoefficient;
26 |
27 | ///
28 | /// Constructs an instance of AzureQueueActivityLogger
29 | ///
30 | /// Reference to a CloudQueue instance
31 | /// Settings informing the logger how to handle large messages and whether compression is required
32 | /// JSON serialziation settings used to write the formatted JSON message before adding to the queue
33 | public AzureQueueActivityLogger(CloudQueue cloudQueue, QueueLoggerSettings queueSettings = null, JsonSerializerSettings settings = null)
34 | {
35 | SetField.NotNull(out _cloudQueue, nameof(cloudQueue), cloudQueue);
36 |
37 | //set the defaults
38 | _queueLoggerSettings = queueSettings ?? new QueueLoggerSettings();
39 | _jsonSerializerSettings = settings;
40 | _cutCoefficient = 1 - _queueLoggerSettings.MessageTrimRate;
41 | }
42 |
43 | ///
44 | /// Logs a single Activity message
45 | ///
46 | /// An activity to be logged
47 | ///
48 | /// thrown when message exceeds length limit
49 | public async Task LogAsync(IActivity activity)
50 | {
51 | var message = activity.AsMessageActivity();
52 |
53 | var jsonMsg = JsonConvert.SerializeObject(message, _jsonSerializerSettings);
54 | var bytes = GetBytes(jsonMsg);
55 |
56 | if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Discard)
57 | {
58 | //if fails, do not do anything....
59 | try
60 | {
61 | await _cloudQueue.AddMessageAsync(new CloudQueueMessage(bytes));
62 | }
63 | catch
64 | {
65 | // ignored
66 | }
67 | }
68 | else if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Error)
69 | {
70 | //let it fail
71 | await _cloudQueue.AddMessageAsync(new CloudQueueMessage(bytes));
72 | }
73 | else if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Trim)
74 | {
75 | do
76 | {
77 | try
78 | {
79 | await _cloudQueue.AddMessageAsync(new CloudQueueMessage(bytes));
80 | return;
81 | }
82 | catch (Exception)
83 | {
84 | //cut off some of the text to fit
85 | message.Text = message.Text.Substring(0, (int)(message.Text.Length * _cutCoefficient));
86 | jsonMsg = JsonConvert.SerializeObject(message, _jsonSerializerSettings);
87 | bytes = GetBytes(jsonMsg);
88 | }
89 | } while (true);
90 | }
91 | }
92 |
93 | byte[] GetBytes(string message)
94 | {
95 | return _queueLoggerSettings.CompressMessage ? message.Compress() : Encoding.UTF8.GetBytes(message);
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/AzureQueueReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Microsoft.Bot.Builder.Internals.Fibers;
5 | using Microsoft.Bot.Connector;
6 | using Microsoft.WindowsAzure.Storage.Queue;
7 | using Newtonsoft.Json;
8 |
9 | namespace Microsoft.Bot.Builder.Azure
10 | {
11 | ///
12 | /// Reads messages from an Azure Storage Queue
13 | ///
14 | public class AzureQueueReader : IQueueReader
15 | {
16 | private readonly CloudQueue _cloudQueue;
17 | private readonly QueueLoggerSettings _queueLoggerSettings;
18 |
19 | ///
20 | ///
21 | ///
22 | /// Reference to a CloudQueue instance
23 | /// Settings informing the logger how to handle large messages and whether compression is required
24 | public AzureQueueReader(CloudQueue cloudQueue, QueueLoggerSettings queueSettings = null)
25 | {
26 | SetField.NotNull(out _cloudQueue, nameof(cloudQueue), cloudQueue);
27 |
28 | //set the defaults
29 | _queueLoggerSettings = queueSettings ?? new QueueLoggerSettings();
30 | }
31 | private Activity DeserializeItem(CloudQueueMessage msg)
32 | {
33 | string jsonActivity;
34 |
35 | //message is compressed
36 | if (_queueLoggerSettings.CompressMessage)
37 | jsonActivity = msg.AsBytes.Decompress();
38 | else
39 | jsonActivity = msg.AsString;
40 |
41 | var data = JsonConvert.DeserializeObject(jsonActivity);
42 |
43 | return data;
44 | }
45 | ///
46 | /// Read a single activity message from the queue
47 | ///
48 | ///
49 | public IActivity Read()
50 | {
51 | return ReadAsync().GetAwaiter().GetResult();
52 | }
53 |
54 | ///
55 | /// Read a single activity message from the queue, asynchronously
56 | ///
57 | ///
58 | public async Task ReadAsync()
59 | {
60 | var msg = await _cloudQueue.GetMessageAsync();
61 |
62 | if (msg == null)
63 | return null;
64 |
65 | var data = DeserializeItem(msg);
66 |
67 | return data;
68 | }
69 |
70 | ///
71 | /// Queue may contain more than one message, read the {messageCount} of messages from the queue
72 | ///
73 | /// Maximum number of messages to return
74 | ///
75 | public List ReadBatch(int messageCount)
76 | {
77 | return ReadBatchAsync(messageCount).GetAwaiter().GetResult();
78 | }
79 |
80 | ///
81 | /// Reads a batch of messages from the queue not to exceed the message count.
82 | ///
83 | /// Maximum number of messages to return
84 | /// This parameter is ignored
85 | ///
86 | public List ReadBatch(int messageCount, TimeSpan serviceWaitTime)
87 | {
88 | return ReadBatch(messageCount);
89 | }
90 |
91 | ///
92 | /// Reads a batch of messages from the queue not to exceed the message count.
93 | ///
94 | /// Maximum number of messages to return
95 | ///
96 | public async Task> ReadBatchAsync(int messageCount)
97 | {
98 | List batch = new List();
99 | var messageBatch = await _cloudQueue.GetMessagesAsync(messageCount);
100 |
101 | foreach (var msg in messageBatch)
102 | {
103 | batch.Add(DeserializeItem(msg));
104 | }
105 |
106 | return batch;
107 | }
108 | ///
109 | /// Reads a batch of messages from the queue not to exceed the message count.
110 | ///
111 | /// Maximum number of messages to return
112 | /// This parameter is ignored
113 | ///
114 | public Task> ReadBatchAsync(int messageCount, TimeSpan serviceWaitTime)
115 | {
116 | return ReadBatchAsync(messageCount);
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/IQueueReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Microsoft.Bot.Connector;
5 |
6 | namespace Microsoft.Bot.Builder.Azure
7 | {
8 | ///
9 | /// Interface for queue reader
10 | ///
11 | public interface IQueueReader
12 | {
13 | ///
14 | /// Read a single activity message from the queue
15 | ///
16 | IActivity Read();
17 | ///
18 | /// Read a single activity message from the queue, asynchronously
19 | ///
20 | Task ReadAsync();
21 | ///
22 | /// Reads a batch of messages from the queue not to exceed the message count.
23 | ///
24 | /// Maximum number of messages to return
25 | List ReadBatch(int messageCount);
26 | ///
27 | /// Reads a batch of messages from the queue not to exceed the message count.
28 | ///
29 | /// Maximum number of messages to return
30 | Task> ReadBatchAsync(int messageCount, TimeSpan serviceWaitTime);
31 | ///
32 | /// Reads a batch of messages from the queue not to exceed the message count, asynchronously
33 | ///
34 | /// Maximum number of messages to return
35 | Task> ReadBatchAsync(int messageCount);
36 | }
37 | }
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/LargeMessageMode.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Bot.Builder.Azure
2 | {
3 | ///
4 | /// Enumeration for handling of large messages
5 | ///
6 | public enum LargeMessageMode
7 | {
8 | ///
9 | /// Drop the message if exceeds the length limit
10 | ///
11 | Discard,
12 | ///
13 | /// Limit the text to be within the allowed limits
14 | ///
15 | Trim,
16 | ///
17 | /// Throw an exception if message exceeds allowed limit
18 | ///
19 | Error
20 | }
21 | }
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Microsoft.Bot.Builder.Azure.Logging")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Microsoft.Bot.Builder.Azure.Logging")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("f8fdcbfb-3a5d-41e4-8c3d-a158d8783b3e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.1.0")]
36 | [assembly: AssemblyFileVersion("1.0.1.0")]
37 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/QueueLoggerSettings.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Bot.Builder.Azure
2 | {
3 | ///
4 | /// Logger setting to control compression and how to handle large messages
5 | ///
6 | public class QueueLoggerSettings
7 | {
8 | ///
9 | /// Creates an instance of QueueLoggerSettings with default settings
10 | ///
11 | public QueueLoggerSettings()
12 | {
13 | CompressMessage = false;
14 | OverflowHanding = LargeMessageMode.Discard;
15 | MessageTrimRate = 0.10f;
16 | }
17 | ///
18 | /// Informs logger to compress messages, default is false
19 | ///
20 | public bool CompressMessage { get; set; }
21 | ///
22 | /// Informs logger what to do with messages that exceed length limit, default is Discard
23 | ///
24 | public LargeMessageMode OverflowHanding { get; set; }
25 |
26 | //if Overflow is set to trim, MessageTrimRate controls how much string to trim at one time, default is 0.10
27 | public float MessageTrimRate;
28 | }
29 | }
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/ServiceBusActivityLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.Threading.Tasks;
3 | using Microsoft.Bot.Builder.History;
4 | using Microsoft.Bot.Builder.Internals.Fibers;
5 | using Microsoft.Bot.Connector;
6 | using Microsoft.ServiceBus.Messaging;
7 | using Newtonsoft.Json;
8 |
9 | namespace Microsoft.Bot.Builder.Azure
10 | {
11 | ///
12 | /// Log activities to Service Bus Queue.
13 | ///
14 | ///
15 | /// Activities are limited to size of Service Bus queue payload. Disposition of larger messages is controlled by QueueLoggerSettings.
16 | /// for more information on limits see https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-azure-and-service-bus-queues-compared-contrasted
17 | ///
18 | public class ServiceBusActivityLogger : IActivityLogger
19 | {
20 | private readonly QueueClient _client;
21 | private readonly JsonSerializerSettings _jsonSerializerSettings;
22 | private readonly QueueLoggerSettings _queueLoggerSettings;
23 |
24 | //controls how much message we will keep after the cut
25 | private readonly float _cutCoefficient;
26 |
27 | ///
28 | /// Constructs an instance of ServiceBusActivityLogger
29 | ///
30 | /// Reference to a QueueClient instance
31 | /// Settings informing the logger how to handle large messages and whether compression is required
32 | /// JSON serialziation settings used to write the formatted JSON message before adding to the queue
33 | public ServiceBusActivityLogger(QueueClient client, QueueLoggerSettings queueSettings = null,
34 | JsonSerializerSettings settings = null)
35 | {
36 |
37 | SetField.NotNull(out _client, nameof(client), client);
38 |
39 | //set the defaults
40 | _queueLoggerSettings = queueSettings ?? new QueueLoggerSettings();
41 |
42 | _jsonSerializerSettings = settings;
43 | _cutCoefficient = 1 - _queueLoggerSettings.MessageTrimRate;
44 | }
45 |
46 | byte[] GetBytes(string message)
47 | {
48 | return _queueLoggerSettings.CompressMessage ? message.Compress() : Encoding.UTF8.GetBytes(message);
49 | }
50 |
51 | ///
52 | /// Logs a single Activity message
53 | ///
54 | /// An activity to be logged
55 | ///
56 | /// thrown when message exceeds length limit
57 | public async Task LogAsync(IActivity activity)
58 | {
59 | var message = activity.AsMessageActivity();
60 |
61 | string jsonMsg = JsonConvert.SerializeObject(message, _jsonSerializerSettings);
62 | var bytes = GetBytes(jsonMsg);
63 |
64 | if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Discard)
65 | {
66 | //if fails do not do anything....
67 | try
68 | {
69 | await _client.SendAsync(new BrokeredMessage(bytes));
70 | }
71 | catch
72 | {
73 | // ignored
74 | }
75 | }
76 | else if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Error)
77 | {
78 | //let it fail
79 | await _client.SendAsync(new BrokeredMessage(bytes));
80 | }
81 | else if (_queueLoggerSettings.OverflowHanding == LargeMessageMode.Trim)
82 | {
83 | do
84 | {
85 | try
86 | {
87 | await _client.SendAsync(new BrokeredMessage(bytes));
88 | return;
89 | }
90 | catch
91 | {
92 | //cut off some of the text to fit
93 | message.Text = message.Text.Substring(0, (int)(message.Text.Length * _cutCoefficient));
94 | jsonMsg = JsonConvert.SerializeObject(message, _jsonSerializerSettings);
95 | bytes = GetBytes(jsonMsg);
96 | }
97 |
98 | } while (true);
99 | }
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure.Logging/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/AzureBot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.Bot.Builder.Dialogs;
8 | using Microsoft.Bot.Connector;
9 |
10 | namespace Microsoft.Bot.Builder.Azure
11 | {
12 | ///
13 | /// The azure bot utilities and helpers.
14 | ///
15 | ///
16 | /// This class is obsolete now. Use instead.
17 | ///
18 | [Obsolete("This class is obsolete. Use BotService instead.", false)]
19 | public static class AzureBot
20 | {
21 | ///
22 | /// The bot authenticator.
23 | ///
24 | public static BotAuthenticator Authenticator => BotService.Authenticator;
25 |
26 | ///
27 | /// Update the for azure bots.
28 | ///
29 | public static void Initialize()
30 | {
31 | BotService.Initialize(Assembly.GetCallingAssembly());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/BotDataStoreBridge.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Bot.Builder.Dialogs;
2 | using Microsoft.Bot.Builder.Dialogs.Internals;
3 | using Microsoft.Bot.Connector;
4 | using System;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using System.Web;
8 |
9 | namespace Microsoft.Bot.Builder.Azure
10 | {
11 | ///
12 | /// This bridge class should be used during a migration of data from one BotDataStore to another
13 | ///
14 | ///
15 | /// It works by reading from both source and target stores and only writing data to the new store.
16 | /// This allows live code to continue to work while a background job is migrating data from the source store to the target store.
17 | /// To use: deploy your bot using this dual data store while a background job is migrating the data from the
18 | /// source store to the target store. When the background migration job is done you can deploy your bot using the target store
19 | ///
20 | /// NOTE: migration job should ignore precondition failures on write, because if the record already exists in the new store it was migrated
21 | /// dynamically by the use of this class
22 | ///
23 | public class BotDataStoreBridge : IBotDataStore
24 | {
25 | private IBotDataStore sourceStore;
26 | private IBotDataStore targetStore;
27 |
28 | ///
29 | ///
30 | ///
31 | ///
32 | ///
33 | /// if true, a successful write to the target store will remove from the source
34 | public BotDataStoreBridge(IBotDataStore sourceStore, IBotDataStore targetStore)
35 | {
36 | this.sourceStore = sourceStore ?? throw new ArgumentNullException("sourceStore");
37 | this.targetStore = targetStore ?? throw new ArgumentNullException("targetStore");
38 | }
39 |
40 | public async Task LoadAsync(IAddress key, BotStoreType botStoreType, CancellationToken cancellationToken)
41 | {
42 | // read from both in parallel
43 | var sourceStoreReadTask = this.sourceStore.LoadAsync(key, botStoreType, cancellationToken);
44 | var targetStoreReadTask = this.targetStore.LoadAsync(key, botStoreType, cancellationToken);
45 | await Task.WhenAll(sourceStoreReadTask, targetStoreReadTask).ConfigureAwait(false);
46 |
47 | // if record isn't in targetStore yet, return sourceStore record
48 | if (String.IsNullOrEmpty(targetStoreReadTask.Result.ETag) || targetStoreReadTask.Result.ETag == "*")
49 | {
50 | // but with wildcard etag so save will create new record in target store
51 | sourceStoreReadTask.Result.ETag = "*";
52 | return sourceStoreReadTask.Result;
53 | }
54 | return targetStoreReadTask.Result;
55 | }
56 |
57 | public async Task SaveAsync(IAddress key, BotStoreType botStoreType, BotData data, CancellationToken cancellationToken)
58 | {
59 | // Always save to target store
60 | await this.targetStore.SaveAsync(key, botStoreType, data, cancellationToken);
61 | }
62 |
63 | public Task FlushAsync(IAddress key, CancellationToken cancellationToken)
64 | {
65 | // always flush to target store (since we are only writing to target store)
66 | return this.targetStore.FlushAsync(key, cancellationToken);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace Microsoft.Bot.Builder.Azure
6 | {
7 | internal static class StringExtensions
8 | {
9 | private static readonly Dictionary _DefaultReplacementsForCharactersDisallowedByAzure = new Dictionary() { { "/", "|s|" }, { @"\", "|b|" }, { "#", "|h|" }, { "?", "|q|" } };
10 |
11 | ///
12 | /// Replaces the four characters disallowed in Azure keys with something more palatable. You can provide your own mapping if you don't like the defaults.
13 | ///
14 | internal static string SanitizeForAzureKeys(this string input, Dictionary replacements = null)
15 | {
16 | var repmap = replacements ?? _DefaultReplacementsForCharactersDisallowedByAzure;
17 | return input.Trim().Replace("/", repmap["/"]).Replace(@"\", repmap[@"\"]).Replace("#", repmap["#"]).Replace("?", repmap["?"]);
18 | }
19 |
20 | internal static string SanitizeTableName(this string input)
21 | {
22 | if (input.Length > 63)
23 | {
24 | input = input.Substring(0, 63);
25 | }
26 | input = Regex.Replace(input, @"[^a-zA-Z0-9]+", "");
27 | return input;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.Bot.Builder.Azure
5 | $version$
6 | Microsoft
7 | microsoft, BotFramework, nugetbotbuilder
8 | © Microsoft Corporation. All rights reserved.
9 | true
10 | https://github.com/Microsoft/BotBuilder-Azure/blob/master/LICENSE
11 |
12 | Provide Microsoft Azure extensions to the Microsoft Bot Builder. In particular this includes:
13 | * TableLogger -- Activity logger for table storage which allows recording and retrieving conversation activities.
14 | * ReplayTranscript -- Replay activity history on any channel.
15 | * AzureModule -- Module for setting up components for bot builder based on Azure dependencies
16 | * TableBotDataStore2 -- IBotDataStore implementation based on Azure table storage.
17 | * DocumentDbBotDataStore -- IBotDataStore implementation based on Azure table storage.
18 | * SqlBotDataStore -- IBotDataStore implementation based on Azure Sql Server.
19 |
20 | https://github.com/Microsoft/BotBuilder-Azure
21 | http://docs.botframework.com/images/bot_icon.png
22 | Microsoft Azure extensions for Microsoft Bot Builder.
23 | en-US
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Microsoft.Bot.Builder.Azure")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("Microsoft.Bot.Builder.Azure")]
12 | [assembly: AssemblyCopyright("Copyright © 2017")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("77299f9c-8f49-4839-b7ea-55ba726321d5")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("3.16.3.0")]
35 | [assembly: AssemblyFileVersion("3.16.3.0")]
36 |
37 | //[assembly: AssemblyKeyFileAttribute(@"..\\..\\buildtools\\35MSSharedLib1024.snk")]
38 | //[assembly: AssemblyDelaySignAttribute(true)]
39 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/createpackage.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo *** Building Microsoft.Bot.Builder.Azure
3 | setlocal
4 | setlocal enabledelayedexpansion
5 | setlocal enableextensions
6 | set errorlevel=0
7 | mkdir ..\nuget
8 | erase /s ..\nuget\Microsoft.Bot.Builder.Azure*nupkg
9 | msbuild /property:Configuration=release Microsoft.Bot.Builder.Azure.csproj
10 | for /f %%v in ('powershell -noprofile "(Get-Command .\bin\release\Microsoft.Bot.Builder.dll).FileVersionInfo.FileVersion"') do set builder=%%v
11 | for /f %%v in ('powershell -noprofile "(Get-Command .\bin\release\Microsoft.Bot.Builder.History.dll).FileVersionInfo.FileVersion"') do set history=%%v
12 | for /f %%v in ('powershell -noprofile "(Get-Command .\bin\release\Microsoft.Bot.Builder.Azure.dll).FileVersionInfo.FileVersion"') do set version=%%v
13 | ..\..\packages\NuGet.CommandLine.3.4.3\tools\NuGet.exe pack Microsoft.Bot.Builder.Azure.nuspec -symbols -properties version=%version%;history=%history%;builder=%builder% -OutputDirectory ..\nuget
14 | echo *** Finished building Microsoft.Bot.Builder.Azure
15 |
16 |
--------------------------------------------------------------------------------
/CSharp/Library/Microsoft.Bot.Builder.Azure/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/CSharp/Samples/AzureSql/Controllers/MessagesController.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Net.Http;
3 | using System.Threading.Tasks;
4 | using System.Web.Http;
5 | using Microsoft.Bot.Builder.Dialogs;
6 | using Microsoft.Bot.Connector;
7 |
8 | namespace Microsoft.Bot.Sample.AzureSql
9 | {
10 | [BotAuthentication]
11 | public class MessagesController : ApiController
12 | {
13 | ///
14 | /// POST: api/Messages
15 | /// Receive a message from a user and reply to it
16 | ///
17 | public async Task Post([FromBody]Activity activity)
18 | {
19 | if (activity.Type == ActivityTypes.Message)
20 | {
21 | await Conversation.SendAsync(activity, () => new Dialogs.EchoDialog());
22 | }
23 | else
24 | {
25 | HandleSystemMessage(activity);
26 | }
27 | var response = Request.CreateResponse(HttpStatusCode.OK);
28 | return response;
29 | }
30 |
31 | private Activity HandleSystemMessage(Activity message)
32 | {
33 | if (message.Type == ActivityTypes.DeleteUserData)
34 | {
35 | // Implement user deletion here
36 | // If we handle user deletion, return a real message
37 | }
38 | else if (message.Type == ActivityTypes.ConversationUpdate)
39 | {
40 | // Handle conversation state changes, like members being added and removed
41 | // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
42 | // Not available in all channels
43 | }
44 | else if (message.Type == ActivityTypes.ContactRelationUpdate)
45 | {
46 | // Handle add/remove from contact lists
47 | // Activity.From + Activity.Action represent what happened
48 | }
49 | else if (message.Type == ActivityTypes.Typing)
50 | {
51 | // Handle knowing tha the user is typing
52 | }
53 | else if (message.Type == ActivityTypes.Ping)
54 | {
55 | }
56 |
57 | return null;
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/CSharp/Samples/AzureSql/Dialogs/EchoDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Microsoft.Bot.Builder.Dialogs;
4 | using Microsoft.Bot.Connector;
5 | using Microsoft.Bot.Builder.Dialogs.Internals;
6 |
7 | namespace Microsoft.Bot.Sample.AzureSql.Dialogs
8 | {
9 | [Serializable]
10 | public class EchoDialog : IDialog
11 |
12 |
13 |
--------------------------------------------------------------------------------
/CSharp/Samples/AzureSql/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CSharp/Samples/AzureTable/Controllers/MessagesController.cs:
--------------------------------------------------------------------------------
1 | using Autofac;
2 | using Microsoft.Bot.Builder.Dialogs.Internals;
3 | using Microsoft.Bot.Builder.Internals.Fibers;
4 | using Microsoft.Bot.Connector;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Net;
9 | using System.Net.Http;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using System.Web.Http;
13 | using System.Web.Http.Description;
14 | using Microsoft.Bot.Builder.Dialogs;
15 | using Microsoft.Bot.Sample.AzureTable.Dialogs;
16 |
17 | namespace Microsoft.Bot.Sample.AzureTable.Controllers
18 | {
19 | // Autofac provides a mechanism to inject ActionFilterAttributes from the container
20 | // but seems to require the implementation of special interfaces
21 | // https://github.com/autofac/Autofac.WebApi/issues/6
22 | [BotAuthentication]
23 | public class MessagesController : ApiController
24 | {
25 | // TODO: "service locator"
26 | private readonly ILifetimeScope scope;
27 | public MessagesController(ILifetimeScope scope)
28 | {
29 | SetField.NotNull(out this.scope, nameof(scope), scope);
30 | }
31 |
32 | ///
33 | /// POST: api/Messages
34 | /// receive a message from a user and send replies
35 | ///
36 | ///
37 | [ResponseType(typeof(void))]
38 | public virtual async Task Post([FromBody] Activity activity)
39 | {
40 | // check if activity is of type message
41 | if (activity != null && activity.GetActivityType() == ActivityTypes.Message)
42 | {
43 | await Conversation.SendAsync(activity, () => new EchoDialog());
44 | }
45 | else
46 | {
47 | HandleSystemMessage(activity);
48 | }
49 | return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
50 | }
51 |
52 | private Activity HandleSystemMessage(Activity message)
53 | {
54 | if (message.Type == ActivityTypes.DeleteUserData)
55 | {
56 | // Implement user deletion here
57 | // If we handle user deletion, return a real message
58 | }
59 | else if (message.Type == ActivityTypes.ConversationUpdate)
60 | {
61 | // Handle conversation state changes, like members being added and removed
62 | // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
63 | // Not available in all channels
64 | }
65 | else if (message.Type == ActivityTypes.ContactRelationUpdate)
66 | {
67 | // Handle add/remove from contact lists
68 | // Activity.From + Activity.Action represent what happened
69 | }
70 | else if (message.Type == ActivityTypes.Typing)
71 | {
72 | // Handle knowing tha the user is typing
73 | }
74 | else if (message.Type == ActivityTypes.Ping)
75 | {
76 | }
77 |
78 | return null;
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/CSharp/Samples/AzureTable/Dialogs/EchoDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Web;
6 | using Microsoft.Bot.Builder.Dialogs;
7 | using Microsoft.Bot.Connector;
8 |
9 | namespace Microsoft.Bot.Sample.AzureTable.Dialogs
10 | {
11 | [Serializable]
12 | public class EchoDialog : IDialog