diff --git a/iothub/device/src/ClientPropertyCollection.cs b/iothub/device/src/ClientPropertyCollection.cs
index 17729ad2c0..f624c38c30 100644
--- a/iothub/device/src/ClientPropertyCollection.cs
+++ b/iothub/device/src/ClientPropertyCollection.cs
@@ -44,8 +44,16 @@ public void AddRootProperty(string propertyName, object propertyValue)
/// The component with the property to add.
/// The name of the property to add.
/// The value of the property to add.
+ /// or is null.
public void AddComponentProperty(string componentName, string propertyName, object propertyValue)
- => AddInternal(new Dictionary { { propertyName, propertyValue } }, componentName, false);
+ {
+ if (componentName == null)
+ {
+ throw new ArgumentNullException(nameof(componentName));
+ }
+
+ AddInternal(new Dictionary { { propertyName, propertyValue } }, componentName, false);
+ }
///
///
@@ -55,8 +63,16 @@ public void AddComponentProperty(string componentName, string propertyName, obje
/// The component with the properties to add.
/// A collection of properties to add.
/// A property name in already exists in the collection.
+ /// or a property name in is null.
public void AddComponentProperties(string componentName, IDictionary properties)
- => AddInternal(properties, componentName, true);
+ {
+ if (componentName == null)
+ {
+ throw new ArgumentNullException(nameof(componentName));
+ }
+
+ AddInternal(properties, componentName, false);
+ }
///
///
@@ -100,9 +116,16 @@ public void AddOrUpdateRootProperty(string propertyName, object propertyValue)
/// The component with the property to add or update.
/// The name of the property to add or update.
/// The value of the property to add or update.
- /// is null.
+ /// or is null.
public void AddOrUpdateComponentProperty(string componentName, string propertyName, object propertyValue)
- => AddInternal(new Dictionary { { propertyName, propertyValue } }, componentName, true);
+ {
+ if (componentName == null)
+ {
+ throw new ArgumentNullException(nameof(componentName));
+ }
+
+ AddInternal(new Dictionary { { propertyName, propertyValue } }, componentName, true);
+ }
///
///
@@ -116,8 +139,16 @@ public void AddOrUpdateComponentProperty(string componentName, string propertyNa
///
/// The component with the properties to add or update.
/// A collection of properties to add or update.
+ /// or a property name in is null.
public void AddOrUpdateComponentProperties(string componentName, IDictionary properties)
- => AddInternal(properties, componentName, true);
+ {
+ if (componentName == null)
+ {
+ throw new ArgumentNullException(nameof(componentName));
+ }
+
+ AddInternal(properties, componentName, true);
+ }
///
///
@@ -133,9 +164,16 @@ public void AddOrUpdateComponentProperties(string componentName, IDictionaryA collection of properties to add or update.
/// is null.
public void AddOrUpdateRootProperties(IDictionary properties)
- => properties
+ {
+ if (properties == null)
+ {
+ throw new ArgumentNullException(nameof(properties));
+ }
+
+ properties
.ToList()
.ForEach(entry => Collection[entry.Key] = entry.Value);
+ }
///
/// Determines whether the specified property is present.
@@ -426,14 +464,14 @@ internal static ClientPropertyCollection FromClientPropertiesAsDictionary(IDicti
/// The component with the properties to add or update.
/// Forces the collection to use the Add or Update behavior.
/// Setting to true will simply overwrite the value. Setting to false will use
- /// is null for a top-level property operation.
+ /// is null.
private void AddInternal(IDictionary properties, string componentName = default, bool forceUpdate = false)
{
// If the componentName is null then simply add the key-value pair to Collection dictionary.
// This will either insert a property or overwrite it if it already exists.
if (componentName == null)
{
- // If both the component name and properties collection are null then throw a ArgumentNullException.
+ // If both the component name and properties collection are null then throw an ArgumentNullException.
// This is not a valid use-case.
if (properties == null)
{
@@ -442,6 +480,12 @@ private void AddInternal(IDictionary properties, string componen
foreach (KeyValuePair entry in properties)
{
+ // A null property key is not allowed. Throw an ArgumentNullException.
+ if (entry.Key == null)
+ {
+ throw new ArgumentNullException(nameof(entry.Key));
+ }
+
if (forceUpdate)
{
Collection[entry.Key] = entry.Value;
@@ -471,6 +515,12 @@ private void AddInternal(IDictionary properties, string componen
foreach (KeyValuePair entry in properties)
{
+ // A null property key is not allowed. Throw an ArgumentNullException.
+ if (entry.Key == null)
+ {
+ throw new ArgumentNullException(nameof(entry.Key));
+ }
+
if (forceUpdate)
{
componentProperties[entry.Key] = entry.Value;
diff --git a/iothub/device/src/TelemetryCollection.cs b/iothub/device/src/TelemetryCollection.cs
index 99d0164aff..321bdbec7a 100644
--- a/iothub/device/src/TelemetryCollection.cs
+++ b/iothub/device/src/TelemetryCollection.cs
@@ -2,6 +2,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
+using System.Linq;
namespace Microsoft.Azure.Devices.Client
{
@@ -32,5 +34,42 @@ public override void AddOrUpdate(string telemetryName, object telemetryValue)
{
base.AddOrUpdate(telemetryName, telemetryValue);
}
+
+ ///
+ /// Adds the telemetry values to the telemetry collection.
+ ///
+ ///
+ ///
+ /// An element with the same key already exists in the collection.
+ /// is null.
+ public void Add(IDictionary telemetryValues)
+ {
+ if (telemetryValues == null)
+ {
+ throw new ArgumentNullException(nameof(telemetryValues));
+ }
+
+ telemetryValues
+ .ToList()
+ .ForEach(entry => base.Add(entry.Key, entry.Value));
+ }
+
+ ///
+ /// Adds or updates the telemetry values in the telemetry collection.
+ ///
+ ///
+ ///
+ /// is null.
+ public void AddOrUpdate(IDictionary telemetryValues)
+ {
+ if (telemetryValues == null)
+ {
+ throw new ArgumentNullException(nameof(telemetryValues));
+ }
+
+ telemetryValues
+ .ToList()
+ .ForEach(entry => base.AddOrUpdate(entry.Key, entry.Value));
+ }
}
}
diff --git a/iothub/device/tests/ClientPropertyCollectionTests.cs b/iothub/device/tests/ClientPropertyCollectionTests.cs
index 48e3cc6e95..bd0d1dddd4 100644
--- a/iothub/device/tests/ClientPropertyCollectionTests.cs
+++ b/iothub/device/tests/ClientPropertyCollectionTests.cs
@@ -6,6 +6,7 @@
using FluentAssertions;
using Microsoft.Azure.Devices.Shared;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Newtonsoft.Json;
namespace Microsoft.Azure.Devices.Client.Test
{
@@ -427,6 +428,405 @@ public void ClientPropertyCollection_TryGetValueWithComponentShouldReturnFalseIf
isValueRetrieved.Should().BeFalse();
propertyValue.Should().Be(default);
}
+
+ [TestMethod]
+ public void ClientPropertyCollection_AddNullPropertyNameThrows()
+ {
+ // arrange
+ var testPropertyCollection = new ClientPropertyCollection();
+
+ // act
+ Action testAction = () => testPropertyCollection.AddRootProperty(null, 123);
+
+ // assert
+ testAction.Should().Throw();
+ }
+
+ [TestMethod]
+ public void ClientPropertyCollection_AddOrUpdateNullPropertyNameThrows()
+ {
+ // arrange
+ var testPropertyCollection = new ClientPropertyCollection();
+
+ // act
+ Action testAction = () => testPropertyCollection.AddOrUpdateRootProperty(null, 123);
+
+ // assert
+ testAction.Should().Throw();
+ }
+
+ [TestMethod]
+ public void ClientPropertyCollection_AddNullPropertyValueSuccess()
+ {
+ // arrange
+ var testPropertyCollection = new ClientPropertyCollection();
+
+ // act
+ // This should add an entry in the dictionary with a null value.
+ // This patch would be interpreted by the service as the client wanting to remove property "abc" from its properties.
+ testPropertyCollection.AddRootProperty("abc", null);
+
+ // assert
+ bool isValueRetrieved = testPropertyCollection.TryGetValue