Skip to content

Conversation

@rido-min
Copy link
Member

This pull request refactors how sender (From) and recipient (Recipient) accounts are handled throughout the Teams Bot SDK, making them nullable and updating related code to handle null values safely. It also updates builder methods and tests to reflect these changes, and improves robustness by removing unnecessary null checks and updating collection initialization logic.

The most important changes are:

Core SDK and Schema Updates:

  • Made From and Recipient properties nullable in CoreActivity, TeamsActivity, and related classes, and updated their usage throughout the codebase to handle null values safely. This includes replacing direct property access with null-safe navigation and updating serialization/deserialization logic. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

  • Updated builder methods (WithFrom, WithChannelData, etc.) to accept nullable arguments and only set properties if the value is not null. Also removed unnecessary null checks for properties that are now allowed to be null. [1] [2] [3]

Collection Handling:

  • Changed collection factory methods (EntityList.FromJsonArray, TeamsAttachment.FromJArray) to return null instead of empty collections when the input is null, aligning with the new nullable approach. [1] [2]

Test Suite Updates:

  • Updated unit tests to reflect the new nullable behavior for From and Recipient, ensuring tests check for null as appropriate and updating test names and assertions for clarity and correctness. [1] [2] [3] [4] [5] [6] [7] [8]

Payload and Serialization Improvements:

  • Ensured that ServiceUrl is not serialized in outgoing payloads by explicitly setting it to null before serialization in SendActivityAsync.

Configuration:

  • Added a local settings file (core/.claude/settings.local.json) to specify permissions for running certain dotnet CLI commands.

rido-min and others added 4 commits January 23, 2026 08:42
This pull request refactors the `CompatAdapter` and related middleware
to use dependency injection for service resolution, improving
maintainability and aligning with modern .NET practices. The main
changes involve replacing constructor parameters with
`IServiceProvider`, updating middleware to resolve dependencies, and
enhancing logging in the `CompatBotAdapter`.

**Dependency Injection Refactoring:**

* `CompatAdapter` now receives an `IServiceProvider` in its constructor,
and uses it to resolve `TeamsBotApplication` and `CompatBotAdapter`
instead of receiving them directly as parameters. All usages of these
services within the class have been updated accordingly.
* `CompatAdapterMiddleware` now receives both the Bot Framework
middleware and an `IServiceProvider`, enabling it to resolve required
services such as `IHttpContextAccessor` and `ILogger`.

**Middleware and Adapter Updates:**

* Middleware instantiation in `CompatAdapter` is updated to pass the
`IServiceProvider` to each `CompatAdapterMiddleware`, ensuring
dependencies are available during middleware execution.
* Within `CompatAdapterMiddleware`, the `CompatBotAdapter` is now
constructed with resolved `IHttpContextAccessor` and `ILogger`
instances, improving logging and context-awareness.

**Logging Improvements:**

* Enhanced logging in `CompatBotAdapter` to include HTTP status codes
when sending invoke responses, and to avoid serialization if the
response body is null.

**General Code Modernization:**

* Added missing `using` statements for dependency injection and logging
namespaces in affected files.
[[1]](diffhunk://#diff-e6d701ce121dda6651c0dea00498d45e2cc0b0cec446a578f3058be691c7c0f5R8)
[[2]](diffhunk://#diff-80a974c881b9ff3a697fe5b07985c8f55edb2e2896384d6d437a3e8dfa5a2817R5-R6)
The CompatMiddlware Adapter was creating a new TurnContext, and that
created problems with Middleware.

Instead of trying to adapt the middlware, we can just run the BF
Middleware pipeline
Enhance null handling for From/Recipient properties in activities and related classes. Make these properties nullable, add null checks before assignment, and update method calls to use null-conditional operators. Adjust JSON array deserialization to return null instead of empty lists when input is null. These changes increase robustness when handling incomplete or missing activity data.
- Update CoreActivityBuilder and TeamsActivityBuilder to set From to Recipient and leave Recipient null when From is missing in WithConversationReference.
- Remove default assertions that From/Recipient are non-null in builder tests; add explicit null checks where needed.
- WithConversationReference no longer throws for null ChannelId; throws for null Recipient.
- WithChannelData(null) no longer overwrites existing ChannelData.
- Add null-conditional access for ca.From?.Properties in EchoBot.
- Explicitly set Recipient in test activities to prevent null reference errors.
- Add settings.local.json with Bash command permissions.
Copy link
Collaborator

@singhk97 singhk97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a few comments the understand implication of this

WithChannelId(activity.ChannelId);
SetConversation(activity.Conversation);
SetFrom(activity.Recipient);
SetRecipient(activity.From);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the main motivation behind these changes? If activity.From is set shouldn't it be mapped?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APX does not require the Recipient, so I was thinking of using it only for TM

string convId = conversationId.Length > 325 ? conversationId[..325] : conversationId;
url = $"{activity.ServiceUrl.ToString().TrimEnd('/')}/v3/conversations/{convId}/activities";
}
activity.ServiceUrl = null; // do not serialize in the outgoing payload
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doing this means it will always be null and not overridable by the end user. What's the tradeoff here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means that we do not serialize the ServiceURL when sending the response to APX

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants