Skip to content

Update quoted replies#389

Open
corinagum wants to merge 7 commits intomainfrom
cg/quoted-replies
Open

Update quoted replies#389
corinagum wants to merge 7 commits intomainfrom
cg/quoted-replies

Conversation

@corinagum
Copy link
Contributor

  • Remove WithReplyToId(), update ToQuoteReply() and mark it [Obsolete]
  • Add QuotedReplyEntity with nested QuotedReplyData (MessageId required, SenderId/SenderName/Preview/Time/IsReplyDeleted/ValidatedMessageReference optional); register in Entity JSON converter
  • Add GetQuotedMessages() on MessageActivity to read inbound quoted reply entities
  • Add AddQuotedReply(messageId, response?) builder on MessageActivity
  • Update Reply() to stamp QuotedReplyEntity + <quoted messageId="..."/> placeholder instead of blockquote HTML; remove ;messageid= stripping from Conversation.Id (redundant - APX normalizes server-side)
  • Add QuoteReply() on context
  • Mark all quoted reply types and methods as [Experimental("ExperimentalTeamsQuotedReplies")]
  • Add context-level unit tests for Reply() and QuoteReply()
  • Add Samples.QuotedReplies sample exercising all APIs

@corinagum corinagum marked this pull request as ready for review March 24, 2026 18:19
Copilot AI review requested due to automatic review settings March 24, 2026 18:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the SDK’s quoted-reply support to use Teams’ modern quotedReply entity + <quoted messageId="..."/> placeholder format, adds APIs for creating/reading quoted replies, and introduces tests + a sample app to exercise the new behavior.

Changes:

  • Introduces QuotedReplyEntity / QuotedReplyData and registers it in the entity JSON converter.
  • Adds GetQuotedMessages() and AddQuotedReply(...) on MessageActivity, and updates Context.Reply(...) plus new Context.QuoteReply(...) helpers to stamp quoted-reply metadata.
  • Adds unit tests and a new Samples.QuotedReplies project demonstrating end-to-end usage.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Tests/Microsoft.Teams.Apps.Tests/Microsoft.Teams.Apps.Tests.csproj Suppresses experimental diagnostic for quoted replies in Apps tests.
Tests/Microsoft.Teams.Apps.Tests/Contexts/ContextQuotedReplyTests.cs Adds context-level tests validating Reply() / QuoteReply() stamping behavior.
Tests/Microsoft.Teams.Api.Tests/Microsoft.Teams.Api.Tests.csproj Suppresses experimental diagnostic for quoted replies in Api tests.
Tests/Microsoft.Teams.Api.Tests/Json/Entities/QuotedReplyEntity.json Adds golden JSON payload for quoted reply entity serialization tests.
Tests/Microsoft.Teams.Api.Tests/Entities/QuotedReplyEntityTests.cs Adds serialization/deserialization and helper API tests for quoted replies.
Samples/Samples.QuotedReplies/appsettings.json Adds sample configuration for the quoted replies demo app.
Samples/Samples.QuotedReplies/Samples.QuotedReplies.csproj Adds new sample project wired to experimental quoted-reply APIs.
Samples/Samples.QuotedReplies/README.md Documents sample commands and quoted-reply usage patterns.
Samples/Samples.QuotedReplies/Properties/launchSettings.TEMPLATE.json Adds launch profile template for the new sample.
Samples/Samples.QuotedReplies/Program.cs Implements demo bot behavior showing read/write quoted replies.
Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs Updates Reply() quoting behavior and adds QuoteReply() context APIs.
Libraries/Microsoft.Teams.Api/Entities/QuotedReplyEntity.cs Adds the new quoted reply entity types.
Libraries/Microsoft.Teams.Api/Entities/Entity.cs Registers quotedReply in entity JSON (de)serialization.
Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs Adds GetQuotedMessages() and AddQuotedReply(...) builder.
Libraries/Microsoft.Teams.Api/Activities/Activity.cs Removes WithReplyToId(), updates ToQuoteReply() and marks it obsolete.
Comments suppressed due to low confidence (1)

Libraries/Microsoft.Teams.Api/Activities/Activity.cs:201

  • WithReplyToId(string) was removed from Activity. If this library has external consumers, removing a public fluent setter is a breaking change; it may be safer to keep the method and mark it [Obsolete] (or provide a compatible alternative) to avoid forcing downstream recompiles/changes.
    public virtual Activity WithId(string value)
    {
        Id = value;
        return this;
    }

    public virtual Activity WithChannelId(ChannelId value)
    {
        ChannelId = value;
        return this;
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +4 to +24
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;

namespace Microsoft.Teams.Api.Entities;

[Experimental("ExperimentalTeamsQuotedReplies")]
public class QuotedReplyEntity : Entity
{
[JsonPropertyName("quotedReply")]
[JsonPropertyOrder(3)]
public QuotedReplyData QuotedReply { get; set; }

public QuotedReplyEntity() : base("quotedReply") { }
}

[Experimental("ExperimentalTeamsQuotedReplies")]
public class QuotedReplyData
{
[JsonPropertyName("messageId")]
public string MessageId { get; set; }

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

QuotedReplyEntity.QuotedReply and QuotedReplyData.MessageId are non-nullable but never initialized (no required, ctor assignment, or nullability). With TreatWarningsAsErrors=True in Libraries/Directory.Build.props, this will fail the build (CS8618). Consider making these required (matching other entities like MentionEntity.Mentioned) or adding constructors that set them, and/or marking them nullable if they’re legitimately optional. Also using System.Diagnostics.CodeAnalysis; is currently unused and will trigger CS8019 under warnings-as-errors.

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +67
/// <summary>
/// send an activity to the conversation as a reply quoting a specific message by ID
/// </summary>
/// <param name="messageId">the id of the message to quote</param>
/// <param name="activity">activity to send</param>
/// <param name="cancellationToken">optional cancellation token</param>
public Task<T> QuoteReply<T>(string messageId, T activity, CancellationToken cancellationToken = default) where T : IActivity;

/// <summary>
/// send a message activity as a reply quoting a specific message by ID
/// </summary>
/// <param name="messageId">the id of the message to quote</param>
/// <param name="text">the text to send</param>
/// <param name="cancellationToken">optional cancellation token</param>
public Task<MessageActivity> QuoteReply(string messageId, string text, CancellationToken cancellationToken = default);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The new QuoteReply(...) APIs call into experimental quoted-replies types internally (suppressed via #pragma), but the methods themselves aren’t marked [Experimental("ExperimentalTeamsQuotedReplies")]. As a result, consumers won’t see the intended experimental/preview warning when using these APIs. Consider annotating the QuoteReply overloads (and any other new public quoted-reply entrypoints) with the Experimental attribute so the preview surface is clearly communicated.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants