diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ComponentSamples.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ComponentSamples.cs index 6984db5e0ae92..63a47a116a288 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ComponentSamples.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ComponentSamples.cs @@ -51,7 +51,7 @@ public async Task RunSamplesAsync() await DigitalTwinsClient.CreateDigitalTwinAsync(twinId, twinPayload).ConfigureAwait(false); Console.WriteLine($"Created digital twin {twinId}."); - #region Snippet:DigitalTwinSampleUpdateComponent + #region Snippet:DigitalTwinsSampleUpdateComponent // Update Component with replacing property value string propertyPath = "/ComponentProp1"; @@ -62,17 +62,17 @@ public async Task RunSamplesAsync() Response response = await DigitalTwinsClient.UpdateComponentAsync(twinId, SamplesConstants.ComponentPath, componentUpdateUtility.Serialize()); - #endregion Snippet:DigitalTwinSampleUpdateComponent + #endregion Snippet:DigitalTwinsSampleUpdateComponent Console.WriteLine($"Updated component for digital twin {twinId}. Update response status: {response.GetRawResponse().Status}"); // Get Component - #region Snippet:DigitalTwinSampleGetComponent + #region Snippet:DigitalTwinsSampleGetComponent response = await DigitalTwinsClient.GetComponentAsync(twinId, SamplesConstants.ComponentPath).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleGetComponent + #endregion Snippet:DigitalTwinsSampleGetComponent Console.WriteLine($"Get component for digital twin: \n{response.Value}. Get response status: {response.GetRawResponse().Status}"); diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DigitalTwinsLifecycleSamples.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DigitalTwinsLifecycleSamples.cs index 9202695873592..3814ed0b35bb5 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DigitalTwinsLifecycleSamples.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DigitalTwinsLifecycleSamples.cs @@ -172,7 +172,7 @@ public async Task GetAllModelsAsync() { // Get all the twin types - #region Snippet:DigitalTwinSampleGetModels + #region Snippet:DigitalTwinsSampleGetModels AsyncPageable allModels = DigitalTwinsClient.GetModelsAsync(); await foreach (ModelData model in allModels) @@ -180,7 +180,7 @@ public async Task GetAllModelsAsync() Console.WriteLine($"Model Id: {model.Id}, display name: {model.DisplayName["en"]}, upload time: {model.UploadTime}, is decommissioned: {model.Decommissioned}"); } - #endregion Snippet:DigitalTwinSampleGetModels + #endregion Snippet:DigitalTwinsSampleGetModels } catch (Exception ex) { @@ -202,11 +202,11 @@ public async Task DeleteTwinsAsync() { // Delete all relationships - #region Snippet:DigitalTwinSampleGetRelationships + #region Snippet:DigitalTwinsSampleGetRelationships AsyncPageable relationships = DigitalTwinsClient.GetRelationshipsAsync(twin.Key); - #endregion Snippet:DigitalTwinSampleGetRelationships + #endregion Snippet:DigitalTwinsSampleGetRelationships await foreach (var relationshipJson in relationships) { @@ -217,11 +217,11 @@ public async Task DeleteTwinsAsync() // Delete any incoming relationships - #region Snippet:DigitalTwinSampleGetIncomingRelationships + #region Snippet:DigitalTwinsSampleGetIncomingRelationships AsyncPageable incomingRelationships = DigitalTwinsClient.GetIncomingRelationshipsAsync(twin.Key); - #endregion Snippet:DigitalTwinSampleGetIncomingRelationships + #endregion Snippet:DigitalTwinsSampleGetIncomingRelationships await foreach (IncomingRelationship incomingRelationship in incomingRelationships) { @@ -231,11 +231,11 @@ public async Task DeleteTwinsAsync() // Now the digital twin should be safe to delete - #region Snippet:DigitalTwinSampleDeleteTwin + #region Snippet:DigitalTwinsSampleDeleteTwin await DigitalTwinsClient.DeleteDigitalTwinAsync(twin.Key).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleDeleteTwin + #endregion Snippet:DigitalTwinsSampleDeleteTwin Console.WriteLine($"Deleted digital twin {twin.Key}"); } @@ -263,11 +263,11 @@ public async Task CreateAllTwinsAsync() { try { - #region Snippet:DigitalTwinSampleCreateTwin + #region Snippet:DigitalTwinsSampleCreateTwin Response response = await DigitalTwinsClient.CreateDigitalTwinAsync(twin.Key, twin.Value).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleCreateTwin + #endregion Snippet:DigitalTwinsSampleCreateTwin Console.WriteLine($"Created digital twin {twin.Key}. Create response status: {response.GetRawResponse().Status}"); Console.WriteLine($"Body: {response?.Value}"); @@ -287,7 +287,7 @@ public async Task QueryTwinsAsync() { Console.WriteLine("Making a twin query and iterating over the results."); - #region Snippet:DigitalTwinSampleQueryTwins + #region Snippet:DigitalTwinsSampleQueryTwins // This code snippet demonstrates the simplest way to iterate over the digital twin results, where paging // happens under the covers. @@ -302,11 +302,11 @@ public async Task QueryTwinsAsync() Console.WriteLine($"Found digital twin: {twin.Id}"); } - #endregion Snippet:DigitalTwinSampleQueryTwins + #endregion Snippet:DigitalTwinsSampleQueryTwins Console.WriteLine("Making a twin query, with query-charge header extraction."); - #region Snippet:DigitalTwinSampleQueryTwinsWithQueryCharge + #region Snippet:DigitalTwinsSampleQueryTwinsWithQueryCharge // This code snippet demonstrates how you could extract the query charges incurred when calling // the query API. It iterates over the response pages first to access to the query-charge header, @@ -335,7 +335,7 @@ public async Task QueryTwinsAsync() } } - #endregion Snippet:DigitalTwinSampleQueryTwinsWithQueryCharge + #endregion Snippet:DigitalTwinsSampleQueryTwinsWithQueryCharge } catch (Exception ex) { @@ -363,7 +363,7 @@ public async Task ConnectTwinsTogetherAsync() { try { - #region Snippet:DigitalTwinSampleCreateRelationship + #region Snippet:DigitalTwinsSampleCreateRelationship string serializedRelationship = JsonSerializer.Serialize(relationship); @@ -374,7 +374,7 @@ await DigitalTwinsClient serializedRelationship) .ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleCreateRelationship + #endregion Snippet:DigitalTwinsSampleCreateRelationship Console.WriteLine($"Linked {serializedRelationship}"); } @@ -394,7 +394,7 @@ public async Task GetEventRoutes() PrintHeader("LISTING EVENT ROUTES"); try { - #region Snippet:DigitalTwinSampleGetEventRoutes + #region Snippet:DigitalTwinsSampleGetEventRoutes AsyncPageable response = DigitalTwinsClient.GetEventRoutesAsync(); await foreach (EventRoute er in response) @@ -402,7 +402,7 @@ public async Task GetEventRoutes() Console.WriteLine($"Event route: {er.Id}, endpoint name: {er.EndpointName}"); } - #endregion Snippet:DigitalTwinSampleGetEventRoutes + #endregion Snippet:DigitalTwinsSampleGetEventRoutes } catch (Exception ex) { @@ -418,7 +418,7 @@ public async Task CreateEventRoute() PrintHeader("CREATE EVENT ROUTE"); try { - #region Snippet:DigitalTwinSampleCreateEventRoute + #region Snippet:DigitalTwinsSampleCreateEventRoute string eventFilter = "$eventType = 'DigitalTwinTelemetryMessages' or $eventType = 'DigitalTwinLifecycleNotification'"; var eventRoute = new EventRoute(_eventhubEndpointName) @@ -428,7 +428,7 @@ public async Task CreateEventRoute() Response createEventRouteResponse = await DigitalTwinsClient.CreateEventRouteAsync(_eventRouteId, eventRoute).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleCreateEventRoute + #endregion Snippet:DigitalTwinsSampleCreateEventRoute Console.WriteLine($"Created event route: {_eventRouteId} Response status: {createEventRouteResponse.Status}"); } @@ -446,11 +446,11 @@ public async Task DeleteEventRoute() PrintHeader("DELETING EVENT ROUTE"); try { - #region Snippet:DigitalTwinSampleDeleteEventRoute + #region Snippet:DigitalTwinsSampleDeleteEventRoute Response response = await DigitalTwinsClient.DeleteEventRouteAsync(_eventRouteId).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleDeleteEventRoute + #endregion Snippet:DigitalTwinsSampleDeleteEventRoute Console.WriteLine($"Successfully deleted event route: {_eventRouteId}, status: {response.Status}"); } diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ModelLifecycleSamples.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ModelLifecycleSamples.cs index 56b08dad8a4b1..f84f7cb7e4bfd 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ModelLifecycleSamples.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/ModelLifecycleSamples.cs @@ -47,12 +47,12 @@ public async Task RunSamplesAsync() try { - #region Snippet:DigitalTwinSampleCreateModels + #region Snippet:DigitalTwinsSampleCreateModels Response> response = await DigitalTwinsClient.CreateModelsAsync(new[] { newComponentModelPayload, newModelPayload }).ConfigureAwait(false); Console.WriteLine($"Successfully created a model with Id: {newComponentModelId}, {sampleModelId}, status: {response.GetRawResponse().Status}"); - #endregion Snippet:DigitalTwinSampleCreateModels + #endregion Snippet:DigitalTwinsSampleCreateModels } catch (RequestFailedException ex) when (ex.Status == (int)HttpStatusCode.Conflict) { @@ -66,11 +66,11 @@ public async Task RunSamplesAsync() // Get Model try { - #region Snippet:DigitalTwinSampleGetModel + #region Snippet:DigitalTwinsSampleGetModel Response sampleModel = await DigitalTwinsClient.GetModelAsync(sampleModelId).ConfigureAwait(false); - #endregion Snippet:DigitalTwinSampleGetModel + #endregion Snippet:DigitalTwinsSampleGetModel Console.WriteLine($"{sampleModel.Value.Id} has decommission status of {sampleModel.Value.Decommissioned}"); } @@ -81,7 +81,7 @@ public async Task RunSamplesAsync() // Now we decommission the model - #region Snippet:DigitalTwinSampleDecommisionModel + #region Snippet:DigitalTwinsSampleDecommisionModel try { @@ -94,11 +94,11 @@ public async Task RunSamplesAsync() FatalError($"Failed to decommision model {sampleModelId} due to:\n{ex}"); } - #endregion Snippet:DigitalTwinSampleDecommisionModel + #endregion Snippet:DigitalTwinsSampleDecommisionModel // Now delete created model - #region Snippet:DigitalTwinSampleDeleteModel + #region Snippet:DigitalTwinsSampleDeleteModel try { @@ -111,7 +111,7 @@ public async Task RunSamplesAsync() FatalError($"Failed to delete model {sampleModelId} due to:\n{ex}"); } - #endregion Snippet:DigitalTwinSampleDeleteModel + #endregion Snippet:DigitalTwinsSampleDeleteModel } } } diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Options.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Options.cs index a596f98d80e60..5f3dafe64c069 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Options.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Options.cs @@ -2,57 +2,44 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using CommandLine; namespace Azure.DigitalTwins.Core.Samples { + internal enum LoginMethod + { + AppId, + User, + }; + public class Options { - public Options(string adtEndpoint, string clientId, string tenantId, string clientSecret, string eventHubName) - { - AdtEndpoint = adtEndpoint; - ClientId = clientId; - TenantId = tenantId; - ClientSecret = clientSecret; - EventHubName = eventHubName; - } + [Option('a', "adtEndpoint", Required = true, HelpText = "Digital twins service endpoint")] + public string AdtEndpoint { get; set; } - [Option("adtEndpoint", Required = true, HelpText = "Digital twins service endpoint")] - public string AdtEndpoint { get; } + [Option('i', "clientId", Required = true, HelpText = "Client Id of the application Id to login, or the application Id used to log the user in.")] + public string ClientId { get; set; } - [Option("clientId", Required = true, HelpText = "Application client Id")] - public string ClientId { get; } + [Option('m', "loginMethod", Required = false, Default = "AppId", HelpText = "Choose between: AppId, User.")] + public string LoginMethod { get; set; } - [Option("tenantId", Required = true, HelpText = "Application tenant Id")] - public string TenantId { get; } + [Option('t', "tenantId", Required = true, HelpText = "Application tenant Id")] + public string TenantId { get; set; } - [Option("clientSecret", Required = true, HelpText = "Application client secret")] - public string ClientSecret { get; } + [Option('s', "clientSecret", Required = false, HelpText = "Application client secret. Only applicable when using LoginMethod of AppId.")] + public string ClientSecret { get; set; } - [Option("eventHubName", Required = true, HelpText = "Event Hub Name linked to digital twins instance")] - public string EventHubName { get; } + [Option('e', "eventHubName", Required = true, HelpText = "Event Hub Name linked to digital twins instance")] + public string EventHubName { get; set; } - public static void HandleParseError(IEnumerable errors) + internal LoginMethod GetLoginMethod() { - if (errors.IsVersion()) - { - Console.WriteLine("1.0.0"); - return; - } - - if (errors.IsHelp()) + if (Enum.TryParse(LoginMethod, out LoginMethod loginMethod)) { - Console.WriteLine("Usage: .\\DigitalTwinServiceClientSample.exe " + - "--adtEndpoint " + - "--clientId " + - "--tenantId " + - "--clientSecret " + - "--eventHubName "); - return; + return loginMethod; } - Console.WriteLine("Parser Fail"); + return Samples.LoginMethod.AppId; } } } diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Program.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Program.cs index 4502ccebc464c..149e314aa2c28 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Program.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/Program.cs @@ -8,6 +8,7 @@ using Azure.DigitalTwins.Samples; using Azure.Identity; using CommandLine; +using CommandLine.Text; namespace Azure.DigitalTwins.Core.Samples { @@ -20,16 +21,40 @@ public static async Task Main(string[] args) { Options options = null; ParserResult result = Parser.Default.ParseArguments(args) - .WithParsed(parsedOptions => { options = parsedOptions; }) - .WithNotParsed(errors => Options.HandleParseError(errors)); + .WithParsed(parsedOptions => + { + options = parsedOptions; + }) + .WithNotParsed(errors => + { + Environment.Exit(1); + }); + + if (options.GetLoginMethod() == LoginMethod.AppId + && string.IsNullOrWhiteSpace(options.ClientSecret)) + { + Console.Error.WriteLine("When LoginMethod is AppId, ClientSecret parameter is required."); + Console.Error.WriteLine(HelpText.AutoBuild(result, null, null)); + Environment.Exit(1); + } var httpClient = new HttpClient(); - DigitalTwinsClient dtClient = GetDigitalTwinsClient( - options.TenantId, - options.ClientId, - options.ClientSecret, - options.AdtEndpoint, - httpClient); + DigitalTwinsClient dtClient = (options.GetLoginMethod()) switch + { + LoginMethod.AppId => GetDigitalTwinsClient( + options.TenantId, + options.ClientId, + options.ClientSecret, + options.AdtEndpoint), + + LoginMethod.User => GetDigitalTwinsClient( + options.TenantId, + options.ClientId, + options.AdtEndpoint, + httpClient), + + _ => throw new Exception("Unsupported login method"), + }; var dtLifecycleSamples = new DigitalTwinsLifecycleSamples(dtClient, options.EventHubName); await dtLifecycleSamples.RunSamplesAsync().ConfigureAwait(false); @@ -44,8 +69,8 @@ public static async Task Main(string[] args) } /// - /// Illustrates how to construct a with the fewest required parameters, - /// using the implementation of . + /// Illustrates how to construct a , using the + /// implementation of . /// /// The Id of the tenant of the application Id. /// The application Id. @@ -53,9 +78,11 @@ public static async Task Main(string[] args) /// The endpoint of the digital twins instance. private static DigitalTwinsClient GetDigitalTwinsClient(string tenantId, string clientId, string clientSecret, string adtEndpoint) { - #region Snippet:DigitalTwinSampleCreateServiceClient + #region Snippet:DigitalTwinsSampleCreateServiceClientWithClientSecret - var clientSecretCredential = new ClientSecretCredential( + // By using the ClientSecretCredential, a specified application Id can login using a + // client secret. + var tokenCredential = new ClientSecretCredential( tenantId, clientId, clientSecret, @@ -63,46 +90,45 @@ private static DigitalTwinsClient GetDigitalTwinsClient(string tenantId, string var dtClient = new DigitalTwinsClient( new Uri(adtEndpoint), - clientSecretCredential); + tokenCredential); - #endregion Snippet:DigitalTwinSampleCreateServiceClient + #endregion Snippet:DigitalTwinsSampleCreateServiceClientWithClientSecret return dtClient; } /// /// Illustrates how to construct a including client options, - /// using the implementation of . + /// using the implementation of . /// /// The Id of the tenant of the application Id. /// The application Id. - /// A client secret for the application Id. /// The endpoint of the digital twins instance. /// An HttpClient instance for the client to use - private static DigitalTwinsClient GetDigitalTwinsClient(string tenantId, string clientId, string clientSecret, string adtEndpoint, HttpClient httpClient) + private static DigitalTwinsClient GetDigitalTwinsClient(string tenantId, string clientId, string adtEndpoint, HttpClient httpClient) { - #region Snippet:DigitalTwinSampleCreateServiceClientWithHttpClient + #region Snippet:DigitalTwinsSampleCreateServiceClientInteractiveLogin // This illustrates how to specify client options, in this case, by providing an - // instance of HttpClient for the digital twins client to use - + // instance of HttpClient for the digital twins client to use. var clientOptions = new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient), }; - var clientSecretCredential = new ClientSecretCredential( + // By using the InteractiveBrowserCredential, the current user can login using a web browser + // interactively with the AAD + var tokenCredential = new InteractiveBrowserCredential( tenantId, clientId, - clientSecret, new TokenCredentialOptions { AuthorityHost = KnownAuthorityHosts.AzureCloud }); var dtClient = new DigitalTwinsClient( new Uri(adtEndpoint), - clientSecretCredential, + tokenCredential, clientOptions); - #endregion Snippet:DigitalTwinSampleCreateServiceClientWithHttpClient + #endregion Snippet:DigitalTwinsSampleCreateServiceClientInteractiveLogin return dtClient; } diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/Readme.md b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/Readme.md index d0bae7181ac5c..55e7ad3691445 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/Readme.md +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/Readme.md @@ -9,10 +9,15 @@ Sample project demonstrates the following: ## Creating Digital Twin Client -To create a new Digital Twin Client, you need the endpoint to an Azure Digital Twin and credentials. In the sample below, you can set `AdtEndpoint`, `TenantId`, `ClientId` and, `ClientSecret` as command line arguments. - -```C# Snippet:DigitalTwinSampleCreateServiceClient -var clientSecretCredential = new ClientSecretCredential( +To create a new Digital Twin Client, you need the endpoint to an Azure Digital Twin and credentials. +In the sample below, you can set `AdtEndpoint`, `TenantId`, `ClientId`, and `ClientSecret` as command-line arguments. +The client requires an instance of [TokenCredential](https://docs.microsoft.com/en-us/dotnet/api/azure.core.tokencredential?view=azure-dotnet). +In these samples, we illustrate how to use two derived classes: ClientSecretCredential, InteractiveLogin. + +```C# Snippet:DigitalTwinsSampleCreateServiceClientWithClientSecret +// By using the ClientSecretCredential, a specified application Id can login using a +// client secret. +var tokenCredential = new ClientSecretCredential( tenantId, clientId, clientSecret, @@ -20,29 +25,29 @@ var clientSecretCredential = new ClientSecretCredential( var dtClient = new DigitalTwinsClient( new Uri(adtEndpoint), - clientSecretCredential); + tokenCredential); ``` -If you need to override pipeline behavior, such as provide your own HttpClient instance, you can do that via client options. +Also, if you need to override pipeline behavior, such as provide your own HttpClient instance, you can do that via client options. This parameter is optional. -```C# Snippet:DigitalTwinSampleCreateServiceClientWithHttpClient +```C# Snippet:DigitalTwinsSampleCreateServiceClientInteractiveLogin // This illustrates how to specify client options, in this case, by providing an -// instance of HttpClient for the digital twins client to use - +// instance of HttpClient for the digital twins client to use. var clientOptions = new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient), }; -var clientSecretCredential = new ClientSecretCredential( +// By using the InteractiveBrowserCredential, the current user can login using a web browser +// interactively with the AAD +var tokenCredential = new InteractiveBrowserCredential( tenantId, clientId, - clientSecret, new TokenCredentialOptions { AuthorityHost = KnownAuthorityHosts.AzureCloud }); var dtClient = new DigitalTwinsClient( new Uri(adtEndpoint), - clientSecretCredential, + tokenCredential, clientOptions); ``` @@ -52,7 +57,7 @@ var dtClient = new DigitalTwinsClient( Let's create models using the code below. You need to pass in List containing list of json models. Check out sample models [here](https://github.com/Azure/azure-sdk-for-net-pr/tree/feature/IoT-ADT/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DTDL/Models "Models") -```C# Snippet:DigitalTwinSampleCreateModels +```C# Snippet:DigitalTwinsSampleCreateModels Response> response = await DigitalTwinsClient.CreateModelsAsync(new[] { newComponentModelPayload, newModelPayload }).ConfigureAwait(false); Console.WriteLine($"Successfully created a model with Id: {newComponentModelId}, {sampleModelId}, status: {response.GetRawResponse().Status}"); ``` @@ -61,7 +66,7 @@ Console.WriteLine($"Successfully created a model with Id: {newComponentModelId}, Using `GetModelsAsync`, all created models are listed as AsyncPageable -```C# Snippet:DigitalTwinSampleGetModels +```C# Snippet:DigitalTwinsSampleGetModels AsyncPageable allModels = DigitalTwinsClient.GetModelsAsync(); await foreach (ModelData model in allModels) { @@ -71,7 +76,7 @@ await foreach (ModelData model in allModels) Use `GetModelAsync` with model's unique identifier to get a specific model -```C# Snippet:DigitalTwinSampleGetModel +```C# Snippet:DigitalTwinsSampleGetModel Response sampleModel = await DigitalTwinsClient.GetModelAsync(sampleModelId).ConfigureAwait(false); ``` @@ -79,7 +84,7 @@ Response sampleModel = await DigitalTwinsClient.GetModelAsync(sampleM To decommision a model, pass in a model id for the model you want to decommision -```C# Snippet:DigitalTwinSampleDecommisionModel +```C# Snippet:DigitalTwinsSampleDecommisionModel try { await DigitalTwinsClient.DecommissionModelAsync(sampleModelId).ConfigureAwait(false); @@ -96,7 +101,7 @@ catch (Exception ex) To delete a model, pass in a model id for the model you want to delete -```C# Snippet:DigitalTwinSampleDeleteModel +```C# Snippet:DigitalTwinsSampleDeleteModel try { await DigitalTwinsClient.DeleteModelAsync(sampleModelId).ConfigureAwait(false); @@ -115,7 +120,7 @@ catch (Exception ex) For Creating Twin you will need to provide Id of a digital Twin such as `myTwin` and the application/json digital twin based on the model created earlier. You can look at sample application/json [here](https://github.com/Azure/azure-sdk-for-net-pr/tree/feature/IoT-ADT/sdk/digitaltwins/Azure.DigitalTwins.Core/samples/DigitalTwinsClientSample/DTDL/DigitalTwins "DigitalTwin"). -```C# Snippet:DigitalTwinSampleCreateTwin +```C# Snippet:DigitalTwinsSampleCreateTwin Response response = await DigitalTwinsClient.CreateDigitalTwinAsync(twin.Key, twin.Value).ConfigureAwait(false); ``` @@ -123,7 +128,7 @@ Response response = await DigitalTwinsClient.CreateDigitalTwinAsync(twin Query the Azure Digital Twins instance for digital twins using the [Azure Digital Twins Query Store lanaguage](https://review.docs.microsoft.com/en-us/azure/digital-twins-v2/concepts-query-language?branch=pr-en-us-114648). Query calls support paging. Here's an example of how to query for digital twins and how to iterate over the results. -```C# Snippet:DigitalTwinSampleQueryTwins +```C# Snippet:DigitalTwinsSampleQueryTwins // This code snippet demonstrates the simplest way to iterate over the digital twin results, where paging // happens under the covers. AsyncPageable asyncPageableResponse = DigitalTwinsClient.QueryAsync("SELECT * FROM digitaltwins"); @@ -140,7 +145,7 @@ await foreach (string response in asyncPageableResponse) The SDK also allows you to extract the `query-charge` header from the pagebale response. Here's an example of how to query for digital twins and how to iterate over the pageable response to extract the `query-charge` header. -```C# Snippet:DigitalTwinSampleQueryTwinsWithQueryCharge +```C# Snippet:DigitalTwinsSampleQueryTwinsWithQueryCharge // This code snippet demonstrates how you could extract the query charges incurred when calling // the query API. It iterates over the response pages first to access to the query-charge header, // and then the digital twin results within each page. @@ -173,7 +178,7 @@ await foreach (Page page in asyncPageableResponseWithCharge.AsPages()) Delete a digital twin simply by providing id of a digital twin as below. -```C# Snippet:DigitalTwinSampleDeleteTwin +```C# Snippet:DigitalTwinsSampleDeleteTwin await DigitalTwinsClient.DeleteDigitalTwinAsync(twin.Key).ConfigureAwait(false); ``` @@ -183,7 +188,7 @@ await DigitalTwinsClient.DeleteDigitalTwinAsync(twin.Key).ConfigureAwait(false); To update a component or in other words to replace, remove and/or add a component property or subproperty within Digital Twin, you would need id of a digital twin, component name and application/json-patch+json operations to be performed on the specified digital twin's component. Here is the sample code on how to do it. -```C# Snippet:DigitalTwinSampleUpdateComponent +```C# Snippet:DigitalTwinsSampleUpdateComponent // Update Component with replacing property value string propertyPath = "/ComponentProp1"; string propValue = "New Value"; @@ -198,7 +203,7 @@ Response response = await DigitalTwinsClient.UpdateComponentAsync(twinId Get a component by providing name of a component and id of digital twin it belongs to. -```C# Snippet:DigitalTwinSampleGetComponent +```C# Snippet:DigitalTwinsSampleGetComponent response = await DigitalTwinsClient.GetComponentAsync(twinId, SamplesConstants.ComponentPath).ConfigureAwait(false); ``` @@ -208,7 +213,7 @@ response = await DigitalTwinsClient.GetComponentAsync(twinId, SamplesConstants.C `CreateEdgeAsync` creates a relationship edge on a digital twin provided with id of a digital twin, name of relationship such as "contains", id of an edge such as "FloorContainsRoom" and an application/json edge to be created. Must contain property with key "$targetId" to specify the target of the edge. Sample payloads for relationships can be found [here](https://github.com/Azure/azure-sdk-for-net-pr/blob/feature/IoT-ADT/sdk/iot/Azure.Iot.DigitalTwins/samples/DigitalTwinServiceClientSample/DTDL/Relationships/HospitalEdges.json "RelationshipExamples"). -```C# Snippet:DigitalTwinSampleCreateRelationship +```C# Snippet:DigitalTwinsSampleCreateRelationship string serializedRelationship = JsonSerializer.Serialize(relationship); await DigitalTwinsClient @@ -222,11 +227,11 @@ await DigitalTwinsClient `GetEdgesAsync` and `GetIncomingEdgesAsync` lists all the edges and all incoming edges respectively of a digital twin -```C# Snippet:DigitalTwinSampleGetRelationships +```C# Snippet:DigitalTwinsSampleGetRelationships AsyncPageable relationships = DigitalTwinsClient.GetRelationshipsAsync(twin.Key); ``` -```C# Snippet:DigitalTwinSampleGetIncomingRelationships +```C# Snippet:DigitalTwinsSampleGetIncomingRelationships AsyncPageable incomingRelationships = DigitalTwinsClient.GetIncomingRelationshipsAsync(twin.Key); ``` @@ -236,7 +241,7 @@ AsyncPageable incomingRelationships = DigitalTwinsClient.G To create Event route, one needs to provide id of an event route such as "sampleEventRoute" and event route data containing the endpoint and optional filter like the example shown below -```C# Snippet:DigitalTwinSampleCreateEventRoute +```C# Snippet:DigitalTwinsSampleCreateEventRoute string eventFilter = "$eventType = 'DigitalTwinTelemetryMessages' or $eventType = 'DigitalTwinLifecycleNotification'"; var eventRoute = new EventRoute(_eventhubEndpointName) { @@ -250,7 +255,7 @@ Response createEventRouteResponse = await DigitalTwinsClient.CreateEventRouteAsy List a specific event route given event route id or all event routes setting options with `GetEventRouteAsync` and `GetEventRoutesAsync`. -```C# Snippet:DigitalTwinSampleGetEventRoutes +```C# Snippet:DigitalTwinsSampleGetEventRoutes AsyncPageable response = DigitalTwinsClient.GetEventRoutesAsync(); await foreach (EventRoute er in response) { @@ -262,6 +267,6 @@ await foreach (EventRoute er in response) Delete an event route given event route id -```C# Snippet:DigitalTwinSampleDeleteEventRoute +```C# Snippet:DigitalTwinsSampleDeleteEventRoute Response response = await DigitalTwinsClient.DeleteEventRouteAsync(_eventRouteId).ConfigureAwait(false); ``` diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/src/DigitalTwinsClient.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/src/DigitalTwinsClient.cs index 4f17f7e483b52..3c022e33298d7 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/src/DigitalTwinsClient.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/src/DigitalTwinsClient.cs @@ -33,8 +33,10 @@ public class DigitalTwinsClient /// The Azure digital twins service instance URI to connect to. /// The implementation which will be used to request for the authentication token. /// - /// - /// var clientSecretCredential = new ClientSecretCredential( + /// + /// // By using the ClientSecretCredential, a specified application Id can login using a + /// // client secret. + /// var tokenCredential = new ClientSecretCredential( /// tenantId, /// clientId, /// clientSecret, @@ -42,7 +44,7 @@ public class DigitalTwinsClient /// /// var dtClient = new DigitalTwinsClient( /// new Uri(adtEndpoint), - /// clientSecretCredential); + /// tokenCredential); /// /// public DigitalTwinsClient(Uri endpoint, TokenCredential credential) @@ -57,24 +59,24 @@ public DigitalTwinsClient(Uri endpoint, TokenCredential credential) /// The implementation which will be used to request for the authentication token. /// Options that allow configuration of requests sent to the digital twins service. /// - /// + /// /// // This illustrates how to specify client options, in this case, by providing an - /// // instance of HttpClient for the digital twins client to use - /// + /// // instance of HttpClient for the digital twins client to use. /// var clientOptions = new DigitalTwinsClientOptions /// { /// Transport = new HttpClientTransport(httpClient), /// }; /// - /// var clientSecretCredential = new ClientSecretCredential( + /// // By using the InteractiveBrowserCredential, the current user can login using a web browser + /// // interactively with the AAD + /// var tokenCredential = new InteractiveBrowserCredential( /// tenantId, /// clientId, - /// clientSecret, /// new TokenCredentialOptions { AuthorityHost = KnownAuthorityHosts.AzureCloud }); /// /// var dtClient = new DigitalTwinsClient( /// new Uri(adtEndpoint), - /// clientSecretCredential, + /// tokenCredential, /// clientOptions); /// /// @@ -142,7 +144,7 @@ public virtual Response GetDigitalTwin(string digitalTwinId, Cancellatio /// The created application/json digital twin and the http response. /// The digital twin must be the serialization of an instance of or the serialization of an extension of that type. /// - /// + /// /// Response<string> response = await DigitalTwinsClient.CreateDigitalTwinAsync(twin.Key, twin.Value).ConfigureAwait(false); /// /// @@ -175,7 +177,7 @@ public virtual Response CreateDigitalTwin(string digitalTwinId, string d /// To delete a digital twin, any relationships referencing it must be deleted first. /// /// - /// + /// /// await DigitalTwinsClient.DeleteDigitalTwinAsync(twin.Key).ConfigureAwait(false); /// /// @@ -234,7 +236,7 @@ public virtual Response UpdateDigitalTwin(string digitalTwinId, string d /// The cancellation token. /// Json string representation of the component corresponding to the provided componentPath and the HTTP response. /// - /// + /// /// response = await DigitalTwinsClient.GetComponentAsync(twinId, SamplesConstants.ComponentPath).ConfigureAwait(false); /// /// @@ -265,7 +267,7 @@ public virtual Response GetComponent(string digitalTwinId, string compon /// The cancellation token. /// The HTTP response. /// - /// + /// /// // Update Component with replacing property value /// string propertyPath = "/ComponentProp1"; /// string propValue = "New Value"; @@ -304,7 +306,7 @@ public virtual Response UpdateComponent(string digitalTwinId, string com /// The cancellation token. /// The pageable list of application/json relationships belonging to the specified digital twin and the http response. /// - /// + /// /// AsyncPageable<string> relationships = DigitalTwinsClient.GetRelationshipsAsync(twin.Key); /// /// @@ -406,7 +408,7 @@ Page NextPageFunc(string nextLink, int? pageSizeHint) /// The cancellation token. /// The pageable list of application/json relationships directed towards the specified digital twin and the http response. /// - /// + /// /// AsyncPageable<IncomingRelationship> incomingRelationships = DigitalTwinsClient.GetIncomingRelationshipsAsync(twin.Key); /// /// @@ -555,7 +557,7 @@ public virtual Response DeleteRelationship(string digitalTwinId, string relation /// This argument must be the serialization of an instance of or the serialization of an extension of that type. /// /// - /// + /// /// string serializedRelationship = JsonSerializer.Serialize(relationship); /// /// await DigitalTwinsClient @@ -626,7 +628,7 @@ public virtual Response UpdateRelationship(string digitalTwinId, string relation /// The cancellation token. /// A pageable set of application/json models and the http response. /// - /// + /// /// AsyncPageable<ModelData> allModels = DigitalTwinsClient.GetModelsAsync(); /// await foreach (ModelData model in allModels) /// { @@ -723,7 +725,7 @@ Page NextPageFunc(string nextLink, int? pageSizeHint) /// The cancellation token. /// The application/json model and the http response. /// - /// + /// /// Response<ModelData> sampleModel = await DigitalTwinsClient.GetModelAsync(sampleModelId).ConfigureAwait(false); /// /// @@ -757,7 +759,7 @@ public virtual Response GetModel(string modelId, CancellationToken ca /// Once a model is decomissioned, it may not be recommissioned. /// /// - /// + /// /// try /// { /// await DigitalTwinsClient.DecommissionModelAsync(sampleModelId).ConfigureAwait(false); @@ -804,7 +806,7 @@ public virtual Response DecommissionModel(string modelId, CancellationToken canc /// So using this method, model creation is transactional. /// /// - /// + /// /// Response<IReadOnlyList<ModelData>> response = await DigitalTwinsClient.CreateModelsAsync(new[] { newComponentModelPayload, newModelPayload }).ConfigureAwait(false); /// Console.WriteLine($"Successfully created a model with Id: {newComponentModelId}, {sampleModelId}, status: {response.GetRawResponse().Status}"); /// @@ -845,7 +847,7 @@ public virtual Response> CreateModels(IEnumerable /// - /// + /// /// try /// { /// await DigitalTwinsClient.DeleteModelAsync(sampleModelId).ConfigureAwait(false); @@ -888,7 +890,7 @@ public virtual Response DeleteModel(string modelId, CancellationToken cancellati /// The cancellation token. /// The pageable list of query results. /// - /// + /// /// // This code snippet demonstrates the simplest way to iterate over the digital twin results, where paging /// // happens under the covers. /// AsyncPageable<string> asyncPageableResponse = DigitalTwinsClient.QueryAsync("SELECT * FROM digitaltwins"); @@ -1013,7 +1015,7 @@ Page NextPageFunc(string nextLink, int? pageSizeHint) /// The cancellation token. /// A pageable set of application/json event routes and the http response. /// - /// + /// /// AsyncPageable<EventRoute> response = DigitalTwinsClient.GetEventRoutesAsync(); /// await foreach (EventRoute er in response) /// { @@ -1131,7 +1133,7 @@ public virtual Response GetEventRoute(string eventRouteId, Cancellat /// The cancellation token. /// The http response. /// - /// + /// /// string eventFilter = "$eventType = 'DigitalTwinTelemetryMessages' or $eventType = 'DigitalTwinLifecycleNotification'"; /// var eventRoute = new EventRoute(_eventhubEndpointName) /// { @@ -1165,7 +1167,7 @@ public virtual Response CreateEventRoute(string eventRouteId, EventRoute eventRo /// The cancellation token. /// The http response. /// - /// + /// /// Response response = await DigitalTwinsClient.DeleteEventRouteAsync(_eventRouteId).ConfigureAwait(false); /// /// diff --git a/sdk/digitaltwins/Azure.DigitalTwins.Core/src/Queries/QueryChargeHelper.cs b/sdk/digitaltwins/Azure.DigitalTwins.Core/src/Queries/QueryChargeHelper.cs index 3981b4d1bf1c3..e3c8b266cf6e4 100644 --- a/sdk/digitaltwins/Azure.DigitalTwins.Core/src/Queries/QueryChargeHelper.cs +++ b/sdk/digitaltwins/Azure.DigitalTwins.Core/src/Queries/QueryChargeHelper.cs @@ -21,7 +21,7 @@ public static class QueryChargeHelper /// The page that contains the query-charge header. /// The query charge extracted from the header. /// True if the header contains a query-charge field, otherwise false. - /// + /// /// // This code snippet demonstrates how you could extract the query charges incurred when calling /// // the query API. It iterates over the response pages first to access to the query-charge header, /// // and then the digital twin results within each page.