microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
pr-134

Branches

Tags

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

Clone

HTTPS

Download ZIP

Samples/Samples.Dialogs/Program.cs

386lines · modeblame

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