public async Task Component_Lifecycle() { // arrange DigitalTwinsClient client = GetClient(); string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.WifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.RoomWithWifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetSettings.RoomWithWifiTwinIdPrefix).ConfigureAwait(false); string wifiComponentName = "wifiAccessPoint"; try { // CREATE // create roomWithWifi model string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // create wifi model string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await client.CreateModelsAsync(new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // create room digital twin string roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await client.CreateDigitalTwinAsync(roomWithWifiTwinId, roomWithWifiTwin); // Get the component Response <string> getComponentResponse = await client .GetComponentAsync( roomWithWifiTwinId, wifiComponentName) .ConfigureAwait(false); // The response to the GET request should be 200 (OK) getComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK); // Patch component Response <string> updateComponentResponse = await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, TestAssetsHelper.GetWifiComponentUpdatePayload()) .ConfigureAwait(false); // The response to the Patch request should be 204 (No content) updateComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.NoContent); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomWithWifiTwinId)) { await client.DeleteDigitalTwinAsync(roomWithWifiTwinId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(roomWithWifiModelId)) { await client.DeleteModelAsync(roomWithWifiModelId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(wifiModelId)) { await client.DeleteModelAsync(wifiModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
/// <summary> /// Creates a digital twin with Component and upates Component /// </summary> public async Task RunSamplesAsync(DigitalTwinsClient client) { PrintHeader("COMPONENT SAMPLE"); // For the purpose of this example we will create temporary models using a random model Ids. // We have to make sure these model Ids are unique within the DT instance. string componentModelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryComponentModelPrefix, client); string modelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryModelPrefix, client); string basicDtId = await GetUniqueTwinIdAsync(SamplesConstants.TemporaryTwinPrefix, client); string newComponentModelPayload = SamplesConstants.TemporaryComponentModelPayload .Replace(SamplesConstants.ComponentId, componentModelId); string newModelPayload = SamplesConstants.TemporaryModelWithComponentPayload .Replace(SamplesConstants.ModelId, modelId) .Replace(SamplesConstants.ComponentId, componentModelId); // Then we create models await client.CreateModelsAsync( new[] { newComponentModelPayload, newModelPayload }); Console.WriteLine($"Created models {componentModelId} and {modelId}."); #region Snippet:DigitalTwinsSampleCreateBasicTwin // Create digital twin with component payload using the BasicDigitalTwin serialization helper var basicTwin = new BasicDigitalTwin { Id = basicDtId, // model Id of digital twin Metadata = { ModelId = modelId }, Contents = { // digital twin properties { "Prop1", "Value1" }, { "Prop2", 987 }, // component { "Component1", new BasicDigitalTwinComponent { // component properties Contents = { { "ComponentProp1", "Component value 1" }, { "ComponentProp2", 123 }, }, } }, }, }; Response <BasicDigitalTwin> createDigitalTwinResponse = await client.CreateOrReplaceDigitalTwinAsync(basicDtId, basicTwin); Console.WriteLine($"Created digital twin '{createDigitalTwinResponse.Value.Id}'."); #endregion Snippet:DigitalTwinsSampleCreateBasicTwin // You can also get a digital twin as a BasicDigitalTwin type. // It works well for basic stuff, but as you can see it gets more difficult when delving into // more complex properties, like components. #region Snippet:DigitalTwinsSampleGetBasicDigitalTwin Response <BasicDigitalTwin> getBasicDtResponse = await client.GetDigitalTwinAsync <BasicDigitalTwin>(basicDtId); if (getBasicDtResponse.GetRawResponse().Status == (int)HttpStatusCode.OK) { BasicDigitalTwin basicDt = getBasicDtResponse.Value; // Must cast Component1 as a JsonElement and get its raw text in order to deserialize it as a dictionary string component1RawText = ((JsonElement)basicDt.Contents["Component1"]).GetRawText(); IDictionary <string, object> component1 = JsonSerializer.Deserialize <IDictionary <string, object> >(component1RawText); Console.WriteLine($"Retrieved and deserialized digital twin {basicDt.Id}:\n\t" + $"ETag: {basicDt.ETag}\n\t" + $"Prop1: {basicDt.Contents["Prop1"]}\n\t" + $"Prop2: {basicDt.Contents["Prop2"]}\n\t" + $"ComponentProp1: {component1["ComponentProp1"]}\n\t" + $"ComponentProp2: {component1["ComponentProp2"]}"); } #endregion Snippet:DigitalTwinsSampleGetBasicDigitalTwin string customDtId = await GetUniqueTwinIdAsync(SamplesConstants.TemporaryTwinPrefix, client); // Alternatively, you can create your own custom data types to serialize and deserialize your digital twins. // By specifying your properties and types directly, it requires less code or knowledge of the type for // interaction. #region Snippet:DigitalTwinsSampleCreateCustomTwin var customTwin = new CustomDigitalTwin { Id = customDtId, Metadata = { ModelId = modelId }, Prop1 = "Prop1 val", Prop2 = 987, Component1 = new MyCustomComponent { ComponentProp1 = "Component prop1 val", ComponentProp2 = 123, }, }; Response <CustomDigitalTwin> createCustomDigitalTwinResponse = await client.CreateOrReplaceDigitalTwinAsync(customDtId, customTwin); Console.WriteLine($"Created digital twin '{createCustomDigitalTwinResponse.Value.Id}'."); #endregion Snippet:DigitalTwinsSampleCreateCustomTwin // Getting a digital twin as a custom data type is extremely easy. // Custom types provide the best possible experience. #region Snippet:DigitalTwinsSampleGetCustomDigitalTwin Response <CustomDigitalTwin> getCustomDtResponse = await client.GetDigitalTwinAsync <CustomDigitalTwin>(customDtId); CustomDigitalTwin customDt = getCustomDtResponse.Value; Console.WriteLine($"Retrieved and deserialized digital twin {customDt.Id}:\n\t" + $"ETag: {customDt.ETag}\n\t" + $"Prop1: {customDt.Prop1}\n\t" + $"Prop2: {customDt.Prop2}\n\t" + $"ComponentProp1: {customDt.Component1.ComponentProp1}\n\t" + $"ComponentProp2: {customDt.Component1.ComponentProp2}"); #endregion Snippet:DigitalTwinsSampleGetCustomDigitalTwin #region Snippet:DigitalTwinsSampleUpdateComponent // Update Component1 by replacing the property ComponentProp1 value, // using an optional utility to build the payload. var componentJsonPatchDocument = new JsonPatchDocument(); componentJsonPatchDocument.AppendReplace("/ComponentProp1", "Some new value"); await client.UpdateComponentAsync(basicDtId, "Component1", componentJsonPatchDocument); Console.WriteLine($"Updated component for digital twin '{basicDtId}'."); #endregion Snippet:DigitalTwinsSampleUpdateComponent // Get Component #region Snippet:DigitalTwinsSampleGetComponent await client.GetComponentAsync <MyCustomComponent>(basicDtId, SamplesConstants.ComponentName); Console.WriteLine($"Retrieved component for digital twin '{basicDtId}'."); #endregion Snippet:DigitalTwinsSampleGetComponent // Clean up try { await client.DeleteDigitalTwinAsync(basicDtId); await client.DeleteDigitalTwinAsync(customDtId); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete digital twin due to {ex}"); } try { await client.DeleteModelAsync(modelId); await client.DeleteModelAsync(componentModelId); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete models due to {ex}"); } }
public async Task Component_Lifecycle() { // arrange DigitalTwinsClient client = GetClient(); string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomWithWifiTwinIdPrefix).ConfigureAwait(false); string wifiComponentName = "wifiAccessPoint"; try { // CREATE // create roomWithWifi model string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // create wifi model string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await CreateAndListModelsAsync(client, new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // create room digital twin BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName); await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin); // Get the component Response <object> getComponentResponse = await client .GetComponentAsync <object>( roomWithWifiTwinId, wifiComponentName) .ConfigureAwait(false); // The response to the GET request should be 200 (OK) getComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK); // Patch component JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument(); componentUpdatePatchDocument.AppendReplace("/Network", "New Network"); Response updateComponentResponse = await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, componentUpdatePatchDocument) .ConfigureAwait(false); // The response to the Patch request should be 204 (No content) updateComponentResponse.Status.Should().Be((int)HttpStatusCode.NoContent); } catch (Exception ex) { Assert.Fail($"Failure in executing a step in the test case: {ex.Message}."); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomWithWifiTwinId)) { await client.DeleteDigitalTwinAsync(roomWithWifiTwinId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(roomWithWifiModelId)) { await client.DeleteModelAsync(roomWithWifiModelId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(wifiModelId)) { await client.DeleteModelAsync(wifiModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Component_UpdateComponentSucceedsWhenIfMatchHeaderIsCorrect() { // arrange DigitalTwinsClient client = GetClient(); string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomWithWifiTwinIdPrefix).ConfigureAwait(false); string wifiComponentName = "wifiAccessPoint"; try { // CREATE // create roomWithWifi model string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // create wifi model string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await client.CreateModelsAsync(new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // create room digital twin BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName); await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin); // Get the component Response <object> getComponentResponse = await client .GetComponentAsync <object>( roomWithWifiTwinId, wifiComponentName) .ConfigureAwait(false); // Patch component JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument(); componentUpdatePatchDocument.AppendReplace("/Network", "New Network"); Response updateComponentResponse = await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, componentUpdatePatchDocument) .ConfigureAwait(false); // Get the latest ETag ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId)).Value.ETag; Assert.IsNotNull(etagBeforeUpdate); // Patch component again, but with the now out of date ETag JsonPatchDocument secondComponentUpdatePatchDocument = new JsonPatchDocument(); componentUpdatePatchDocument.AppendReplace("/Network", "Even newer Network"); try { await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, secondComponentUpdatePatchDocument, etagBeforeUpdate) .ConfigureAwait(false); } catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.PreconditionFailed) { throw new AssertionException("UpdateComponent should not have thrown PreconditionFailed because the ETag was up to date", ex); } } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomWithWifiTwinId)) { await client.DeleteDigitalTwinAsync(roomWithWifiTwinId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(roomWithWifiModelId)) { await client.DeleteModelAsync(roomWithWifiModelId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(wifiModelId)) { await client.DeleteModelAsync(wifiModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Component_UpdateComponentFailsWhenIfMatchHeaderOutOfDate() { // arrange DigitalTwinsClient client = GetClient(); string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomWithWifiTwinIdPrefix).ConfigureAwait(false); string wifiComponentName = "wifiAccessPoint"; try { // CREATE // create roomWithWifi model string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // create wifi model string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await CreateAndListModelsAsync(client, new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // create room digital twin BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName); await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin); // Get the component Response <object> getComponentResponse = await client .GetComponentAsync <object>( roomWithWifiTwinId, wifiComponentName) .ConfigureAwait(false); ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId)).Value.ETag; // Patch component JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument(); componentUpdatePatchDocument.AppendReplace("/Network", "New Network"); Response updateComponentResponse = await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, componentUpdatePatchDocument) .ConfigureAwait(false); // Patch component again, but with the now out of date ETag JsonPatchDocument secondComponentUpdatePatchDocument = new JsonPatchDocument(); secondComponentUpdatePatchDocument.AppendReplace("/Network", "Even newer Network"); Func <Task> act = async() => { await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, secondComponentUpdatePatchDocument, etagBeforeUpdate) .ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>() .And.Status.Should().Be((int)HttpStatusCode.PreconditionFailed); } catch (Exception ex) { Assert.Fail($"Failure in executing a step in the test case: {ex.Message}."); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomWithWifiTwinId)) { await client.DeleteDigitalTwinAsync(roomWithWifiTwinId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(roomWithWifiModelId)) { await client.DeleteModelAsync(roomWithWifiModelId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(wifiModelId)) { await client.DeleteModelAsync(wifiModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }