This document outlines the changes made from this library's v1 releases to its v2 releases. Since this is a major version update, there are a number of breaking changes that will affect compilation and runtime behavior. Provided here are lists of the notable changes as well as a mapping from v1 to v2 APIs to aid migrating.
- Why the v1 SDK is being replaced
- What will happen to the v1 SDK
- Migration guide
- Frequently asked questions
There are a number of reasons why the Azure IoT SDK team chose to do a major version revision. Here are a few of the more important reasons:
The v1 SDK is supplied in many NuGet packages. This causes several problems of discoverability and challenges of managing updates. In v2, we've aimed to simplify this experience.
- Updated in place
- Microsoft.Azure.Devices (IoT hub service)
- Microsoft.Azure.Devices.Client (IoT hub device)
- Microsoft.Azure.Devices.Provisioning.Client
- Microsoft.Azure.Devices.Provisioning.Service
- Removed
- Microsoft.Azure.Devices.Shared
We removed as much shared code as possible. Classes, like Twin, have moved to the libraries that use them. They've been trimmed down to only include properties and methods that are applicable to that client, which removes confusing/useless API surface.
- Microsoft.Azure.Devices.Provisioning.Transport.Amqp
Rolled into Microsoft.Azure.Devices.Provisioning.Client.
- Microsoft.Azure.Devices.Provisioning.Transport.Http
Rolled into Microsoft.Azure.Devices.Provisioning.Client.
- Microsoft.Azure.Devices.Provisioning.Transport.Mqtt
Rolled into Microsoft.Azure.Devices.Provisioning.Client.
- Microsoft.Azure.Devices.Provisioning.Security.Tpm
Deprecated.
- From preview001, Microsoft.Azure.Devices.Authentication.
Rolled into Microsoft.Azure.Devices.Provisioning.Client.
- Microsoft.Azure.Devices.Shared
Namespaces have been simplified to reduce confusion and improve discoverability of all available types in the library. Each client library has its own namespace, and the namespace is the same as the package name.
The folllowing namespaces have been deprecated:
Microsoft.Azure.Devices.Shared
Microsoft.Azure.Devices.Common.Exceptions
Microsoft.Azure.Devices.Client.Exceptions
Microsoft.Azure.Devices.Client.Transport.Mqtt
Many existing client clients (e.g., RegistryManager, ServiceClient) were confusingly named and contained methods that weren't always consistent with the client's assumed responsibilities.
- It isn't always clear based on the name which classes were clients.
- It is difficult to know which client is needed for different operations.
- It is overly difficult to need to initialize each client and manage lifetime.
With the advent of v2, there is one client to initalize, IotHubServiceClient
.
From it, one will find subclients with names representing those kinds of operations.
For example, all operations for devices are found under the IotHubServiceClient.Devices
subclient, twins under IothubServiceClient.Twins
, and so forth.
The goal is to simplify client lifetime and operation discovery.
Existing clients had a mix of standard constructors (new RegistryManager(...)
) and static builder methods (DeviceClient.CreateFromConnectionString(...)
) that caused some confusion among users and prohibited mocking.
The factory methods have been removed and the addition of constructors in clients also enables unit test mocking.
Exception handling in the v1 SDK required a wide variety of exception types to be caught. Many exception types have been consolidated.
The v2 strategy can be grouped into 3 categories.
- Parameter validation and invalid client state. These are standard .NET exception types. The following exceptions may be observed:
ArgumentException
for basic parameter validation.- Also,
ArgumentNullException
andArgumentOutOfRangeException
inherit from it and provide more specific feedback.
- Also,
FormatException
when a string parameter format does not match what is expected (e.g., connection string with embedded key/value pairs).InvalidOperationException
- For example, when calling device client operations before explicility calling
IotHubDeviceClient.OpenAsync()
first. - When some runtime validated user input is invalid in some other way, for example, importing or exporting devices where there is a null value in the list.
ObjectDisposedException
when the client has been disposed but an operation has been issued.
- For example, when calling device client operations before explicility calling
- Handle canceled operations.
OperationCanceledException
when a user's cancelation token was signaled and the operation was stopped prematurely.All async operations accept an optional
CancellationToken
parameter. It is recommended to use cancelation tokens with a timed expiration as the SDK no longer has a default operation timeout. Without that, an operation could continue indefinitely, depending on retry policy.
- When an operation fails due to a service error or network issues prevent issuance.
IotHubClientException
for device client andIotHubServiceException
for service client for any exceptions arising from communication attempts with IoT hub.- Review the
IsTransient
property to determine if an exception is transient. - Review the
ErrorCode
property for specific, structured error details. - For the service client only, the
StatusCode
property is the HTTP status response. - The exception message is meant for human readable explanation.
- Inner exceptions may offer more insight and are worth logging out.
TrackingId
is for uniquely identifying specific operations and are useful in sharing with IoT hub support to assist them in more quickly identifying errors that may have been logged by the service.
- Review the
ProvisioningClientException
for provisioning device client andProvisioningServiceException
for provisioning service client for exceptions arising from communication attempts with DPS.As with the IoT hub exceptions, primarily observe the
IsTransient
andErrorCode
properties. Other properties may be valuable for logging or debugging.
The IoT hub device client now caches the latest connection status information so the client app does not have to do it. It can be found at IotHubDeviceClient.ConnectionStatusInfo
(same property for module client). It is useful, for example, in avoiding starting an operation when the client is temporarily disconnected.
In the connection status callback, a third value, RecommendedAction
, is now provided to assist in knowing what action the client app is recommended to take. Previously, one would need to know based on every status and reason what action the client app should take, a nearly impossible task without reading a code sample.
After the v2 SDK is released as GA (general availability), meaning it is no longer only in preview, there will be one final LTS of the v1 SDK released that we will support like any other LTS release (security bug fixes, some non-security bug fixes as needed). Users are still encouraged to migrate to v2 when they have the chance.
For more details on LTS releases, see this document.
This guide has been organized by the previous clients. Find a client you currently use below, read the table of API name changes and use that to update your client app for when type and property names have changed.
- Many models have changed to be nullable to prevent default values (e.g., DateTimeOffset defaults to Jan 01 0001) instead of null.
- This may mean having to change referencing code to use the
Value
property or the null conditional operator (e.g., given a model namedmodel
with a nullable property namedNullableProperty
:model.NullableProperty.Value.SubProperty
ormodel.NullableProperty?.SubProperty
) to avoid a NullReferenceException.
- This may mean having to change referencing code to use the
- Most properties that were
DateTime
have changed to the preferredDateTimeOffset
.
- The transport default has changed from AMQP (TCP with web socket fail over) to MQTT TCP.
- To override the transport default, create an instance of
IotHubClientOptions
and pass an instance of the transport settings you wish to use (i.e.,IotHubClientMqttSettings
,IotHubClientAmqpSettings
). - TCP will be the default. For web socket, pass
IotHubClientTransportProtocol.WebSocket
to the transport settings constructors.
- To override the transport default, create an instance of
- HTTP has been removed as a transport option.
It had very limited support across the device options and some APIs behaved differently. We feel this caused more harm than good and as such it was best to remove.
- Some options that were previously set in the
DeviceClient
constructor are now in the optionalIotHubClientOptions
parameter. - The connection status callback parameters have changed. Instead of two parameters, a class with several properties is provided.
- Two properties enum values are mostly the same as before, with some renames (underscores removed) and obsolete members removed.
- A new property has been added with a recommended action, which a device developer may observe or ignore.
- The file upload method has been split into the three individual steps that this method used to take. See this file upload sample for an example of how to do file upload using these discrete steps.
- Cloud-to-device messages can be received by calling
SetMessageIncomingMessageCallbackAsync
and providing a callback. Users no longer need to poll for messages withReceiveAsync
. - Support for sending a batch of events over MQTT by calling
SendEventBatchAsync
has been removed. MQTT v3.1 does not support true batching but instead sends the messages one after another. True batching is still supported over AMQP. - Several callback handler set methods and definitions have changed, losing the
userContext
parameter which was deemed unnecessary and a vestige of the C device client. - The exponential back-off retry policy has updated parameters and logic.
- Remote certificate validation is no natively longer supported for AMQP web socket connections.
- The supported workaround is to provide a client web socket instance in the client options.
- The authentication classes for devices and modules have been consolidated.
- Reduced access levels to classes and methods that were never intended to be public where possible.
- The device and module clients now only support
IAsyncDisposable
, which will ensureCloseAsync()
is called before disposing.- The syntax for this might be quite new for some and feel awkward. You can choose from the following options:
- Manually call
await client.DisposeAsync();
. - Initialize the client with the await keyword:
await using client = new IotHubDeviceClient(...);
. The client will be disposed when it goes out of scope.
- Manually call
- For more information, see https://learn.microsoft.com/dotnet/api/system.iasyncdisposable.
DirectMethodRequest
constructor for module-initiated direct method calls requires the method name as a parameter; the property is not settable directly.
- The syntax for this might be quite new for some and feel awkward. You can choose from the following options:
- The device and module clients now have a property (e.g.,
IotHubDeviceClient.ConnectionStatusInfo
) with the latest connection status information on it, eliminating the need for a connection status callback method to cache the latest values. - Added support for setting a client web socket instance in the client options so that users can have better control over AMQP web socket connections.
- The library now includes 2 new
IIotHubClientRetryPolicy
implementations:IotHubClientIncrementalDelayRetryPolicy
andIotHubClientFixedDelayRetryPolicy
. - The client can now be re-opened after it has been closed, removing the need to close/dispose/initialize/open; simply initialize/open, then if necessary close/open, and finally when done dispose.
Be advised, subscriptions do not carry over when the client is re-opened.
It cannot be re-opened after disposal.
DirectMethodResponse
now has a methodTryGetValue<T>
to deserialize the payload to a type of your choice. One usage of this method is to deserialize the direct method response received by an edge module client after it invokes a direct method on an edge device or an edge module connected to the same edge hub.
v1 API | Equivalent v2 API | Notes |
---|---|---|
DeviceClient |
IotHubDeviceClient |
Specify the service it is a device client for. |
ITransportSettings |
IotHubClientTransportSettings |
Disambiguate with other clients. |
IRetryPolicy |
IIotHubClientRetryPolicy |
Disambiguate with other clients. |
DeviceClient.Dispose() |
IotHubDeviceClient.DisposeAsync() |
Ensures the client is closed before disposing. |
DeviceClient.SendEventAsync(...) |
IotHubDeviceClient.SendTelemetryAsync(TelemetryMessage, ...) |
Even our public documentation calls this telemetry, so we renamed the method to describe this better.¹ |
DeviceClient.SendEventBatchAsync(...) |
IotHubDeviceClient.SendTelemetryAsync(IEnumerable<TelemetryMessage>, ...) |
This is now only supported over AMQP. Support over MQTT has been removed. Also, see¹. |
DeviceClient.SetConnectionStatusChangesHandler(...) |
IotHubDeviceClient.ConnectionStatusChangeCallback |
Local operation doesn't require being a method. |
DeviceClient.SetReceiveMessageHandlerAsync(...) |
IotHubDeviceClient.SetIncomingMessageCallbackAsync(...) |
Disambiguate from telemetry messages. |
SetMethodDefaultHandlerAsync |
SetDirectMethodCallbackAsync |
Use full name of the operation type.⁴ |
SetMethodHandlerAsync |
Deprecated. | Handler by method name is deprecated. Use SetDirectMethodCallbackAsync and filter by method name in the callback. |
DeviceClient.GetTwinAsync(...) |
IotHubDeviceClient.GetTwinPropertiesAsync(...) |
The device client doesn't get the full twin, just the properties so this helps avoid that confusion.² |
Twin |
TwinProperties |
See² |
Twin.Properties.Desired |
TwinProperties.Desired |
See² |
Twin.Properties.Reported |
TwinProperties.Reported |
See² |
MessageResponse |
MessageAcknowledgement |
It isn't a full response, just a simple acknowledgement. |
MessageResponse.Completed |
MessageAcknowledgement.Complete |
Use imperative tense for acknowledgements. |
Message |
TelemetryMessage , IncomingMessage |
Distinguished between the different messaging operations. |
Message.CreationTimeUtc |
TelemetryMessage.CreatedOnUtc , IncomingMessage.CreatedOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC).³ |
Message.EnqueuedTimeUtc |
TelemetryMessage.EnqueuedtimeUtc , IncomingMessage.EnqueuedTimeUtc |
See³ |
Message.ExpiryTimeUtc |
TelemetryMessage.ExpiresOnUtc , IncomingMessage.ExpiresOnUtc |
See³ |
Message.GetBytes |
IncomingMessage.GetPayloadAsBytes |
More descriptive name. |
DeviceClient.SetRetryPolicy(...) |
IotHubClientOptions.RetryPolicy |
Should be specified at initialization time, and putting it in the client options object reduces the client API surface. |
ExponentialBackOff |
IotHubClientExponentialBackOffRetryPolicy |
Clarify it is a retry policy. |
MethodRequest |
DirectMethodRequest |
See⁴ |
MethodResponse |
DirectMethodResponse |
See⁴ |
IotHubException |
IotHubClientException |
Specify the exception is for Hub device and module client only. |
DeviceAuthenticationWithTokenRefresh and ModuleAuthenticationWithTokenRefresh |
ClientAuthenticationWithTokenRefresh |
More descriptive naming and reduce duplication.⁵ |
DeviceAuthenticationWithToken and ModuleAuthenticationWithToken |
ClientAuthenticationWithSharedAccessSignature |
See⁵ |
DeviceAuthenticationWithSakRefresh and ModuleAuthenticationWithSakRefresh |
ClientAuthenticationWithSharedAccessKeyRefresh |
See⁵ |
DeviceAuthenticationWithX509Certificate and ModuleAuthenticationWithX509Certificate |
ClientAuthenticationWithX509Certificate |
See⁵ |
AuthenticationWithTokenRefresh.SafeCreateNewToken(...) and derived classes |
ClientAuthenticationWithTokenRefresh.SafeCreateNewTokenAsync(...) and derived classes. |
Async suffix for async methods. |
TwinCollection |
DesiredProperties , ReportedProperties |
Distinguished between the desired and reported properties. |
The device client and module client share a lot of API surface and underlying implementation. See changes to the IoT hub device client.
v1 API | Equivalent v2 API | Notes |
---|---|---|
SetMessageHandlerAsync |
SetIncomingMessageCallbackAsync |
Renamed to be more descriptive about the callback being set. |
SetInputMessageHandlerAsync |
SetIncomingMessageCallbackAsync |
The input parameter is deprecated; the callback can observe and filter using the IncomingMessage.InputName property. |
ModuleClient.SendEventAsync(string outputName, ...) |
IotHubModuleClient.SendMessageToRouteAsync(string outputName, ...) |
Change the name to be more descriptive about sending messages between Edge modules.¹ |
ModuleClient.SendEventBatchAsync(string outputName, ...) |
IotHubModuleClient.SendMessagesToRouteAsync(string outputName, ...) |
See¹ |
MethodRequest |
EdgeModuleDirectMethodRequest |
Use full name of the operation type. Create a type that is meant to be used only with IotHubModuleClient for invoking methods on an edge device or an edge module connected to the same edge hub. |
N/A
v1 API | Equivalent v2 API | Notes |
---|---|---|
ModuleClient |
IotHubModuleClient |
Specify the service it is a device client for. |
This service client has probably seen more updates than any other client library in this v2. What was a loose affiliation of separate clients is now a consolidated client with organized subclients by operation type.
IotHubConnectionStringBuilder
has been removed. It was not required as part of any API calls and was intended to be internal.
These span across all service clients.
v1 API | Equivalent v2 API | Notes |
---|---|---|
ErrorCode |
IotHubServiceErrorCode |
See⁵ |
IotHubException |
OperationCanceledException |
When a cancelation token is signaled. |
IotHubException |
IotHubServiceException |
When an invalid delivery acknowledgement was specified. |
ConfigurationNotFoundException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ConfigurationNotFound . |
DeviceAlreadyExistsException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.DeviceAlreadyExists . |
DeviceMaximumQueueDepthExceededException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.DeviceMaximumQueueDepthExceeded . |
DeviceNotFoundException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.DeviceNotFound . |
InvalidProtocolVersionException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.InvalidProtocolVersion . |
IotHubSuspendedException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.IotHubSuspended . |
IotHubThrottledException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ThrottlingException . |
IotHubCommunicationException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.Unknown when network errors occurred. |
IotHubCommunicationException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.Unknown when an operation timed out. |
IotHubNotFoundException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.Unknown . |
JobNotFoundException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.JobNotFound . |
JobQuotaExceededException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.JobQuotaExceeded . |
MessageTooLargeException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.MessageTooLarge . |
ModuleAlreadyExistsException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ModuleAlreadyExistsOnDevice . |
ModuleNotFoundException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ModuleNotFound . |
PreconditionFailedException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.PreconditionFailed . |
QuotaExceededException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.IotHubQuotaExceeded . |
ServerBusyException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ServiceUnavailable . |
ServerErrorException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ServerError . |
ThrottlingException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.ThrottlingException or IotHubServiceErrorCode.ThrottlingBacklogTimeout . |
TooManyDevicesException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.TooManyDevices . |
TooManyModulesOnDeviceException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.TooManyModulesOnDevice . |
UnauthorizedException |
IotHubServiceException |
With an ErrorCode of IotHubServiceErrorCode.IotHubUnauthorizedAccess . |
DeviceInvalidResultCountException |
Deprecated. | Was not thrown by v1 client¹. |
DeviceMessageLockLostException |
Deprecated. | See¹ |
IotHubSerializationVersionException |
Deprecated. | See¹ |
JobCancelledException |
Deprecated. | See¹ |
- Operations that offer concurrency protection using
ETag
s, now take a parameteronlyIfUnchanged
that relies on the ETag property of the submitted entity. IotHubServiceClient.Query.Create<T>(...)
now returns anAsyncPageable
of the queried results.- Iterate on entries by using
await foreach (ClientTwin queriedTwin in client.Query.Create<ClientTwin>(queryText))
. - Iterate on pages of entries by using
await foreach (Page<ClientTwin> queriedTwinPage in _client.Query.Create<ClientTwin>(queryText).AsPages())
.
- Iterate on entries by using
JobProperties
properties that hold Azure Storage SAS URIs are now of typeSystem.Uri
instead ofstring
.JobProperties
has been split into several classes with only the necessary properties for the specified operation.- See
ExportJobProperties
,ImportJobProperties
, andIotHubJobResponse
.
- See
- Twin.Tags is now of type
IDictionary<string, object>
.
JobProperties
now has a helper propertyIsFinished
which returns true if the job status is in a terminal state.TryGetValue<T>(...)
is available off of the desired and reported properties onClientTwinProperties
.- Added type
ImportJobError
to deserialize the error details of an import job.
v1 API | Equivalent v2 API | Notes |
---|---|---|
RegistryManager |
IotHubServiceClient , subclients: Devices , Twins , Configurations , etc. |
|
RegistryManager.AddDeviceAsync(Device, ...) |
IotHubServiceClient.Devices.CreateAsync(Device, ...) |
|
RegistryManager.AddDevices2Async(...) |
IotHubServiceClient.Devices.CreateAsync(IEnumerable<Device>,...) |
|
RegistryManager.RemoveDeviceAsync(...) |
IotHubServiceClient.Devices.DeleteAsync(...) |
|
Device.ConnectionStateUpdatedTime |
Device.ConnectionStateUpdatedOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC).¹ |
Device.StatusUpdatedTime |
Device.StatusUpdatedOnUtc |
See¹ |
Device.LastActivityTime |
Device.LastActiveOnUtc |
See¹ |
Device.Capabilities.IotEdge |
Device.Capabilities.IsIotEdge |
Boolean properties should start with a verb, usually "Is". |
Module.ConnectionStateUpdatedTime |
Module.ConnectionStateUpdatedOnUtc |
See¹ |
Module.LastActivityTime |
Module.LastActiveOnUtc |
See¹ |
RegistryManager.GetTwinAsync(...) |
IotHubServiceClient.Twins.GetAsync(...) |
|
RegistryManager.UpdateTwinAsync(...) |
IotHubServiceClient.Twins.UpdateAsync(...) |
|
Twin |
TwinProperties |
The device only gets properties, not the full twin. |
Twin.StatusUpdatedOn |
ClientTwin.StatusUpdatedOnUtc |
See¹ |
Twin.LastActivityOn |
ClientTwin.LastActiveOnUtc |
See¹ |
TwinCollection |
ClientTwinProperties |
"Client" is a word we often use to indicate the device- or module-side of the data-plane.² |
TwinCollection.GetLastUpdatedOn() |
ClientTwinProperties.Metadata.LastUpdatedOnUtc |
See¹ |
TwinCollectionValue |
ClientTwinProperties.TryGetValue(...) |
Now just get the property as a type you know expect to be. |
Metadata |
ClientTwinMetadata |
See² |
Metadata.LastUpdatedOn |
ClientTwinMetadata.LastUpdatedOnUtc |
See¹ |
AuthenticationType |
ClientAuthenticationType |
See² |
DeviceConnectionState |
ClientConnectionState |
See² |
DeviceStatus |
ClientStatus |
See² |
DeviceCapabilities |
ClientCapabilities |
See² |
RegistryManager.CreateQuery(...) |
IotHubServiceClient.Query.Create<T>(...) |
|
RegistryManager.AddConfigurationAsync(...) |
IotHubServiceClient.Configurations.CreateAsync(...) |
|
RegistryManager.GetConfigurationsAsync(int maxCount) |
IotHubServiceClient.Configurations.GetAsync(int maxCount) |
|
RegistryManager.RemoveConfigurationAsync(...) |
IotHubServiceClient.Configurations.DeleteAsync(...) |
|
RegistryManager.ImportDevicesAsync(...) |
IotHubServiceClient.Devices.ImportAsync(...) |
|
RegistryManager.ExportDevicesAsync(...) |
IotHubServiceClient.Devices.ExportAsync(...) |
|
JobProperties.CreateForImportJob(...) |
new JobProperties(Uri, Uri) |
|
JobProperties.CreateForExportJob(...) |
new JobProperties(Uri, bool) |
|
RegistryManager.GetJobAsync(...) |
IotHubServiceClient.Devices.GetJobAsync(...) |
|
RegistryManager.CancelJobAsync(...) |
IotHubServiceClient.Devices.CancelJobAsync(...) |
|
JobProperties.Type |
JobProperties.JobType |
Other parts of the API use "JobType" and "Type" is otherwise too ambiguous with System.Type . |
ExportImportDevice.Properties.DesiredProperties |
ExportImportDevice.Properties.Desired |
|
ExportImportDevice.Properties.ReportedProperties |
ExportImportDevice.Properties.Reported |
- The
Message
class no longer requires disposal! FeedbackReceiver
is now a callback assigned to theMessageFeedbackProcessor
property.GetFileNotificationReceiver(...)
is now a callback assigned toFileUploadNotificationProcessor
property. These methods return a callback value.FileUploadNotification.BlobUriPath
was a string and is now of typeSystem.Uri
.
- The library now includes
IIotHubServiceRetryPolicy
implementations:IotHubServiceExponentialBackoffRetryPolicy
,IotHubServiceFixedDelayRetryPolicy
,IotHubServiceIncrementalDelayRetryPolicy
andIotHubServiceNoRetry
, which can be set viaIotHubServiceClientOptions.RetryPolicy
. DirectMethodClientResponse
now has a methodTryGetValue<T>
to deserialize the payload to a type of your choice.- Added
ImportJobError
class to help deserialize errors from device/module/configuration import job.- Use the
ImportErrorsBlobName
to load the output errors file, if it exists, in the blob container specified inImportJobProperties.InputBlobContainerUri
.
- Use the
IsFinished
convenience property now exists onCloudToDeviceMethodScheduledJob
,ScheduledJob
, andTwinScheduledJob
which is true whenStatus
isCompleted
,Failed
, orCancelled
.
v1 API | Equivalent v2 API | Notes |
---|---|---|
ServiceClient |
IotHubServiceClient , subclients Messages , MessageFeedback , FileUploadNotifications |
|
ServiceClient.SendAsync(...) |
IotHubServiceClient.Messages.SendAsync(...) |
|
Message |
OutgoingMessage |
Disambiguate from the other kinds of messages used in IoT hub. |
Message.ExpiryTimeUtc |
OutgoingMessage.ExpiresOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC).¹ |
Message.CreationTimeUtc |
OutgoingMessage.CreatedOnUtc |
See¹ |
ServiceClient.InvokeDeviceMethodAsync(...) |
IotHubServiceClient.DirectMethods.InvokeAsync(...) |
|
CloudToDeviceMethod |
DirectMethodServiceRequest |
Disambiguate from types in the device client.² |
CloudToDeviceMethodResult |
DirectMethodClientResponse |
See² |
CloudToDeviceMethodResult.GetPayloadAsJson() |
DirectMethodClientResponse.PayloadAsString |
|
ServiceClient.GetFeedbackReceiver(...) |
IotHubServiceClient.MessageFeedback.MessageFeedbackProcessor |
|
ServiceClient.GetFileNotificationReceiver() |
IotHubServiceClient.FileUploadNotifications.FileUploadNotificationProcessor |
|
IotHubException |
IotHubServiceException |
Specify the exception is for Hub service client only. |
JobClient.ScheduleTwinUpdateAsync(...)
previously returned aJobResponse
, now returnsScheduledJob
.ScheduleJobs.GetAsync()
return type has changed toAsyncPageable<ScheduledJob>
fromIEnumerable<JobResponse>
.
v1 API | Equivalent v2 API | Notes |
---|---|---|
JobsClient |
IotHubServiceClient , subclients ScheduledJobs |
|
JobClient.GetJobAsync(...) |
IotHubServiceClient.ScheduledJobs.GetAsync(...) |
|
JobClient.CreateQuery() |
IotHubServiceClient.ScheduledJobs.CreateQuery() |
|
JobsClient.ScheduleTwinUpdateAsync(...) |
IotHubServiceClient.ScheduledJobs.ScheduledTwinUpdateAsync(...) |
|
JobType.ExportDevices |
JobType.Export |
Matches the actual value expected by the service.¹ |
JobType.ImportDevices |
JobType.Import |
See¹ |
- Methods on this client have new, simpler return types. Check each method documentation comments for details.
- Formerly
HttpOperationResponse
and now specific per method call. To get the body of the response before it would have beenHttpOperationResponse.Body
and now it will be, for example,DigitalTwinGetReponse<T>.DigitalTwin
.
- Formerly
- The update method takes an
InvokeDigitalTwinCommandOptions
which holds the optional payload, connect timeout, and response timeout. - The `HttpOperationException will no longer be thrown. Exceptions that might be thrown are documented on each method.
UpdateDigitalTwinOptions.IfMatch
type changed fromstring
toETag
.
v1 API | Equivalent v2 API | Notes |
---|---|---|
DigitalTwinClient |
IotHubServiceClient.DigitalTwins |
|
DigitalTwinClient.GetDigitalTwinAsync(...) |
IotHubServiceClient.DigitalTwins.GetAsync(...) |
|
DigitalTwinClient.UpdateDigitalTwinAsync(...) |
IotHubServiceClient.DigitalTwins.UpdateAsync(...) |
|
WritableProperty.LastUpdatedOn |
WritableProperty.LastUpdatedOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC). |
UpdateOperationsUtility |
Removed. | Azure.JsonPatchDocument from Azure.Core package is recommended. |
- The security providers that are used in conjunction with this client have changed. See this section for more details.
- The previous way of providing transport level settings,
ProvisioningTransportHandler
, has been replaced withProvisioningClientTransportSettings
. - TPM support removed. The library used for TPM operations is broken on Linux and support for it is being shutdown. We'll reconsider how to support HSM.
- HTTP has been removed as a transport option to keep the provisioning device SDK consistent with IoT hub device SDK transport options.
- Added support for setting a client web socket instance in the client options so that users can have better control over AMQP web socket connections.
- Added support for setting the web socket level keep alive interval for AMQP web socket connections.
- Added support for setting the remote certificate validation callback for AMQP TCP connections.
- The library now includes
IProvisioningClientRetryPolicy
implementations:ProvisioningClientExponentialBackoffRetryPolicy
,ProvisioningClientFixedDelayRetryPolicy
,ProvisioningClientIncrementalDelayRetryPolicy
andProvisioningClientNoRetry
, which can be set viaProvisioningClientOptions.RetryPolicy
. - ProvisioningRegistrationSubstatus.ReprovisionedToInitalAssignment value added meaning the device has been reprovisioned to a previously assigned IoT hub.
DeviceRegistrationResult
now has a methodTryGetPayload<T>(...)
.ProvisioningClientTransportSettings
and derived classes now have settable propertyCertificateRevocationCheck
. Remote certificate validation check is turned off by default.- For connections over AMQP, this check is used in conjunction with the property
RemoteCertificateValidationCallback
onProvisioningClientTransportSettings
. - For connections over MQTT, this check is set directly on the TLS settings.
- For connections over AMQP, this check is used in conjunction with the property
v1 API | Equivalent v2 API | Notes |
---|---|---|
ProvisioningDeviceClient.Create(...) |
new ProvisioningDeviceClient(...) |
|
ProvisioningDeviceClient initializer parameter transportHandler replaced |
ProvisioningClientOptions parameter added |
|
ProvisioningRegistrationAdditionalData |
RegistrationRequestPayload |
|
ProvisioningRegistrationAdditionalData.JsonData |
RegistrationRequestPayload.Payload |
|
DeviceRegistrationResult.CreatedDateTimeUtc |
DeviceRegistrationResult.CreatedOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC).¹ |
DeviceRegistrationResult.LastUpdatedDateTimeUtc |
DeviceRegistrationResult.LastUpdatedOnUtc |
See¹ |
ProvisioningTransportException |
ProvisioningClientException |
|
PnpConvention |
ModelIdPayload |
Added model class to replace a JSON helper. |
ProvisioningRegistrationStatusType |
ProvisioningRegistrationStatus |
Renamed, because not a type.² |
ProvisioningRegistrationSubstatusType |
ProvisioningRegistrationSubstatus |
See² |
ProvisioningServiceClient.DeviceRegistrationStates.CreateEnrollmentGroupQuery(...)
now returns anAsyncPageable
of the queried results.- Iterate on entries by using
await foreach (DeviceRegistrationState registrationState in client.DeviceRegistrationStates.CreateEnrollmentGroupQuery(queryText))
. - Iterate on pages of entries by using
await foreach (Page<DeviceRegistrationState> registrationStatePage in client.DeviceRegistrationStates.CreateEnrollmentGroupQuery(queryText).AsPages())
.
- Iterate on entries by using
ProvisioningServiceClient.IndividualEnrollments.CreateQuery(...)
now returns anAsyncPageable
of the queried results.- Iterate on entries by using
await foreach (IndividualEnrollment enrollment in client.IndividualEnrollments.CreateQuery(queryText))
. - Iterate on pages of entries by using
await foreach (Page<IndividualEnrollment> enrollmentsPage in client.IndividualEnrollments.CreateQuery(queryText).AsPages())
.
- Iterate on entries by using
ProvisioningServiceClient.EnrollmentGroups.CreateQuery(...)
now returns anAsyncPageable
of the queried results.- Iterate on entries by using
await foreach (EnrollmentGroup enrollment in client.EnrollmentGroups.CreateQuery(queryText))
. - Iterate on pages of entries by using
await foreach (Page<EnrollmentGroup> enrollmentsPage in client.EnrollmentGroups.CreateQuery(queryText).AsPages())
.
- Iterate on entries by using
- ETag fields on the classes
IndividualEnrollment
,EnrollmentGroup
, andDeviceRegistrationState
are now taken as theAzure.ETag
type instead of strings. - Twin.Tags is now of type
IDictionary<string, object>
. CustomAllocationDefinition.WebhookUri
is now of typeSystem.Uri
instead ofSystem.String
.
- The library now includes
IProvisioningServiceRetryPolicy
implementations:ProvisioningServiceExponentialBackoffRetryPolicy
,ProvisioningServiceFixedDelayRetryPolicy
,ProvisioningServiceIncrementalDelayRetryPolicy
andProvisioningServiceNoRetry
, which can be set viaProvisioningServiceOptions.RetryPolicy
.
v1 API | Equivalent v2 API | Notes |
---|---|---|
ProvisioningServiceClient.CreateFromConnectionString(...) |
new ProvisioningServiceClient() |
Constructors enable mocking for unit tests. |
QuerySpecification |
Type removed from public API. | Methods take the parameters directly. |
ProvisioningServiceClient.CreateOrUpdateIndividualEnrollmentAsync(IndividualEnrollment, ...) |
ProvisioningServiceClient.IndividualEnrollments.CreateOrUpdateAsync(IndividualEnrollment, ...) |
|
ProvisioningServiceClient.GetIndividualEnrollmentAsync(IndividualEnrollment, ...) |
ProvisioningServiceClient.IndividualEnrollments.GetAsync(IndividualEnrollment, ...) |
|
ProvisioningServiceClient.DeleteIndividualEnrollmentAsync(...) |
ProvisioningServiceClient.IndividualEnrollments.DeleteAsync(...) |
|
ProvisioningServiceClient.GetIndividualEnrollmentAttestationAsync(...) |
ProvisioningServiceClient.IndividualEnrollments.GetAttestationAsync(...) |
|
ProvisioningServiceClient.CreateIndividualEnrollmentQuery(...) |
ProvisioningServiceClient.IndividualEnrollments.CreateQuery(...) |
|
ProvisioningServiceClient.RunBulkEnrollmentOperationAsync(...) |
ProvisioningServiceClient.IndividualEnrollments.RunBulkEnrollmentOperationAsync(...) |
|
ProvisioningServiceClient.CreateOrUpdateEnrollmentGroupAsync(EnrollmentGroup, ...) |
ProvisioningServiceClient.EnrollmentGroups.CreateOrUpdateAsync(EnrollmentGroup, ...) |
|
ProvisioningServiceClient.GetEnrollmentGroupAsync(EnrollmentGroup, ...) |
ProvisioningServiceClient.EnrollmentGroups.GetAsync(EnrollmentGroup, ...) |
|
ProvisioningServiceClient.DeleteEnrollmentGroupAsync(...) |
ProvisioningServiceClient.EnrollmentGroups.DeleteAsync(...) |
|
ProvisioningServiceClient.GetEnrollmentGroupAttestationAsync(...) |
ProvisioningServiceClient.EnrollmentGroups.GetAttestationAsync(...) |
|
ProvisioningServiceClient.CreateEnrollmentGroupQuery(...) |
ProvisioningServiceClient.EnrollmentGroups.CreateQuery(...) |
|
ProvisioningServiceClient.GetDeviceRegistrationStateAsync(...) |
ProvisioningServiceClient.DeviceRegistrationStates.GetAsync(...) |
|
ProvisioningServiceClient.DeleteDeviceRegistrationStateAsync(...) |
ProvisioningServiceClient.DeviceRegistrationStates.DeleteAsync(...) |
|
ProvisioningServiceClient.CreateEnrollmentGroupRegistrationStateQuery(...) |
ProvisioningServiceClient.DeviceRegistrationStates.CreateEnrollmentGroupQuery(...) |
|
DeviceRegistrationState.CreatedDateTimeUtc |
DeviceRegistrationState.CreatedOnUtc |
Conforming to the naming guidelines by the Azure SDK team, where DateTime/Offset types have an "On" suffix (and "Utc" suffix when explicitly in UTC).¹ |
DeviceRegistrationState.LastUpdatedDateTimeUtc |
DeviceRegistrationState.LastUpdatedOnUtc |
See¹ |
EnrollmentGroup.EnrollmentGroupId |
EnrollmentGroup.Id |
Simplify property name. |
EnrollmentGroup.CreatedDateTimeUtc |
EnrollmentGroup.CreatedOnUtc |
See¹ |
EnrollmentGroup.LastUpdatedDateTimeUtc |
EnrollmentGroup.LastUpdatedOnUtc |
See¹ |
IndividualEnrollment.CreatedDateTimeUtc |
IndividualEnrollment.CreatedOnUtc |
See¹ |
IndividualEnrollment.LastUpdatedDateTimeUtc |
IndividualEnrollment.LastUpdatedOnUtc |
See¹ |
Twin |
InitialTwin |
Disambiguate between similar types in the IoT hub service and device clients, and make it clearer that this is only represents the initial state of the device's twin.² |
Twin.StatusUpdatedOn |
InitalTwin.StatusUpdatedOnUtc |
See¹ |
Twin.LastActivityOn |
InitialTwin.LastActiveOnUtc |
See¹ |
TwinCollection |
InitialTwinPropertyCollection |
See² |
TwinCollection.GetLastUpdatedOn() |
InitialTwinProperties.GetLastUpdatedOnUtc() |
See¹ |
TwinCollectionValue |
InitialTwinPropertyValue |
See² |
TwinCollectionValue.GetLastUpdatedOn() |
InitialTwinPropertyValue.GetLastUpdatedOnUtc() |
See¹ |
TwinCollectionArray |
InitialTwinPropertyArray |
See² |
TwinCollectionArray.GetLastUpdatedOn() |
InitialTwinPropertyArray.GetLastUpdatedOnUtc() |
See¹ |
Metadata |
InitialTwinMetadata |
See² |
Metadata.LastUpdatedOn |
InitialTwinMetadata.LastUpdatedOnUtc |
See¹ |
DeviceCapabilities |
InitialTwinCapabilities |
See² |
X509Attestation.CreateFromCAReferences(...) |
X509Attestation.CreateFromCaReferences(...) |
Pascal casing.³ |
X509Attestation.CAReferences |
X509Attestation.CaReferences |
See³ |
X509CAReferences |
X509CaReferences |
See³ |
X509CertificateInfo.SHA1Thumbprint |
X509CertificateInfo.Sha1Thumbprint |
See³ |
X509CertificateInfo.SHA256Thumbprint |
X509CertificateInfo.Sha256Thumbprint |
See³ |
ProvisioningServiceClientException |
ProvisioningServiceException |
|
ProvisioningClientCapabilities.IotEdge |
InitialClientCapabilities.IsIotEdge |
Boolean properties should start with a verb, usually "Is". |
Query |
Class removed | AsyncPageable type replaces this type and is returned by all query functions now |
QueryResult |
Class removed | AsyncPageable type replaces this type and is returned by all query functions now |
QueryResultType |
Class removed | The AsyncPageable returned by each Query API has a hardcoded type now (IndividualEnrollment , EnrollmentGroup , or DeviceRegistrationState ) |
- Microsoft.Azure.Devices.Shared.SecurityProvider* types moved from Microsoft.Azure.Devices.Shared.dll into Microsoft.Azure.Devices.Provisioning.Client.dll and renamed.
- Derived
AuthenticationProvider
types no longer require disposal because of the base class. - TPM support removed. The library used for TPM operations is broken on Linux and support for it is being shutdown. We'll reconsider how to support HSM.
v1 API | Equivalent v2 API | Notes |
---|---|---|
SecurityProvider |
AuthenticationProvider |
These classes are about authentication, not security. ¹ |
SecurityProvider.GetRegistrationID() |
AuthenticationProvider.GetRegistrationId() |
|
SecurityProviderSymmetricKey |
AuthenticationProviderSymmetricKey |
See¹ |
SecurityProviderX509Certificate |
AuthenticationProviderX509 |
See¹ |
SecurityProviderX509 abstract base class |
removed | Unnecessary class. |
SecurityProviderTpm |
removed | Deprecated. |
Question:
What do I gain by upgrading to the v2 release?
Answer:
A smaller set of dependencies which makes for a lighter SDK overall, a more concise and clearer API surface, fewer types requiring disposal, and mocking in unit tests.
Question:
Will the v1 releases continue to be supported?
Answer:
The long-term support (LTS) releases of the v1 SDK will continue to have support during their lifespans. Newer features in the services will not be brought into to the v 1 SDKs. Users are encouraged to upgrade to the 2 SDK for all the best feature support, stability, and bug fixes.
Question:
Can I still upload files to Azure Storage using this SDK now that
DeviceClient.UploadToBlobAsync(...)
has been removed?
Answer:
Yes, you will still be able to upload files to Azure Storage after upgrading.
This SDK allows you to get the necessary credentials to upload your files to Azure Storage, but you will need to bring in the Azure Storage SDK as a dependency to do the actual file upload step.
For an example of how to do file upload after upgrading, see this sample.
Question:
I was using a deprecated API that was removed in the v2 upgrade, what should I do?
Answer:
The deprecated API in v1 documents which API you should use instead of the deprecated API. This guide also contains a mapping from v1 API to equivalent v2 API that should tell you which API to use.
Question:
After upgrading, some catch handlers no longer work because the API I was using no longer declares that it throws that exception. What exception type should be caught?
Answer:
The SDK has an updated exception strategy. Please refer to the documentation comments on each API where the relevant exceptions are documented.
Question:
Does this major version bump bring any changes to what platforms this SDK supports?
Answer:
These SDKs now only target .NET Standard 2.0, which is usable by all modern .NET targets, including .NET 6.0. The SDKs are tested with this matrix.
Question:
Is the v2 library backwards compatible?
Answer:
No. Please refer to Semver rules and see above in the Migration guide.