microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
kavin/agents-sdk-interop

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Samples/Samples.Dialogs/Program.cs

306lines · modecode

1using System.Text.Json;
2using System.Text.Json.Serialization;
3
4using Microsoft.Teams.Apps.Activities;
5using Microsoft.Teams.Apps.Activities.Invokes;
6using Microsoft.Teams.Apps.Extensions;
7using Microsoft.Teams.Common;
8using Microsoft.Teams.Plugins.AspNetCore.Extensions;
9
10var builder = WebApplication.CreateBuilder(args);
11builder.Services.AddOpenApi();
12builder.AddTeams();
13
14var app = builder.Build();
15
16if (app.Environment.IsDevelopment())
17{
18 app.MapOpenApi();
19}
20
21app.UseHttpsRedirection();
22var teams = app.UseTeams();
23app.AddTab("dialog-form", "Web/dialog-form");
24
25teams.OnMessage(async (context, cancellationToken) =>
26{
27 var activity = context.Activity;
28 context.Log.Info($"[MESSAGE] Received: {SanitizeForLog(activity.Text)}");
29 context.Log.Info($"[MESSAGE] From: {SanitizeForLog(activity.From?.Name ?? "unknown")}");
30
31 var card = CreateDialogLauncherCard();
32 await context.Send(card, cancellationToken);
33});
34
35teams.OnTaskFetch((context, cancellationToken) =>
36{
37 var activity = context.Activity;
38 context.Log.Info("[TASK_FETCH] Task fetch request received");
39
40 var data = activity.Value?.Data as JsonElement?;
41 if (data == null)
42 {
43 context.Log.Info("[TASK_FETCH] No data found in the activity value");
44 return Task.FromResult(new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("No data found in the activity value")));
45 }
46
47 var dialogType = data.Value.TryGetProperty("dialog_id", out var dialogTypeElement) && dialogTypeElement.ValueKind == JsonValueKind.String
48 ? dialogTypeElement.GetString()
49 : null;
50
51 context.Log.Info($"[TASK_FETCH] Dialog type: {dialogType}");
52
53 var response = dialogType switch
54 {
55 "simple_form" => CreateSimpleFormDialog(),
56 "webpage_dialog" => CreateWebpageDialog(app.Configuration, context.Log),
57 "multi_step_form" => CreateMultiStepFormDialog(),
58 "mixed_example" => CreateMixedExampleDialog(),
59 _ => new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("Unknown dialog type"))
60 };
61 return Task.FromResult(response);
62});
63
64teams.OnTaskSubmit(async (context, cancellationToken) =>
65{
66 var activity = context.Activity;
67 context.Log.Info("[TASK_SUBMIT] Task submit request received");
68
69 var data = activity.Value?.Data as JsonElement?;
70 if (data == null)
71 {
72 context.Log.Info("[TASK_SUBMIT] No data found in the activity value");
73 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("No data found in the activity value"));
74 }
75
76 var submissionType = data.Value.TryGetProperty("submissiondialogtype", out var submissionTypeObj) && submissionTypeObj.ValueKind == JsonValueKind.String
77 ? submissionTypeObj.ToString()
78 : null;
79
80 context.Log.Info($"[TASK_SUBMIT] Submission type: {submissionType}");
81
82 string? GetFormValue(string key)
83 {
84 if (data.Value.TryGetProperty(key, out var val))
85 {
86 if (val is JsonElement element)
87 return element.GetString();
88 return val.ToString();
89 }
90 return null;
91 }
92
93 switch (submissionType)
94 {
95 case "simple_form":
96 var name = GetFormValue("name") ?? "Unknown";
97 await context.Send($"Hi {name}, thanks for submitting the form!", cancellationToken);
98 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("Form was submitted"));
99
100 case "webpage_dialog":
101 var webName = GetFormValue("name") ?? "Unknown";
102 var email = GetFormValue("email") ?? "No email";
103 await context.Send($"Hi {webName}, thanks for submitting the form! We got that your email is {email}", cancellationToken);
104 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("Form submitted successfully"));
105
106 case "webpage_dialog_step_1":
107 var nameStep1 = GetFormValue("name") ?? "Unknown";
108 var nextStepCardJson = $$"""
109 {
110 "type": "AdaptiveCard",
111 "version": "1.4",
112 "body": [
113 { "type": "TextBlock", "text": "Email", "size": "Large", "weight": "Bolder" },
114 { "type": "Input.Text", "id": "email", "label": "Email", "placeholder": "Enter your email", "isRequired": true }
115 ],
116 "actions": [{ "type": "Action.Submit", "title": "Submit", "data": {"submissiondialogtype": "webpage_dialog_step_2", "name": "{{nameStep1}}"} }]
117 }
118 """;
119
120 var nextStepCard = JsonSerializer.Deserialize<Microsoft.Teams.Cards.AdaptiveCard>(nextStepCardJson)
121 ?? throw new InvalidOperationException("Failed to deserialize next step card");
122
123 var nextStepTaskInfo = new Microsoft.Teams.Api.TaskModules.TaskInfo
124 {
125 Title = $"Thanks {nameStep1} - Get Email",
126 Card = new Microsoft.Teams.Api.Attachment
127 {
128 ContentType = new Microsoft.Teams.Api.ContentType("application/vnd.microsoft.card.adaptive"),
129 Content = nextStepCard
130 }
131 };
132 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.ContinueTask(nextStepTaskInfo));
133
134 case "webpage_dialog_step_2":
135 var nameStep2 = GetFormValue("name") ?? "Unknown";
136 var emailStep2 = GetFormValue("email") ?? "No email";
137 await context.Send($"Hi {nameStep2}, thanks for submitting the form! We got that your email is {emailStep2}", cancellationToken);
138 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("Multi-step form completed successfully"));
139
140 default:
141 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.MessageTask("Unknown submission type"));
142 }
143});
144
145app.Run();
146
147static string SanitizeForLog(string? input)
148{
149 if (input == null) return "";
150 return input.Replace("\r", "").Replace("\n", "");
151}
152
153static Microsoft.Teams.Cards.SubmitAction CreateTaskFetchSubmitAction(string title, string dialogId)
154{
155 return new Microsoft.Teams.Cards.SubmitAction
156 {
157 Title = title,
158 Data = new Microsoft.Teams.Common.Union<string, Microsoft.Teams.Cards.SubmitActionData>(
159 new Microsoft.Teams.Cards.OpenDialogData(dialogId))
160 };
161}
162
163static Microsoft.Teams.Cards.AdaptiveCard CreateDialogLauncherCard()
164{
165 var card = new Microsoft.Teams.Cards.AdaptiveCard
166 {
167 Body = new List<Microsoft.Teams.Cards.CardElement>
168 {
169 new Microsoft.Teams.Cards.TextBlock("Select the examples you want to see!")
170 {
171 Size = Microsoft.Teams.Cards.TextSize.Large,
172 Weight = Microsoft.Teams.Cards.TextWeight.Bolder
173 }
174 },
175 Actions = new List<Microsoft.Teams.Cards.Action>
176 {
177 CreateTaskFetchSubmitAction("Simple form test", "simple_form"),
178 CreateTaskFetchSubmitAction("Webpage Dialog", "webpage_dialog"),
179 CreateTaskFetchSubmitAction("Multi-step Form", "multi_step_form"),
180 CreateTaskFetchSubmitAction("Mixed Example", "mixed_example")
181 }
182 };
183
184 var serializedCard = JsonSerializer.Serialize(card, new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
185 Console.WriteLine($"[DEBUG] Launcher Card JSON: {serializedCard}");
186
187 return card;
188}
189
190static Microsoft.Teams.Api.TaskModules.Response CreateSimpleFormDialog()
191{
192 var cardJson = """
193 {
194 "type": "AdaptiveCard",
195 "version": "1.4",
196 "body": [
197 { "type": "TextBlock", "text": "This is a simple form", "size": "Large", "weight": "Bolder" },
198 { "type": "Input.Text", "id": "name", "label": "Name", "placeholder": "Enter your name", "isRequired": true }
199 ],
200 "actions": [{"type": "Action.Submit", "title": "Submit", "data": {"submissiondialogtype": "simple_form"}}]
201 }
202 """;
203
204 var dialogCard = JsonSerializer.Deserialize<Microsoft.Teams.Cards.AdaptiveCard>(cardJson)
205 ?? throw new InvalidOperationException("Failed to deserialize simple form card");
206
207 var serializedCard = JsonSerializer.Serialize(dialogCard);
208 Console.WriteLine($"[DEBUG] Simple Form Card JSON: {serializedCard}");
209
210 var taskInfo = new Microsoft.Teams.Api.TaskModules.TaskInfo
211 {
212 Title = "Simple Form Dialog",
213 Card = new Microsoft.Teams.Api.Attachment
214 {
215 ContentType = new Microsoft.Teams.Api.ContentType("application/vnd.microsoft.card.adaptive"),
216 Content = dialogCard
217 }
218 };
219
220 var continueTask = new Microsoft.Teams.Api.TaskModules.ContinueTask(taskInfo);
221
222 Console.WriteLine($"[DEBUG] continueTask.Value is null: {continueTask.Value == null}");
223 Console.WriteLine($"[DEBUG] continueTask.Value.Title: '{continueTask.Value?.Title}'");
224 Console.WriteLine($"[DEBUG] continueTask.Value.Card is null: {continueTask.Value?.Card == null}");
225
226 var debugOptions = new JsonSerializerOptions
227 {
228 DefaultIgnoreCondition = JsonIgnoreCondition.Never,
229 WriteIndented = true
230 };
231 var continueTaskJson = JsonSerializer.Serialize(continueTask, debugOptions);
232 Console.WriteLine($"[DEBUG] ContinueTask JSON (no ignore): {continueTaskJson}");
233
234 var response = new Microsoft.Teams.Api.TaskModules.Response(continueTask);
235 var serializedResponse = JsonSerializer.Serialize(response, debugOptions);
236 Console.WriteLine($"[DEBUG] Response JSON (no ignore): {serializedResponse}");
237
238 return response;
239}
240
241static Microsoft.Teams.Api.TaskModules.Response CreateWebpageDialog(IConfiguration configuration, Microsoft.Teams.Common.Logging.ILogger log)
242{
243 var botEndpoint = configuration["BotEndpoint"];
244 if (string.IsNullOrEmpty(botEndpoint))
245 {
246 log.Warn("No remote endpoint detected. Using webpages for dialog will not work as expected");
247 botEndpoint = "http://localhost:3978";
248 }
249 else
250 {
251 log.Info($"Using BotEndpoint: {botEndpoint}/tabs/dialog-form");
252 }
253
254 var taskInfo = new Microsoft.Teams.Api.TaskModules.TaskInfo
255 {
256 Title = "Webpage Dialog",
257 Width = new Union<int, Microsoft.Teams.Api.TaskModules.Size>(1000),
258 Height = new Union<int, Microsoft.Teams.Api.TaskModules.Size>(800),
259 Url = $"{botEndpoint}/tabs/dialog-form"
260 };
261
262 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.ContinueTask(taskInfo));
263}
264
265static Microsoft.Teams.Api.TaskModules.Response CreateMultiStepFormDialog()
266{
267 var cardJson = """
268 {
269 "type": "AdaptiveCard",
270 "version": "1.4",
271 "body": [
272 { "type": "TextBlock", "text": "This is a multi-step form", "size": "Large", "weight": "Bolder" },
273 { "type": "Input.Text", "id": "name", "label": "Name", "placeholder": "Enter your name", "isRequired": true }
274 ],
275 "actions": [{ "type": "Action.Submit", "title": "Submit", "data": {"submissiondialogtype": "webpage_dialog_step_1"} }]
276 }
277 """;
278
279 var dialogCard = JsonSerializer.Deserialize<Microsoft.Teams.Cards.AdaptiveCard>(cardJson)
280 ?? throw new InvalidOperationException("Failed to deserialize multi-step form card");
281
282 var taskInfo = new Microsoft.Teams.Api.TaskModules.TaskInfo
283 {
284 Title = "Multi-step Form Dialog",
285 Card = new Microsoft.Teams.Api.Attachment
286 {
287 ContentType = new Microsoft.Teams.Api.ContentType("application/vnd.microsoft.card.adaptive"),
288 Content = dialogCard
289 }
290 };
291
292 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.ContinueTask(taskInfo));
293}
294
295static Microsoft.Teams.Api.TaskModules.Response CreateMixedExampleDialog()
296{
297 var taskInfo = new Microsoft.Teams.Api.TaskModules.TaskInfo
298 {
299 Title = "Mixed Example (C# Sample)",
300 Width = new Union<int, Microsoft.Teams.Api.TaskModules.Size>(800),
301 Height = new Union<int, Microsoft.Teams.Api.TaskModules.Size>(600),
302 Url = "https://teams.microsoft.com/l/task/example-mixed"
303 };
304
305 return new Microsoft.Teams.Api.TaskModules.Response(new Microsoft.Teams.Api.TaskModules.ContinueTask(taskInfo));
306}