microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
3ddf9fa76ec1801a0e3ca312c6d9855879571ac1

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/docs/MigrationGuide.md

387lines · modecode

1# Migration Guide: Libraries/Microsoft.Teams.Apps to core/src/Microsoft.Teams.Apps
2
3This guide covers migrating from the old `Microsoft.Teams.Apps` library (`Libraries/`) to the new `Microsoft.Teams.Apps` library (`core/src/`).
4
5---
6
7## Assembly Mapping
8
9The old library is split across 16 assemblies. The new library consolidates into 3.
10
11### New library assemblies
12
13| New Assembly | Purpose |
14|---|---|
15| `Microsoft.Teams.Core` | Foundation: activity protocol, auth, middleware, HTTP clients |
16| `Microsoft.Teams.Apps` | High-level: handlers, routing, OAuth flows, API clients |
17| `Microsoft.Teams.Apps.BotBuilder` | Backward compat layer for Bot Framework SDK |
18
19### Old assemblies not available in the new library
20
21These assemblies have no equivalent in the new library and must be sourced separately or replaced:
22
23| Old Assembly | Status |
24|---|---|
25| `Microsoft.Teams.AI` | Not available |
26| `Microsoft.Teams.AI.Models.OpenAI` | Not available |
27| `Microsoft.Teams.Cards` | Not available |
28| `Microsoft.Teams.Extensions.Graph` | Not available |
29| `Microsoft.Teams.Plugins.AspNetCore.DevTools` | Not available |
30| `Microsoft.Teams.Plugins.External.Mcp` | Not available — plugin architecture removed |
31| `Microsoft.Teams.Plugins.External.McpClient` | Not available — plugin architecture removed |
32| `Microsoft.Teams.Apps.Testing` | Not available — use standard DI mocking instead of `TestPlugin` |
33
34### Old assemblies replaced by standard .NET
35
36| Old Assembly | Replaced By |
37|---|---|
38| `Microsoft.Teams.Common` (logging) | `Microsoft.Extensions.Logging` |
39| `Microsoft.Teams.Common` (HTTP) | `System.Net.Http.HttpClient` + DI |
40| `Microsoft.Teams.Common` (storage) | No direct replacement — `IStorage<K,V>` removed |
41| `Microsoft.Teams.Extensions.Configuration` | `Microsoft.Extensions.Configuration` via `BotConfig` |
42| `Microsoft.Teams.Extensions.Logging` | `Microsoft.Extensions.Logging` (no bridge needed) |
43| `Microsoft.Teams.Extensions.Hosting` | `TeamsBotApplicationHostingExtensions` |
44| `Microsoft.Teams.Plugins.AspNetCore` | Standard ASP.NET Core middleware + `BotApplication.ProcessAsync()` |
45| `Microsoft.Teams.Plugins.AspNetCore.BotBuilder` | `Microsoft.Teams.Apps.BotBuilder` (compat layer) |
46
47---
48
49## Quick Reference
50
51| Old API | New API | Notes |
52|---------|---------|-------|
53| `builder.AddTeams()` | `builder.AddTeams()` | Now works on both `WebApplicationBuilder` and `IServiceCollection` |
54| `context.Send("text", ct)` | `context.Send("text", ct)` | Same API |
55| `context.Send(activity, ct)` | `context.Send(activity, ct)` | Same API |
56| `context.Reply("text", ct)` | `context.Reply("text", ct)` | Same API |
57| `context.Reply(activity, ct)` | `context.Reply(activity, ct)` | Same API |
58| `context.Typing("text", ct)` | `context.Typing("text", ct)` | Same API |
59| `context.Log.Info(...)` | `context.Log.Info(...)` | Same API, delegates to `ILogger` |
60| `context.Log.Error(...)` | `context.Log.Error(...)` | Same API |
61| `context.Log.Debug(...)` | `context.Log.Debug(...)` | Same API |
62| `context.Log.Warn(...)` | `context.Log.Warn(...)` | Same API |
63| `context.AppId` | `context.AppId` | Same API |
64| `teams.OnMeetingJoin(h)` | `teams.OnMeetingJoin(h)` | Alias for `OnMeetingParticipantJoin` |
65| `teams.OnMeetingLeave(h)` | `teams.OnMeetingLeave(h)` | Alias for `OnMeetingParticipantLeave` |
66| `teams.Send(convId, text)` | `teams.Send(convId, text)` | Proactive messaging |
67| `teams.Reply(convId, msgId, text)` | `teams.Reply(convId, msgId, text)` | Proactive threaded reply |
68| `InvokeResponse(200, body)` | `InvokeResponse.Ok(body)` | Factory method available |
69| `InvokeResponse(400, body)` | `InvokeResponse.Error(400, body)` | Factory method available |
70
71---
72
73## Backward-Compatible Changes (No Migration Needed)
74
75These APIs have been added to the new library to match the old API surface. Existing code using these patterns will work without changes.
76
77### Context Convenience Methods (BC-1)
78
79The following methods are available on `Context<TActivity>`:
80
81```csharp
82// Send a text message
83await context.Send("Hello!", cancellationToken);
84
85// Send an activity
86await context.Send(myActivity, cancellationToken);
87
88// Send a threaded reply
89await context.Reply("This is a reply", cancellationToken);
90await context.Reply(myActivity, cancellationToken);
91
92// Send typing indicator
93await context.Typing(cancellationToken: cancellationToken);
94```
95
96> **Note:** `Send(AdaptiveCard)` and `Reply(AdaptiveCard)` are not yet available to avoid a dependency on `Microsoft.Teams.Cards`. Use `TeamsActivityBuilder` with `AddAdaptiveCardAttachment()` instead.
97
98### Context Logger (BC-2)
99
100`context.Log` provides `.Info()`, `.Error()`, `.Debug()`, and `.Warn()` methods:
101
102```csharp
103context.Log.Info("Processing message");
104context.Log.Error("Something failed", ex.Message);
105context.Log.Debug("Activity ID:", context.Activity.Id);
106```
107
108These delegate to `Microsoft.Extensions.Logging.ILogger` under the hood. The underlying `ILogger` is accessible via `context.Log.Logger` if needed.
109
110### Context AppId (BC-5)
111
112```csharp
113var appId = context.AppId; // reads from TeamsBotApplication.AppId
114```
115
116### WebApplicationBuilder.AddTeams() (BC-7)
117
118Both styles work:
119```csharp
120// Old style (on WebApplicationBuilder)
121builder.AddTeams();
122
123// New style (on IServiceCollection)
124builder.Services.AddTeams();
125```
126
127### Meeting Handler Aliases (BC-10)
128
129Both old and new names work:
130```csharp
131// Old names
132teams.OnMeetingJoin(handler);
133teams.OnMeetingLeave(handler);
134
135// New names (preferred)
136teams.OnMeetingParticipantJoin(handler);
137teams.OnMeetingParticipantLeave(handler);
138```
139
140### Proactive Messaging (BC-8)
141
142```csharp
143// Send proactively to a conversation
144await teams.Send(conversationId, "Hello!", cancellationToken: ct);
145
146// Send a threaded reply proactively
147await teams.Reply(conversationId, messageId, "Replying!", ct);
148```
149
150> **Note:** The service URL is automatically cached from incoming activities. If you need to send proactively before any activity has been received, pass a `serviceUrl` parameter to `Send()`.
151
152### InvokeResponse Factory Methods (BC-12)
153
154```csharp
155// Instead of: new InvokeResponse(200, body)
156return InvokeResponse.Ok(body);
157
158// Typed version
159return InvokeResponse.Ok<TaskModuleResponse>(response);
160
161// Error responses
162return InvokeResponse.Error(400, errorDetails);
163```
164
165### MessageActivity Fluent Methods (BC-15)
166
167Extension methods on `MessageActivity`:
168
169```csharp
170var msg = new MessageActivity("hello")
171 .WithSuggestedActions(actions)
172 .WithAttachmentLayout("carousel")
173 .AddAttachment(attachment1, attachment2);
174```
175
176Available: `WithText()`, `WithSuggestedActions()`, `WithTextFormat()`, `WithAttachmentLayout()`, `AddAttachment()`, `AddStreamFinal()`.
177
178### Activity Entity Methods
179
180Entity getter helpers are exposed via entity-scoped extension methods:
181
182```csharp
183// Retrieve entity collections
184activity.GetMentions(); // IEnumerable<MentionEntity>
185activity.GetQuotedMessages(); // IEnumerable<QuotedReplyEntity> (ExperimentalTeamsQuotedReplies)
186activity.GetSensitivityLabels(); // IEnumerable<SensitiveUsageEntity>
187
188// Retrieve single entities
189activity.GetClientInfo(); // ClientInfoEntity?
190activity.GetCitation(); // CitationEntity?
191activity.GetStreamInfo(); // StreamInfoEntity?
192activity.GetTargetedMessageInfo(); // TargetedMessageInfoEntity? (ExperimentalTeamsTargeted)
193activity.GetProductInfo(); // ProductInfoEntity?
194activity.GetMessageEntity(); // OMessageEntity?
195```
196
197All Get* methods are extension methods defined in the respective entity files (e.g., `GetMentions` is in `MentionEntityExtensions`).
198
199---
200
201### App.Builder() Pattern (BC-6)
202
203`App.Builder()` is supported with `AddOAuth()`:
204
205```csharp
206// This works in both old and new libraries:
207var appBuilder = App.Builder()
208 .AddOAuth("graph");
209builder.AddTeams(appBuilder);
210```
211
212The following `AppBuilder` methods from the old library are **not available** and should use standard ASP.NET DI instead:
213
214| Old AppBuilder Method | New Equivalent |
215|----------------------|----------------|
216| `.AddLogger(new ConsoleLogger(...))` | `builder.Logging.AddConsole()` |
217| `.AddStorage(storage)` | Register via `builder.Services.AddSingleton<IStorage>(...)` |
218| `.AddClient(httpClient)` | Register via `builder.Services.AddHttpClient(...)` |
219| `.AddCredentials(credentials)` | Configure in `appsettings.json` AzureAd section |
220| `.AddPlugin(plugin)` | No equivalent — plugins are not supported in the new library |
221| `.AddCloud(cloud)` | Configure via `appsettings.json` |
222
223---
224
225## Breaking Changes Requiring Migration
226
227### BC-4: `context.Ref` Removed
228
229**Old:**
230```csharp
231var conversationId = context.Ref.Conversation.Id;
232```
233
234**New:**
235```csharp
236var conversationId = context.Activity.Conversation.Id;
237```
238
239The `Ref` property is not available. Use `context.Activity.Conversation` directly — it contains the same data.
240
241---
242
243### BC-9: `OnSignIn` / `OnSignInFailure` Events
244
245**Old:**
246```csharp
247teams.OnSignIn(async (_, @event, cancellationToken) => { ... });
248teams.OnSignInFailure(async (context, cancellationToken) => { ... });
249```
250
251**New:**
252```csharp
253var flow = teams.GetOAuthFlow("graph");
254flow.OnSignInComplete(async (context, token, cancellationToken) => { ... });
255flow.OnSignInFailure(async (context, cancellationToken) => { ... });
256```
257
258Sign-in events are now per-flow callbacks, which is more flexible when using multiple OAuth connections.
259
260---
261
262### BC-13: Activity Namespace Changes
263
264| Old Namespace | New Namespace |
265|---------------|---------------|
266| `Microsoft.Teams.Api.Activities` | `Microsoft.Teams.Apps.Schema` |
267| `MessageActivity` | `MessageActivity` (same name) |
268| `InvokeActivity` | `InvokeActivity` (same name) |
269| `IActivity` | `TeamsActivity` (base class) |
270
271Member access (`.Text`, `.From`, `.Conversation`, `.Value`, etc.) remains the same. Only `using` statements need updating.
272
273---
274
275### BC-17: Activity fluent `With*()` methods moved to builder/extensions
276
277**Old:**
278```csharp
279var activity = new Activity().WithFrom(account).WithConversation(conv);
280```
281
282**New (recommended builder):**
283```csharp
284var activity = new TeamsActivityBuilder()
285 .WithFrom(account)
286 .WithConversation(conv)
287 .Build();
288```
289
290**New (extension methods on `MessageActivity`):**
291```csharp
292var activity = new MessageActivity()
293 .WithFrom(account)
294 .WithConversation(conv)
295 .WithChannelId("msteams");
296```
297
298Most base `With*()` methods are available as extension methods in `MessageActivityExtensions` (for example `WithId`, `WithChannelId`, `WithFrom`, `WithRecipient`, `WithConversation`, `WithServiceUrl`, `WithLocale`, `WithTimestamp`, `WithLocalTimestamp`, `WithData`, and `WithAppId`).
299
300`WithRelatesTo` is still unavailable because there is no `ConversationReference` equivalent in core.
301
302---
303
304### BC-18: Activity conversion methods replaced by factories
305
306**Old:**
307```csharp
308var msg = activity.ToMessage();
309```
310
311**New:**
312```csharp
313var msg = MessageActivity.FromActivity(coreActivity);
314```
315
316---
317
318### BC-21: Type incompatibilities
319
320| Property | Old Type | New Type |
321|---|---|---|
322| `Timestamp`, `LocalTimestamp` | `DateTime?` | `string?` |
323| `ServiceUrl` | `string?` | `Uri?` |
324| `ContentUrl`, `ThumbnailUrl` (Attachment) | `string?` | `Uri?` |
325| Enums (`TextFormat`, `InputHint`, etc.) | Enum types | String constants |
326| `Account` | Custom `Account` class | `ConversationAccount` / `TeamsConversationAccount` |
327
328---
329
330### Hosting and Plugin Architecture
331
332The old plugin-based architecture is entirely removed. This affects:
333
334| Old Pattern | New Equivalent |
335|---|---|
336| `ISenderPlugin` / `IAspNetCorePlugin` | Not available — use `TeamsBotApplication` directly |
337| `AddTeamsPlugin<T>()` | Not available — register services via standard DI |
338| `TeamsService` (IHostedService) | Not needed — lifecycle managed by `BotApplication.ProcessAsync()` |
339| `AddTeamsTokenAuthentication()` | Built into `AddTeamsBotApplication()` via `BotConfig` |
340| `TeamsValidationSettings` | Replaced by `JwtExtensions` + `BotConfig` |
341| `AspNetCorePlugin.Configure()` | Use standard `app.UseAuthentication()` / `app.UseAuthorization()` |
342
343---
344
345### Common library replacements
346
347| Old Type | New Equivalent |
348|---|---|
349| `Microsoft.Teams.Common.Logging.ILogger` | `Microsoft.Extensions.Logging.ILogger` |
350| `Microsoft.Teams.Common.Logging.ConsoleLogger` | `builder.Logging.AddConsole()` |
351| `Microsoft.Teams.Common.Logging.LogLevel` | `Microsoft.Extensions.Logging.LogLevel` |
352| `Microsoft.Teams.Common.Http.IHttpClient` | `System.Net.Http.HttpClient` via DI |
353| `Microsoft.Teams.Common.Http.IHttpClientFactory` | `Microsoft.Extensions.Http.IHttpClientFactory` |
354| `Microsoft.Teams.Common.Http.HttpException` | `System.Net.Http.HttpRequestException` |
355| `Microsoft.Teams.Common.Storage.IStorage<K,V>` | No direct replacement — removed from SDK |
356| `Microsoft.Teams.Common.Storage.LocalStorage<V>` | No direct replacement — use `IMemoryCache` or custom |
357
358---
359
360### Testing
361
362The old `TestPlugin` from `Microsoft.Teams.Apps.Testing` is not available. Use standard .NET testing patterns:
363
364```csharp
365// Old: TestPlugin-based
366var plugin = new TestPlugin();
367var app = App.Builder().AddPlugin(plugin).Build();
368
369// New: Direct instantiation with mocks
370var mockBot = new Mock<TeamsBotApplication>(...);
371var context = new Context<MessageActivity>(mockBot.Object, activity);
372```
373
374---
375
376## Items Under Review
377
378The following items are being evaluated and may change:
379
380- **BC-1 (partial):** `Send(AdaptiveCard)` / `Reply(AdaptiveCard)` — pending Teams.Cards dependency decision
381- **BC-3:** Middleware / `OnActivity` / `Use()` / `Next()` — architecture review needed
382- **BC-11:** `OnSetting()` message extension handler — activity type clarification needed
383- **BC-14:** `AddTab()` — scope of feature TBD
384- **BC-19:** Missing activity types (`TypingActivity`, `EndOfConversationActivity`, `CommandActivity`)
385- **BC-20:** Missing handler registration methods (Tab, Command, Infrastructure, commented-out handlers)
386- **BC-22:** `Conversation.ToThreadedConversationId()` static utility
387- **BC-23:** MessageActivity commented-out properties (`Speak`, `InputHint`, `Summary`, `Importance`, `DeliveryMode`, `Expiration`)
388