Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# Release History

## 1.6.0-beta.1 (Unreleased)
## 1.5.1 (2026-01-28)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
- Support for MicrosoftTeamsAppIdentifier CommunicationIdentifier

## 1.5.0 (2025-08-25)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public CallIntelligenceOptions() { }
public partial class CallInvite
{
public CallInvite(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity, Azure.Communication.PhoneNumberIdentifier callerIdNumber) { }
public CallInvite(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down Expand Up @@ -1627,6 +1628,7 @@ internal TransferCallToParticipantResult() { }
public partial class TransferToParticipantOptions
{
public TransferToParticipantOptions(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity) { }
public TransferToParticipantOptions(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public CallIntelligenceOptions() { }
public partial class CallInvite
{
public CallInvite(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity, Azure.Communication.PhoneNumberIdentifier callerIdNumber) { }
public CallInvite(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down Expand Up @@ -1627,6 +1628,7 @@ internal TransferCallToParticipantResult() { }
public partial class TransferToParticipantOptions
{
public TransferToParticipantOptions(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity) { }
public TransferToParticipantOptions(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public CallIntelligenceOptions() { }
public partial class CallInvite
{
public CallInvite(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public CallInvite(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity, Azure.Communication.PhoneNumberIdentifier callerIdNumber) { }
public CallInvite(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down Expand Up @@ -1626,6 +1627,7 @@ internal TransferCallToParticipantResult() { }
public partial class TransferToParticipantOptions
{
public TransferToParticipantOptions(Azure.Communication.CommunicationUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsAppIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.MicrosoftTeamsUserIdentifier targetIdentity) { }
public TransferToParticipantOptions(Azure.Communication.PhoneNumberIdentifier targetPhoneNumberIdentity) { }
public TransferToParticipantOptions(Azure.Communication.TeamsExtensionUserIdentifier targetIdentity) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Microsoft Azure Communication Call Automation quickstart - https://learn.microsoft.com/azure/communication-services/quickstarts/voice-video-calling/callflows-for-customer-interactions?pivots=programming-language-csharp
</Description>
<AssemblyTitle>Azure Communication CallAutomation Service</AssemblyTitle>
<Version>1.6.0-beta.1</Version>
<Version>1.5.1</Version>
<ApiCompatVersion>1.5.0</ApiCompatVersion>
<!--The ApiCompatVersion is managed automatically and should not generally be modified manually.-->
<PackageTags>Microsoft Azure Communication CallAutomation Service;Microsoft;Azure;Azure Communication Service;Azure Communication CallAutomation Service;Calling;Communication;$(PackageCommonTags)</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ public virtual async Task<Response<TransferCallToParticipantResult>> TransferCal
{
options = new TransferToParticipantOptions(targetParticipant as MicrosoftTeamsUserIdentifier);
}
else if (targetParticipant is MicrosoftTeamsAppIdentifier)
{
options = new TransferToParticipantOptions(targetParticipant as MicrosoftTeamsAppIdentifier);
}
else if (targetParticipant is TeamsExtensionUserIdentifier)
{
options = new TransferToParticipantOptions(targetParticipant as TeamsExtensionUserIdentifier);
}
else
{
throw new ArgumentException("targetParticipant type is invalid.", nameof(targetParticipant));
Expand Down Expand Up @@ -233,6 +241,14 @@ public virtual Response<TransferCallToParticipantResult> TransferCallToParticipa
{
options = new TransferToParticipantOptions(targetParticipant as MicrosoftTeamsUserIdentifier);
}
else if (targetParticipant is MicrosoftTeamsAppIdentifier)
{
options = new TransferToParticipantOptions(targetParticipant as MicrosoftTeamsAppIdentifier);
}
else if (targetParticipant is TeamsExtensionUserIdentifier)
{
options = new TransferToParticipantOptions(targetParticipant as TeamsExtensionUserIdentifier);
}
else
{
throw new ArgumentException("targetParticipant type is invalid.", nameof(targetParticipant));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class CallInvite
/// When the source of the call is a Teams App source, callerIdNumber is not supported and should be null.
/// Sip Headers are supported for PSTN calls only. Voip Headers are not supported.
/// </summary>
/// <param name="targetPhoneNumberIdentity"></param>
/// <param name="callerIdNumber"></param>
/// <param name="targetPhoneNumberIdentity">The phone number identifier of the target participant.</param>
/// <param name="callerIdNumber">The caller ID phone number to be displayed to the target participant.</param>
public CallInvite(PhoneNumberIdentifier targetPhoneNumberIdentity, PhoneNumberIdentifier callerIdNumber)
{
Target = targetPhoneNumberIdentity;
Expand All @@ -28,7 +28,7 @@ public CallInvite(PhoneNumberIdentifier targetPhoneNumberIdentity, PhoneNumberId
/// Creates a new CallInvite object.
/// Sip Headers are not supported. Voip Headers are supported for ACS Users.
/// </summary>
/// <param name="targetIdentity"></param>
/// <param name="targetIdentity">The Communication User identifier of the target participant.</param>
public CallInvite(CommunicationUserIdentifier targetIdentity)
{
Target = targetIdentity;
Expand All @@ -39,7 +39,7 @@ public CallInvite(CommunicationUserIdentifier targetIdentity)
/// Creates a new CallInvite object.
/// Sip Headers are not supported. Voip Headers are supported for Microsoft teams Users.
/// </summary>
/// <param name="targetIdentity"></param>
/// <param name="targetIdentity">The Microsoft Teams User identifier of the target participant.</param>
public CallInvite(MicrosoftTeamsUserIdentifier targetIdentity)
{
Target = targetIdentity;
Expand All @@ -50,13 +50,24 @@ public CallInvite(MicrosoftTeamsUserIdentifier targetIdentity)
/// Creates a new CallInvite object.
/// Sip Headers are not supported. Voip Headers are supported for Microsoft Teams Apps.
/// </summary>
/// <param name="targetIdentity"></param>
/// <param name="targetIdentity">The Teams Extension User identifier of the target participant.</param>
public CallInvite(TeamsExtensionUserIdentifier targetIdentity)
{
Target = targetIdentity;
CustomCallingContext = new CustomCallingContext(sipHeaders: null, voipHeaders: new Dictionary<string, string>());
}

/// <summary>
/// Creates a new CallInvite object.
/// Sip Headers are not supported. Voip Headers are supported for Microsoft Teams Apps.
/// </summary>
/// <param name="targetIdentity">The Microsoft Teams App identifier of the target participant.</param>
public CallInvite(MicrosoftTeamsAppIdentifier targetIdentity)
{
Target = targetIdentity;
CustomCallingContext = new CustomCallingContext(sipHeaders: null, voipHeaders: new Dictionary<string, string>());
}

/// <summary>
/// The target callee.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ public TransferToParticipantOptions(TeamsExtensionUserIdentifier targetIdentity)
CustomCallingContext = new CustomCallingContext(sipHeaders: null, voipHeaders: new Dictionary<string, string>());
}

/// <summary>
/// Creates a new TransferToParticipantOptions object.
/// </summary>
/// <param name="targetIdentity"> The target to transfer the call to. </param>
public TransferToParticipantOptions(MicrosoftTeamsAppIdentifier targetIdentity)
{
Target = targetIdentity;
CustomCallingContext = new CustomCallingContext(sipHeaders: null, voipHeaders: new Dictionary<string, string>());
}

/// <summary>
/// The target callee.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,118 @@ public void CreateCallAsync_404NotFound(CallInvite target, Uri callbackUri)
Assert.AreEqual(ex?.Status, 404);
}

[TestCaseSource(nameof(TestData_CreateCall))]
public void CreateCall_404NotFound(CallInvite target, Uri callbackUri)
[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public async Task CreateCallAsync_MicrosoftTeamsAppIdentifier_201Created(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(201, CreateOrAnswerCallOrGetCallConnectionPayload);

var options = new CreateCallOptions(target, callbackUri);
var response = await callAutomationClient.CreateCallAsync(options).ConfigureAwait(false);
CreateCallResult result = (CreateCallResult)response;
Assert.NotNull(result);
Assert.AreEqual((int)HttpStatusCode.Created, response.GetRawResponse().Status);
verifyCallConnectionProperties(result.CallConnectionProperties);
Assert.Null(response.Value.CallConnectionProperties.MediaStreamingSubscription);
Assert.Null(response.Value.CallConnectionProperties.TranscriptionSubscription);
Assert.AreEqual(CallConnectionId, result.CallConnection.CallConnectionId);

// Verify the target is correctly typed as MicrosoftTeamsAppIdentifier
Assert.IsInstanceOf<MicrosoftTeamsAppIdentifier>(target.Target);
var teamsApp = target.Target as MicrosoftTeamsAppIdentifier;
Assert.IsNotNull(teamsApp);
Assert.AreEqual("testAppId", teamsApp!.AppId);
}

[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public void CreateCall_MicrosoftTeamsAppIdentifier_201Created(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(201, CreateOrAnswerCallOrGetCallConnectionPayload);

var options = new CreateCallOptions(target, callbackUri);
var response = callAutomationClient.CreateCall(options);
CreateCallResult result = (CreateCallResult)response;
Assert.NotNull(result);
Assert.AreEqual((int)HttpStatusCode.Created, response.GetRawResponse().Status);
verifyCallConnectionProperties(result.CallConnectionProperties);
Assert.Null(response.Value.CallConnectionProperties.MediaStreamingSubscription);
Assert.Null(response.Value.CallConnectionProperties.TranscriptionSubscription);
Assert.AreEqual(CallConnectionId, result.CallConnection.CallConnectionId);

// Verify the target is correctly typed as MicrosoftTeamsAppIdentifier
Assert.IsInstanceOf<MicrosoftTeamsAppIdentifier>(target.Target);
var teamsApp = target.Target as MicrosoftTeamsAppIdentifier;
Assert.IsNotNull(teamsApp);
Assert.AreEqual("testAppId", teamsApp!.AppId);
}

[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public async Task CreateCallWithOptionsAsync_MicrosoftTeamsAppIdentifier_201Created(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(201, CreateOrAnswerCallOrGetCallConnectionWithMediaSubscriptionAndTranscriptionPayload);
CreateCallOptions options = new CreateCallOptions(
callInvite: target,
callbackUri: callbackUri)
{
MediaStreamingOptions = _mediaStreamingConfiguration,
TranscriptionOptions = _transcriptionConfiguration,
OperationContext = "teams-app-context"
};

var response = await callAutomationClient.CreateCallAsync(options).ConfigureAwait(false);
CreateCallResult result = (CreateCallResult)response;
Assert.NotNull(result);
Assert.AreEqual((int)HttpStatusCode.Created, response.GetRawResponse().Status);
verifyCallConnectionProperties(result.CallConnectionProperties);
Assert.AreEqual(CallConnectionId, result.CallConnection.CallConnectionId);
Assert.NotNull(response.Value.CallConnectionProperties.MediaStreamingSubscription);
Assert.NotNull(response.Value.CallConnectionProperties.TranscriptionSubscription);

// Verify all optional properties can be set
Assert.AreEqual("teams-app-context", options.OperationContext);
Assert.IsNotNull(options.MediaStreamingOptions);
Assert.IsNotNull(options.TranscriptionOptions);
}

[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public void CreateCallWithOptions_MicrosoftTeamsAppIdentifier_201Created(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(201, CreateOrAnswerCallOrGetCallConnectionWithMediaSubscriptionAndTranscriptionPayload);
CreateCallOptions options = new CreateCallOptions(
callInvite: target,
callbackUri: callbackUri)
{
MediaStreamingOptions = _mediaStreamingConfiguration,
TranscriptionOptions = _transcriptionConfiguration,
OperationContext = "teams-app-context"
};

var response = callAutomationClient.CreateCall(options);
CreateCallResult result = (CreateCallResult)response;
Assert.NotNull(result);
Assert.AreEqual((int)HttpStatusCode.Created, response.GetRawResponse().Status);
verifyCallConnectionProperties(result.CallConnectionProperties);
Assert.AreEqual(CallConnectionId, result.CallConnection.CallConnectionId);
Assert.NotNull(response.Value.CallConnectionProperties.MediaStreamingSubscription);
Assert.NotNull(response.Value.CallConnectionProperties.TranscriptionSubscription);

// Verify all optional properties can be set
Assert.AreEqual("teams-app-context", options.OperationContext);
Assert.IsNotNull(options.MediaStreamingOptions);
Assert.IsNotNull(options.TranscriptionOptions);
}

[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public void CreateCallAsync_MicrosoftTeamsAppIdentifier_404NotFound(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(404);

RequestFailedException? ex = Assert.ThrowsAsync<RequestFailedException>(async () => await callAutomationClient.CreateCallAsync(new CreateCallOptions(target, callbackUri)).ConfigureAwait(false));
Assert.NotNull(ex);
Assert.AreEqual(ex?.Status, 404);
}

[TestCaseSource(nameof(TestData_CreateCall_MicrosoftTeamsApp))]
public void CreateCall_MicrosoftTeamsAppIdentifier_404NotFound(CallInvite target, Uri callbackUri)
{
CallAutomationClient callAutomationClient = CreateMockCallAutomationClient(404);

Expand Down Expand Up @@ -512,6 +622,39 @@ private static void ValidateCallConnectionProperties(CallConnectionProperties pr
};
}

private static IEnumerable<object?[]> TestData_CreateCall_MicrosoftTeamsApp()
{
var callInvite = new CallInvite(new MicrosoftTeamsAppIdentifier("testAppId"));
callInvite.CustomCallingContext.AddVoip("key1", "value1");
return new[]
{
new object?[]
{
callInvite,
new Uri("https://bot.contoso.com/callback")
},
};
}

private static IEnumerable<object?[]> TestData_CreateCall_MicrosoftTeamsAppWithCloud()
{
var callInvitePublic = new CallInvite(new MicrosoftTeamsAppIdentifier("testAppId", CommunicationCloudEnvironment.Public));
callInvitePublic.CustomCallingContext.AddVoip("key1", "value1");

var callInviteDod = new CallInvite(new MicrosoftTeamsAppIdentifier("testAppId", CommunicationCloudEnvironment.Dod));
callInviteDod.CustomCallingContext.AddVoip("key2", "value2");

var callInviteGcch = new CallInvite(new MicrosoftTeamsAppIdentifier("testAppId", CommunicationCloudEnvironment.Gcch));
callInviteGcch.CustomCallingContext.AddVoip("key3", "value3");

return new[]
{
new object?[] { callInvitePublic, new Uri("https://bot.contoso.com/callback") },
new object?[] { callInviteDod, new Uri("https://bot.contoso.com/callback") },
new object?[] { callInviteGcch, new Uri("https://bot.contoso.com/callback") },
};
}

private static IEnumerable<object?[]> TestData_CreateGroupCall()
{
return new[]
Expand Down
Loading