microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9dfef728feacaff7db1ea1762d5ccde4d6a434ff

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/src/Microsoft.Bot.Core/Schema/CoreActivity.cs

185lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json;
5using System.Text.Json.Nodes;
6
7namespace Microsoft.Bot.Core.Schema;
8
9/// <summary>
10/// Represents a dictionary for storing extended properties as key-value pairs.
11/// </summary>
12public class ExtendedPropertiesDictionary : Dictionary<string, object?> { }
13
14/// <summary>
15/// Represents a core activity object that encapsulates the data and metadata for a bot interaction.
16/// </summary>
17/// <remarks>
18/// This class provides the foundational structure for bot activities including message exchanges,
19/// conversation updates, and other bot-related events. It supports serialization to and from JSON
20/// and includes extension properties for channel-specific data.
21/// Follows the Activity Protocol Specification: https://github.com/microsoft/Agents/blob/main/specs/activity/protocol-activity.md
22/// </remarks>
23public class CoreActivity(string type = ActivityTypes.Message)
24{
25 /// <summary>
26 /// Gets or sets the type of the activity. See <see cref="ActivityTypes"/> for common values.
27 /// </summary>
28 /// <remarks>
29 /// Common activity types include "message", "conversationUpdate", "contactRelationUpdate", etc.
30 /// </remarks>
31 [JsonPropertyName("type")] public string Type { get; set; } = type;
32 /// <summary>
33 /// Gets or sets the unique identifier for the channel on which this activity is occurring.
34 /// </summary>
35 [JsonPropertyName("channelId")] public string? ChannelId { get; set; }
36 /// <summary>
37 /// Gets or sets the text content of the message.
38 /// </summary>
39 [JsonPropertyName("text")] public string? Text { get; set; }
40 /// <summary>
41 /// Gets or sets the unique identifier for the activity.
42 /// </summary>
43 [JsonPropertyName("id")] public string? Id { get; set; }
44 /// <summary>
45 /// Gets or sets the URL of the service endpoint for this activity.
46 /// </summary>
47 /// <remarks>
48 /// This URL is used to send responses back to the channel.
49 /// </remarks>
50 [JsonPropertyName("serviceUrl")] public Uri? ServiceUrl { get; set; }
51 /// <summary>
52 /// Gets or sets channel-specific data associated with this activity.
53 /// </summary>
54 [JsonPropertyName("channelData")] public ChannelData? ChannelData { get; set; }
55 /// <summary>
56 /// Gets or sets the account that sent this activity.
57 /// </summary>
58 [JsonPropertyName("from")] public ConversationAccount From { get; set; } = new();
59 /// <summary>
60 /// Gets or sets the account that should receive this activity.
61 /// </summary>
62 [JsonPropertyName("recipient")] public ConversationAccount Recipient { get; set; } = new();
63 /// <summary>
64 /// Gets or sets the conversation in which this activity is taking place.
65 /// </summary>
66 [JsonPropertyName("conversation")] public Conversation Conversation { get; set; } = new();
67 /// <summary>
68 /// Gets the collection of entities contained in this activity.
69 /// </summary>
70 /// <remarks>
71 /// Entities are structured objects that represent mentions, places, or other data.
72 /// </remarks>
73 [JsonPropertyName("entities")] public JsonArray? Entities { get; }
74 /// <summary>
75 /// Gets the extension data dictionary for storing additional properties not defined in the schema.
76 /// </summary>
77#pragma warning disable CA2227 // Collection properties should be read only
78 [JsonExtensionData] public ExtendedPropertiesDictionary Properties { get; set; } = [];
79#pragma warning restore CA2227 // Collection properties should be read only
80
81 /// <summary>
82 /// Gets the default JSON serializer options used for serializing and deserializing activities.
83 /// </summary>
84 /// <remarks>
85 /// Uses the source-generated JSON context for AOT-compatible serialization.
86 /// </remarks>
87 public static readonly JsonSerializerOptions DefaultJsonOptions = CoreActivityJsonContext.Default.Options;
88
89 /// <summary>
90 /// Gets the JSON serializer options used for reflection-based serialization of extended activity types.
91 /// </summary>
92 /// <remarks>
93 /// Uses reflection-based serialization to support custom activity types that extend CoreActivity.
94 /// This is used when serializing/deserializing types not registered in the source-generated context.
95 /// </remarks>
96 private static readonly JsonSerializerOptions ReflectionJsonOptions = new()
97 {
98 WriteIndented = true,
99 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
100 PropertyNamingPolicy = JsonNamingPolicy.CamelCase
101 };
102
103 /// <summary>
104 /// Serializes the current activity to a JSON string.
105 /// </summary>
106 /// <returns>A JSON string representation of the activity.</returns>
107 public string ToJson() => JsonSerializer.Serialize(this, CoreActivityJsonContext.Default.CoreActivity);
108
109 /// <summary>
110 /// Serializes the specified activity instance to a JSON string using the default serialization options.
111 /// </summary>
112 /// <remarks>The serialization uses the default JSON options defined by DefaultJsonOptions. The resulting
113 /// JSON reflects the public properties of the activity instance.</remarks>
114 /// <typeparam name="T">The type of the activity to serialize. Must inherit from CoreActivity.</typeparam>
115 /// <param name="instance">The activity instance to serialize. Cannot be null.</param>
116 /// <returns>A JSON string representation of the specified activity instance.</returns>
117 public static string ToJson<T>(T instance) where T : CoreActivity
118 => JsonSerializer.Serialize<T>(instance, ReflectionJsonOptions);
119
120 /// <summary>
121 /// Deserializes a JSON string into a <see cref="CoreActivity"/> object.
122 /// </summary>
123 /// <param name="json">The JSON string to deserialize.</param>
124 /// <returns>A <see cref="CoreActivity"/> instance.</returns>
125 public static CoreActivity FromJsonString(string json)
126 => JsonSerializer.Deserialize(json, CoreActivityJsonContext.Default.CoreActivity)!;
127
128 /// <summary>
129 /// Deserializes the specified JSON string to an object of type T.
130 /// </summary>
131 /// <remarks>The deserialization uses default JSON options defined by the application. If the JSON is
132 /// invalid or does not match the target type, a JsonException may be thrown.</remarks>
133 /// <typeparam name="T">The type of the object to deserialize to. Must be compatible with the JSON structure.</typeparam>
134 /// <param name="json">The JSON string to deserialize. Cannot be null or empty.</param>
135 /// <returns>An instance of type T that represents the deserialized JSON data.</returns>
136 public static T FromJsonString<T>(string json) where T : CoreActivity
137 => JsonSerializer.Deserialize<T>(json, ReflectionJsonOptions)!;
138
139 /// <summary>
140 /// Asynchronously deserializes a JSON stream into a <see cref="CoreActivity"/> object.
141 /// </summary>
142 /// <param name="stream">The stream containing JSON data to deserialize.</param>
143 /// <param name="cancellationToken">A cancellation token to cancel the operation.</param>
144 /// <returns>A task that represents the asynchronous operation. The task result contains the deserialized <see cref="CoreActivity"/> instance, or null if deserialization fails.</returns>
145 public static ValueTask<CoreActivity?> FromJsonStreamAsync(Stream stream, CancellationToken cancellationToken = default)
146 => JsonSerializer.DeserializeAsync(stream, CoreActivityJsonContext.Default.CoreActivity, cancellationToken);
147
148 /// <summary>
149 /// Asynchronously deserializes a JSON value from the specified stream into an instance of type T.
150 /// </summary>
151 /// <remarks>The caller is responsible for managing the lifetime of the provided stream. The method uses
152 /// default JSON serialization options.</remarks>
153 /// <typeparam name="T">The type of the object to deserialize. Must derive from CoreActivity.</typeparam>
154 /// <param name="stream">The stream containing the JSON data to deserialize. The stream must be readable and positioned at the start of
155 /// the JSON content.</param>
156 /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
157 /// <returns>A ValueTask that represents the asynchronous operation. The result contains an instance of type T if
158 /// deserialization is successful; otherwise, null.</returns>
159 public static ValueTask<T?> FromJsonStreamAsync<T>(Stream stream, CancellationToken cancellationToken = default) where T : CoreActivity
160 => JsonSerializer.DeserializeAsync<T>(stream, ReflectionJsonOptions, cancellationToken);
161
162 /// <summary>
163 /// Creates a reply activity based on the current activity.
164 /// </summary>
165 /// <param name="text">The text content for the reply. Defaults to an empty string.</param>
166 /// <returns>A new <see cref="CoreActivity"/> configured as a reply to the current activity.</returns>
167 /// <remarks>
168 /// The reply activity automatically swaps the From and Recipient accounts and preserves
169 /// the conversation context, channel ID, and service URL from the original activity.
170 /// </remarks>
171 public CoreActivity CreateReplyMessageActivity(string text = "")
172 {
173 CoreActivity result = new()
174 {
175 Type = ActivityTypes.Message,
176 ChannelId = ChannelId,
177 ServiceUrl = ServiceUrl,
178 Conversation = Conversation,
179 From = Recipient,
180 Recipient = From,
181 Text = text
182 };
183 return result;
184 }
185}