diff --git a/src/Microsoft.Devices.HardwareDevCenterManager/DevCenterHandler.cs b/src/Microsoft.Devices.HardwareDevCenterManager/DevCenterHandler.cs
index 5342748..84a2ed2 100644
--- a/src/Microsoft.Devices.HardwareDevCenterManager/DevCenterHandler.cs
+++ b/src/Microsoft.Devices.HardwareDevCenterManager/DevCenterHandler.cs
@@ -1,475 +1,474 @@
-/*++
- Copyright (c) Microsoft Corporation. All rights reserved.
-
- Licensed under the MIT license. See LICENSE file in the project root for full license information.
---*/
-using Microsoft.Devices.HardwareDevCenterManager.Utility;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.Devices.HardwareDevCenterManager.DevCenterApi
-{
- public class DevCenterHandler : IDisposable, IDevCenterHandler
- {
- private readonly DelegatingHandler AuthHandler;
- private readonly AuthorizationHandlerCredentials AuthCredentials;
- private readonly TimeSpan HttpTimeout;
- private Guid CorrelationId;
- private readonly LastCommandDelegate LastCommand;
- private DevCenterTrace Trace;
-
- ///
- /// Creates a new DevCenterHandler using the provided credentials
- ///
- /// Authorization credentials for HWDC
- /// Options object containing options necessary for DevCenterHandler to function
- public DevCenterHandler(AuthorizationHandlerCredentials credentials, DevCenterOptions options)
- {
- AuthCredentials = credentials;
- AuthHandler = new AuthorizationHandler(AuthCredentials, options.HttpTimeoutSeconds);
- HttpTimeout = TimeSpan.FromSeconds(options.HttpTimeoutSeconds);
- CorrelationId = options.CorrelationId;
- LastCommand = options.LastCommand;
- }
-
- private string GetDevCenterBaseUrl()
- {
- Uri returnUri = AuthCredentials.Url;
- if (AuthCredentials.UrlPrefix != null)
- {
- returnUri = new Uri(returnUri, AuthCredentials.UrlPrefix);
- }
- return returnUri.AbsoluteUri;
- }
-
- private const string DefaultErrorcode = "InvalidInput";
-
- ///
- /// Invokes HDC service with the specified options
- ///
- /// HTTP method to use
- /// URI of the service to invoke
- /// Content used as the request options
- /// Process the service return content
- /// Dev Center response with either an error or null if the operation was successful
- public async Task InvokeHdcService(
- HttpMethod method, string uri, object input, Action processContent)
- {
- DevCenterErrorReturn reterr = null;
- string RequestId = Guid.NewGuid().ToString();
- string json = JsonConvert.SerializeObject(input ?? new object());
-
- using (HttpClient client = new HttpClient(AuthHandler, false))
- {
- client.DefaultRequestHeaders.Add("MS-CorrelationId", CorrelationId.ToString());
- client.DefaultRequestHeaders.Add("MS-RequestId", RequestId);
- Trace = new DevCenterTrace()
- {
- CorrelationId = CorrelationId.ToString(),
- RequestId = RequestId,
- Method = method.ToString(),
- Url = uri,
- Content = json
- };
-
- LastCommand?.Invoke(new DevCenterErrorDetails()
+/*++
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Licensed under the MIT license. See LICENSE file in the project root for full license information.
+--*/
+
+using Microsoft.Devices.HardwareDevCenterManager.Utility;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.Devices.HardwareDevCenterManager.DevCenterApi;
+
+public class DevCenterHandler : IDisposable, IDevCenterHandler
+{
+ private readonly DelegatingHandler _authHandler;
+ private readonly AuthorizationHandlerCredentials _authCredentials;
+ private readonly TimeSpan _httpTimeout;
+ private Guid _correlationId;
+ private readonly LastCommandDelegate _lastCommand;
+ private DevCenterTrace _trace;
+
+ ///
+ /// Creates a new DevCenterHandler using the provided credentials
+ ///
+ /// Authorization credentials for HDC
+ /// Options object containing options necessary for DevCenterHandler to function
+ public DevCenterHandler(AuthorizationHandlerCredentials credentials, DevCenterOptions options)
+ {
+ _authCredentials = credentials;
+ _authHandler = new AuthorizationHandler(_authCredentials, options.HttpTimeoutSeconds);
+ _httpTimeout = TimeSpan.FromSeconds(options.HttpTimeoutSeconds);
+ _correlationId = options.CorrelationId;
+ _lastCommand = options.LastCommand;
+ }
+
+ private string GetDevCenterBaseUrl()
+ {
+ Uri returnUri = _authCredentials.Url;
+ if (_authCredentials.UrlPrefix != null)
+ {
+ returnUri = new Uri(returnUri, _authCredentials.UrlPrefix);
+ }
+ return returnUri.AbsoluteUri;
+ }
+
+ private const string _defaultErrorCode = "InvalidInput";
+
+ ///
+ /// Invokes HDC service with the specified options
+ ///
+ /// HTTP method to use
+ /// URI of the service to invoke
+ /// Content used as the request options
+ /// Process the service return content
+ /// Dev Center response with either an error or null if the operation was successful
+ public async Task InvokeHdcService(
+ HttpMethod method, string uri, object input, Action processContent)
+ {
+ DevCenterErrorReturn returnError = null;
+ string RequestId = Guid.NewGuid().ToString();
+ string json = JsonSerializer.Serialize(input ?? new object());
+
+ using HttpClient client = new(_authHandler, false);
+ client.DefaultRequestHeaders.Add("MS-CorrelationId", _correlationId.ToString());
+ client.DefaultRequestHeaders.Add("MS-RequestId", RequestId);
+
+ _trace = new DevCenterTrace()
+ {
+ CorrelationId = _correlationId.ToString(),
+ RequestId = RequestId,
+ Method = method.ToString(),
+ Url = uri,
+ Content = json
+ };
+
+ _lastCommand?.Invoke(new DevCenterErrorDetails()
+ {
+ Trace = _trace
+ });
+
+ client.Timeout = _httpTimeout;
+ Uri restApi = new(uri);
+
+ if (!(HttpMethod.Get == method || HttpMethod.Post == method || HttpMethod.Put == method))
+ {
+ return new DevCenterErrorDetails
+ {
+ HttpErrorCode = -1,
+ Code = _defaultErrorCode,
+ Message = "Unsupported HTTP method",
+ Trace = _trace
+ };
+ }
+
+ HttpResponseMessage infoResult = null;
+
+ try
+ {
+ if (HttpMethod.Get == method)
+ {
+ infoResult = await client.GetAsync(restApi);
+ }
+ else if (HttpMethod.Post == method)
+ {
+ StringContent postContent = new(json, System.Text.Encoding.UTF8, "application/json");
+ infoResult = await client.PostAsync(restApi, postContent);
+ }
+ else if (HttpMethod.Put == method)
+ {
+ infoResult = await client.PutAsync(restApi, null);
+ }
+ }
+ catch (TaskCanceledException tcex)
+ {
+ if (!tcex.CancellationToken.IsCancellationRequested)
+ {
+ // HDC time out, wait a bit and try again
+ Thread.Sleep(2000);
+ }
+ else
+ {
+ throw tcex;
+ }
+ }
+
+ string content = await infoResult.Content.ReadAsStringAsync();
+
+ if (infoResult.IsSuccessStatusCode)
+ {
+ processContent?.Invoke(content);
+ return null;
+ }
+
+ try
+ {
+ returnError = JsonSerializer.Deserialize(content);
+ }
+ catch (JsonException)
+ {
+ // Error is in bad format, return raw
+ returnError = new DevCenterErrorReturn()
+ {
+ HttpErrorCode = (int)infoResult.StatusCode,
+ StatusCode = infoResult.StatusCode.ToString("D") + " " + infoResult.StatusCode.ToString(),
+ Message = content
+ };
+ }
+
+ // returnError can be null when there is HTTP error
+ if (returnError == null || (returnError.HttpErrorCode.HasValue && returnError.HttpErrorCode.Value == 0))
+ {
+ returnError = new DevCenterErrorReturn()
+ {
+ HttpErrorCode = (int)infoResult.StatusCode,
+ StatusCode = infoResult.StatusCode.ToString("D") + " " + infoResult.StatusCode.ToString(),
+ Message = infoResult.ReasonPhrase
+ };
+ }
+
+ if (returnError.Error != null)
+ {
+ // include additional error details if missing from deserialization
+ returnError.Error.HttpErrorCode = (int)infoResult.StatusCode;
+
+ return returnError.Error;
+ }
+
+ return new DevCenterErrorDetails
+ {
+ Headers = infoResult.Headers,
+ HttpErrorCode = (int)infoResult.StatusCode,
+ Code = returnError.StatusCode,
+ Message = returnError.Message,
+ ValidationErrors = returnError.ValidationErrors,
+ Trace = _trace
+ };
+ }
+
+ ///
+ /// Invokes HDC service with the specified options
+ ///
+ /// HTTP method to use
+ /// URI of the service to invoke
+ /// Options for the new artifact to be generated
+ /// Whether the result has a single entity or multiple
+ /// Dev Center response with either an error or an artifact if created/queried successfully
+ public async Task> InvokeHdcService