Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Communication] - PhoneNumberClient - Adding samples for phone number administration #16935

Merged
merged 23 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d36bcf5
Merge pull request #2 from Azure/master
pavelprystinka Nov 9, 2020
4fae158
Merge pull request #3 from Azure/master
pavelprystinka Nov 13, 2020
846cf86
inroduce phone number addministration tests
pavelprystinka Nov 13, 2020
cf56c02
Samples are created
pavelprystinka Nov 18, 2020
9e78df8
Improve sanitization in tests
pavelprystinka Nov 23, 2020
cfeb709
Merge branch 'pavel/feature/communication/administration_tests' into …
pavelprystinka Nov 23, 2020
735dbbe
Improve sanitization in tests
pavelprystinka Nov 23, 2020
a044c2d
Merge branch 'pavel/feature/communication/administration_tests' into …
pavelprystinka Nov 23, 2020
113bb9d
Update test records
pavelprystinka Nov 23, 2020
14f32cb
Ignore phone numbers live test for not playback if INCLUDE_PHONENUMBE…
pavelprystinka Nov 23, 2020
cc41d52
Merge pull request #5 from Azure/master
pavelprystinka Nov 25, 2020
987f4ad
Merge branch 'master' into pavel/feature/communication/administration…
pavelprystinka Nov 26, 2020
1825458
Update readme
pavelprystinka Nov 26, 2020
ac07d86
Update readme
pavelprystinka Nov 26, 2020
2802d98
samples wording update
pavelprystinka Nov 27, 2020
85a63fe
rename test
pavelprystinka Nov 27, 2020
09400df
addressing tests code formatting
pavelprystinka Nov 27, 2020
1430df8
addressing tests code formatting
pavelprystinka Nov 27, 2020
00694d8
add assertion to sample test
pavelprystinka Nov 28, 2020
c727cea
add release phone number method for single number
pavelprystinka Nov 30, 2020
251ce9a
add release phone number method for single number - update api
pavelprystinka Nov 30, 2020
2662c83
address PR comments (sample wording and renames)
pavelprystinka Dec 1, 2020
c3bd4f9
update sample wording and some variable names
pavelprystinka Dec 1, 2020
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
16 changes: 2 additions & 14 deletions sdk/communication/Azure.Communication.Administration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Identity client: 2020-07-20-preview2

Azure Communication Administration is managing tokens and phone numbers for Azure Communication Services.

[Source code][source] | [Package (NuGet)][package] | [Product documentation][product_docs]
[Source code][source] | [Package (NuGet)][package] | [Product documentation][product_docs] | [Samples][source_samples]

## Getting started

Expand Down Expand Up @@ -205,19 +205,6 @@ Console.WriteLine($"ReservationId: {reservationResponse.Value.ReservationId}, St
```C#
var reservationPurchaseOperation = await client.StartPurchaseReservationAsync(reservationId).ConfigureAwait(false);
await reservationPurchaseOperation.WaitForCompletionAsync().ConfigureAwait(false);

// Ensure purchase has completed successfuly
try
{
var reservationStatus = reservationPurchaseOperation.Value;
// ...
}
catch (Exception ex)
{
Console.WriteLine("Purchase failed");
Console.WriteLine(ex.Message);
}

```

### Configure phone number
Expand Down Expand Up @@ -249,6 +236,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m
[azure_sub]: https://azure.microsoft.com/free/
[azure_portal]: https://portal.azure.com
[source]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Administration/src
[source_samples]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/communication/Azure.Communication.Administration/samples
[cla]: https://cla.microsoft.com
[coc]: https://opensource.microsoft.com/codeofconduct/
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ name: Azure Communication Administration samples for .NET
description: Samples for the Azure.Communication.Administration client library
---

# Azure Communication Administration SDK Samples
# Azure Communication Administration SDK samples

Azure Communication Administration is a client library that is used to do operations necessary for using different services offered by Azure Communication Services, such as calling, chat, SMS, PSTN etc.
To get started you will need to have an Azure Subscription. Once you have this you can go into the Azure portal and create Azure Communication Services resource. The page will give you necessary information to be able to use the sample codes here such as connections string, shared access key, etc.

This client library allows to do following operations:
- Generate user tokens that allows the holders to access Azure Communication Services.
- Purchase, configure and release phone numbers.

<!--
You can find samples for each of these functions below.
- [Generate user tokens](https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Administration/samples/Sample1_CommunicationIdentityClient.md)
-->
#### You can find samples for each of these functions below.
- Generate user tokens [synchronously][sample_identity] or [asynchronously][sample_identity_async]
- Manage phone numbers [synchronously][sample_admin] or [asynchronously][sample_admin_async]

<!-- LINKS -->
[sample_identity]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Administration/samples/Sample1_CommunicationIdentityClient.md
[sample_identity_async]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Administration/samples/Sample1_CommunicationIdentityClientAsync.md
[sample_admin]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/communication/Azure.Communication.Administration/samples/Sample2_PhoneNumberAdministrationClient.md
[sample_admin_async]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/communication/Azure.Communication.Administration/samples/Sample2_PhoneNumberAdministrationClientAsync.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# Searching, reserving, purchasing, releasing phone numbers

This sample demonstrates how to search, reserve, purchase and release phone numbers in Azure Communication Services.
To get started, you'll need a URI to an Azure Communication Services. See the [README](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/communication/Azure.Communication.Administration/README.md) for links and instructions.

## Creating a PhoneNumberAdministrationClient

To create a new `PhoneNumberAdministrationClient` you need a connection string to the Azure Communication Services resource that you can get from the Azure Portal once you create a relevant resource.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
To create a new `PhoneNumberAdministrationClient` you need a connection string to the Azure Communication Services resource that you can get from the Azure Portal once you create a relevant resource.
To create a new `PhoneNumberAdministrationClient` you need a connection string to the Azure Communication Services resource that you can get from the Azure Portal once you have created the resource.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


You can set `connectionString` based on an environment variable, a configuration setting, or any way that works for your application.

```C# Snippet:CreatePhoneNumberAdministrationClient
// Get a connection string to our Azure Communication resource.
var connectionString = "<connection_string>";
var client = new PhoneNumberAdministrationClient(connectionString);
```

## Listing all supported countries

In order to acquire a phone number you will need to know if Azure Communication Services are available in particular country. You can do that by retrieving a list of supported countries.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
In order to acquire a phone number you will need to know if Azure Communication Services are available in particular country. You can do that by retrieving a list of supported countries.
In order to acquire a phone number you will need to know if Azure Communication Services are available in a particular country. You can find out by retrieving a list of supported countries.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:GetAllSupportedCountries
var supportedCountries = client.GetAllSupportedCountries(locale);
foreach (var country in supportedCountries)
{
Console.WriteLine($"Supported country code: {country.CountryCode}, name: {country.LocalizedName}");
}
```

## Listing phone plan groups

Phone plan groups come in two types, Geographic and Toll-Free.

```C# Snippet:GetPhonePlanGroups
var phonePlanGroups = client.GetPhonePlanGroups(countryCode, locale);

foreach (var phonePlanGroup in phonePlanGroups)
{
Console.WriteLine($"Plan group: {phonePlanGroup.LocalizedName}, type: {phonePlanGroup.PhoneNumberType}");
}
```

## Listing phone plans

Unlike Toll-Free phone plans, area codes for Geographic Phone Plans are empty. Area codes are found in the Area Codes API.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Unlike Toll-Free phone plans, area codes for Geographic Phone Plans are empty. Area codes are found in the Area Codes API.
Unlike Toll-Free phone plans, area codes for Geographic phone plans are empty. Area codes are found in the Area Codes API.


```C# Snippet:GetPhonePlans
var phonePlans = client.GetPhonePlans(countryCode, phonePlanGroupId, locale);
foreach (var phonePlan in phonePlans)
{
Console.WriteLine($"Plan: {phonePlan.LocalizedName}, {phonePlan.LocationType}");
}
```

## Get location options

For Geographic phone plans, you can query the available geographic locations. The locations options are structured like the geographic hierarchy of a country. For example, the US has states and within each state are cities.

```C# Snippet:GetPhonePlanLocationOptions
var locationOptionsResponse = client.GetPhonePlanLocationOptions(countryCode, geographicPhonePlanGroup.PhonePlanGroupId, phonePlanId);

void printLocationOption(LocationOptions locationOptions)
{
Console.WriteLine($"LabelId: {locationOptions.LabelId}, LabelName: {locationOptions.LabelName}");

foreach (var locationOption in locationOptions.Options)
{
Console.WriteLine($"Name: {locationOption.Name}, Value: {locationOption.Value}");

foreach (var subLocationOption in locationOption.LocationOptions)
printLocationOption(subLocationOption);
}
}
printLocationOption(locationOptionsResponse.Value.LocationOptions);
```

## Get area codes

Fetching area codes for geographic phone plans will require the the location options queries set. You must include the chain of geographic locations traversing down the location options object returned by the GetPhonePlanLocationOptions.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Fetching area codes for geographic phone plans will require the the location options queries set. You must include the chain of geographic locations traversing down the location options object returned by the GetPhonePlanLocationOptions.
Fetching area codes for geographic phone plans will require the location options queries set. You must include the chain of geographic locations traversing down the location options object returned by the GetPhonePlanLocationOptions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:GeographicalAreaCodes
var locationOptionsResponse = client.GetPhonePlanLocationOptions(countryCode, geographicPhonePlanGroupId, geographicPhonePlanId);
var state = locationOptionsResponse.Value.LocationOptions.Options.First();

var locationOptionsQueries = new List<LocationOptionsQuery>{
new LocationOptionsQuery
{
LabelId = "state",
OptionsValue = state.Value
},
new LocationOptionsQuery
{
LabelId = "city",
OptionsValue = state.LocationOptions.First().Options.First().Value
}
};

var areaCodes = client.GetAllAreaCodes(geographicPhonePlan.LocationType.ToString(), countryCode, geographicPhonePlan.PhonePlanId, locationOptionsQueries);

foreach (var areaCode in areaCodes.Value.PrimaryAreaCodes)
{
Console.WriteLine($"Primary area code: {areaCode}");
}
```

Area codes for toll free phone plans can be found in the plan.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Area codes for toll free phone plans can be found in the plan.
Area codes for toll-free phone plans can be found in the plan.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:TollFreePlanAreCodes
Copy link
Member

Choose a reason for hiding this comment

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

nit: spelling in region and snippet title

Suggested change
```C# Snippet:TollFreePlanAreCodes
```C# Snippet:TollFreePlanAreaCodes

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

var phonePlans = client.GetPhonePlans(countryCode, tollFreePhonePlanGroupId, locale);
var tollFreePhonePlan = phonePlans.First();

foreach (var areaCode in tollFreePhonePlan.AreaCodes)
{
Console.WriteLine($"Area code: {areaCode}");
}
```

## Reserve phone numbers

Phone numbers need to be reserved for purchase. Reservation is a long running operation that can be started by CreateReservationOptions function that returns an PhoneNumberReservationOperation object. PhoneNumberReservationOperation can be used to update status of the operation and to check for completeness.
Copy link
Member

Choose a reason for hiding this comment

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

Let's go through the file and `` format all references to code where we use the literal name of a type or method. Just fixing one sentence here as an example.

Suggested change
Phone numbers need to be reserved for purchase. Reservation is a long running operation that can be started by CreateReservationOptions function that returns an PhoneNumberReservationOperation object. PhoneNumberReservationOperation can be used to update status of the operation and to check for completeness.
Phone numbers need to be reserved before they can be purchased. Reservation is a long running operation that can be started by `CreateReservationOptions` function that returns an `PhoneNumberReservationOperation` object. `PhoneNumberReservationOperation` can be used to update status of the operation and to check for completeness.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:ReservePhoneNumbers
var reservationName = "My reservation";
var reservationDescription = "reservation description";
var reservationOptions = new CreateReservationOptions(reservationName, reservationDescription, new[] { phonePlanId }, areaCode);
reservationOptions.Quantity = 1;

var reservationOperation = client.StartReservation(reservationOptions);

while (true)
Copy link
Member

Choose a reason for hiding this comment

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

Why are we manually polling here and not using WaitForCompletionAsync?

If we give the while loop and Thread.Sleep as an example snippet, developers will copy and it and think that's the default way how to do reservations. Let's change the snippet to wait on the operation instead.

Copy link
Member

Choose a reason for hiding this comment

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

Saw the other comment thread below just now, let's see what Christopher says.

{
reservationOperation.UpdateStatus();
if (reservationOperation.HasCompleted)
{
break;
}

Thread.Sleep(1000);
}
```

## Persist reserve phone numbers operation

You can persist phone number reservation operation Id so that you can get back later to check operation status.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
You can persist phone number reservation operation Id so that you can get back later to check operation status.
You can persist the operation Id of the phone number reservation so that you can come back and check the operation status later.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:PersistReservePhoneNumbersOperation
var reservationId = reservationOperation.Id;

// persist reservationOperationId and then continue with new operation

var newPhoneNumberReservationOperation = new PhoneNumberReservationOperation(client, reservationId);
Copy link
Member

Choose a reason for hiding this comment

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

Can we shorten the name? Maybe just operation or reserveOperation.

The context makes it clear what the operation is about and it can't be confused with another operation, that's why I think a short and less precise name reads better.

Copy link
Member

Choose a reason for hiding this comment

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

+1 on reserveOperation

Copy link
Member Author

Choose a reason for hiding this comment

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

I made it newReserveOperation to stress that is a new object created with reservationId
Also there is reserveOperation variable in the same test where code snippet is coming

Copy link
Member

Choose a reason for hiding this comment

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

Usually one would only prefix variable names with new if they are a new replacement for something existing, for example an event handler with newValue. Otherwise every variable that holds a constructed object would start with new. In general, we're preferring short names over encoding types in the name, which is a practice that comes from Hungarian notation among others and is now discouraged.

To avoid a name clash with the other reserveOperation you can extract a function to have a new context.

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed it to reserveOperation


while (true)
{
newPhoneNumberReservationOperation.UpdateStatus();
if (newPhoneNumberReservationOperation.HasCompleted)
{
break;
}

Thread.Sleep(1000);
Copy link
Member

Choose a reason for hiding this comment

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

@christothes is there a better recommended way to have sync tests for long running operations?

Copy link
Member Author

Choose a reason for hiding this comment

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

@christothes @RezaJooyandeh just a reminder that this test code is copied over MD sample file

Copy link
Member

Choose a reason for hiding this comment

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

Let's follow how KeyVault has written the code. https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/keyvault/Azure.Security.KeyVault.Keys/samples/Sample1_HelloWorld.md#purging-a-deleted-key

while (!newPhoneNumberReservationOperation.HasCompleted)
{
    Thread.Sleep(2000);

    operation.UpdateStatus();
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

}
```

## Purchase phone numbers

Phone numbers can be acquired by purchasing reservation.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Phone numbers can be acquired by purchasing reservation.
Phone numbers can be acquired through purchasing a reservation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


```C# Snippet:StartPurchaseReservation
var reservationPurchaseOperation = client.StartPurchaseReservation(reservationId);
Copy link
Member

Choose a reason for hiding this comment

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

We can shorten this to purchaseOperation

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


while (true)
{
reservationPurchaseOperation.UpdateStatus();
if (reservationPurchaseOperation.HasCompleted)
{
break;
}

Thread.Sleep(1000);
}
```

## Listing acquired phone numbers

DominikMe marked this conversation as resolved.
Show resolved Hide resolved
```C# Snippet:ListAcquiredPhoneNumbers
var acquiredPhoneNumbers = client.GetAllPhoneNumbers(locale);

foreach (var phoneNumber in acquiredPhoneNumbers)
{
Console.WriteLine($"Phone number: {phoneNumber.PhoneNumber}, activation state: {phoneNumber.ActivationState}");
}
```

## Release phone numbers

If you no longer need a phone number you can release it.

```C# Snippet:ReleasePhoneNumbers
var acquiredPhoneNumber = "<acquired_phone_number>";
var phoneNumbers = new List<PhoneNumber> { new PhoneNumber(acquiredPhoneNumber) };
var phoneNumberReleaseOperation = client.StartReleasePhoneNumbers(phoneNumbers);

while (true)
{
phoneNumberReleaseOperation.UpdateStatus();
if (phoneNumberReleaseOperation.HasCompleted)
{
break;
}

Thread.Sleep(1000);
}
```
Loading