From 84f1cf602993fb1629e97c5f8dba7a20bb628975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Carpenter=20=F0=9F=9B=AB?= Date: Sun, 25 Feb 2024 16:57:06 -0800 Subject: [PATCH] update DevCenterHandler --- .../DevCenterHandler.cs | 947 +++++++++--------- 1 file changed, 473 insertions(+), 474 deletions(-) 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( + HttpMethod method, string uri, object input, bool isMany) where Output : IArtifact + { + DevCenterResponse devCenterResponse = new(); + devCenterResponse.Error = await InvokeHdcService(method, uri, input, (content) => + { + if (isMany) + { + Response response = JsonSerializer.Deserialize>(content); + devCenterResponse.ReturnValue = response.Value; + } + else + { + Output ret = JsonSerializer.Deserialize(content); + if (ret.Id != null) + { + devCenterResponse.ReturnValue = new List { ret }; + } + } + }); + + devCenterResponse.Trace = _trace; + return devCenterResponse; + } + + /// + /// Invokes HDC GET request with the specified options + /// + /// URI of the service to invoke + /// Whether the result has a single entity or multiple + /// Dev Center response with either an error or a list of artifacts if queried successfully + public async Task> HdcGet(string uri, bool isMany) where Output : IArtifact + { + return await InvokeHdcService(HttpMethod.Get, uri, null, isMany); + } + + /// + /// Invokes HDC POST request with the specified options + /// + /// URI of the service to invoke + /// Options for the new artifact to be generated + /// Dev Center response with either an error or an artifact if created successfully + public async Task> HdcPost(string uri, object input) where Output : IArtifact + { + return await InvokeHdcService(HttpMethod.Post, uri, input, false); + } + + private const string _devCenterProductsUrl = "/hardware/products"; + + /// + /// Creates a new New Product in HDC with the specified options + /// + /// Options for the new Product to be generated + /// Dev Center response with either an error or a Product if created successfully + public async Task> NewProduct(NewProduct input) + { + string newProductsUrl = GetDevCenterBaseUrl() + _devCenterProductsUrl; + return await HdcPost(newProductsUrl, input); + } + + /// + /// Gets a list of products or a specific product from HDC + /// + /// Gets all products if null otherwise retrieves the specified product + /// Dev Center response with either an error or a Product if queried successfully + public async Task> GetProducts(string productId = null) + { + string getProductsUrl = GetDevCenterBaseUrl() + _devCenterProductsUrl; + + bool isMany = string.IsNullOrEmpty(productId); + if (!isMany) + { + getProductsUrl += "/" + Uri.EscapeDataString(productId); + } + + return await HdcGet(getProductsUrl, isMany); + } + + private const string _devCenterProductSubmissionUrl = "/hardware/products/{0}/submissions"; + + /// + /// Creates a new Submission in HDC with the specified options + /// + /// Specify the Product ID for this Submission + /// Options for the new Submission to be generated + /// Dev Center response with either an error or a Submission if created successfully + public async Task> NewSubmission(string productId, NewSubmission submissionInfo) + { + string newProductSubmissionUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterProductSubmissionUrl, Uri.EscapeDataString(productId)); + return await HdcPost(newProductSubmissionUrl, submissionInfo); + } + + /// + /// Gets a list of submissions or a specific submission from HDC + /// + /// Specify the Product ID for this Submission + /// Gets all submissions if null otherwise retrieves the specified submission + /// Dev Center response with either an error or a Submission if queried successfully + public async Task> GetSubmission(string productId, string submissionId = null) + { + string getProductSubmissionUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterProductSubmissionUrl, Uri.EscapeDataString(productId)); + + bool isMany = string.IsNullOrEmpty(submissionId); + if (!isMany) + { + getProductSubmissionUrl += "/" + Uri.EscapeDataString(submissionId); + } + + return await HdcGet(getProductSubmissionUrl, isMany); + } + + private const string _devCenterPartnerSubmissionUrl = + "/hardware/products/relationships/sourcepubliherid/{0}/sourceproductid/{1}/sourcesubmissionid/{2}"; + + /// + /// Gets shared submission info from a partner-shared Submission with partner ids + /// + /// Specify the Partner's Publisher ID for this Submission + /// Specify the Partner's Product ID for this Submission + /// Specify the Partner's Submission ID for this Submission + /// Dev Center response with either an error or a Submission if queried successfully with IDs for the querying account + public async Task> GetPartnerSubmission( + string publisherId, string productId, string submissionId) + { + string getProductSubmissionUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterPartnerSubmissionUrl, Uri.EscapeDataString(publisherId), + Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); + return await HdcGet(getProductSubmissionUrl, string.IsNullOrEmpty(submissionId)); + } + + private const string _devCenterProductSubmissionCommitUrl = "/hardware/products/{0}/submissions/{1}/commit"; + /// + /// Commits a Submission in HDC + /// + /// Specify the Product ID for the Submission to commit + /// Specify the Submission ID for the Submission to commit + /// Dev Center response with either an error or a true if committed successfully + public async Task> CommitSubmission(string productId, string submissionId) + { + string commitProductSubmissionUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterProductSubmissionCommitUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); + DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Post, commitProductSubmissionUrl, null, null); + DevCenterResponse ret = new() + { + Error = error, + ReturnValue = new List() + { + error == null + }, + Trace = _trace + }; + + if (error != null) + { + if ((error.HttpErrorCode.HasValue) && + (error.HttpErrorCode.Value == (int)System.Net.HttpStatusCode.BadGateway) && + (string.Compare(error.Code, "requestInvalidForCurrentState", true) == 0) + ) + { + // Communication issue likely caused the submission to already be done. Check. + DevCenterResponse SubmissionStatus = await GetSubmission(productId, submissionId); + if (SubmissionStatus.Error == null) { - Trace = Trace - }); - - client.Timeout = HttpTimeout; - Uri restApi = new Uri(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 StringContent(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 - { - reterr = JsonConvert.DeserializeObject(content); - } - catch (JsonReaderException) - { - // Error is in bad format, return raw - reterr = new DevCenterErrorReturn() - { - HttpErrorCode = (int)infoResult.StatusCode, - StatusCode = infoResult.StatusCode.ToString("D") + " " + infoResult.StatusCode.ToString(), - Message = content - }; - } - - // reterr can be null when there is HTTP error - if (reterr == null || (reterr.HttpErrorCode.HasValue && reterr.HttpErrorCode.Value == 0)) - { - reterr = new DevCenterErrorReturn() - { - HttpErrorCode = (int)infoResult.StatusCode, - StatusCode = infoResult.StatusCode.ToString("D") + " " + infoResult.StatusCode.ToString(), - Message = infoResult.ReasonPhrase - }; - } - - if (reterr.Error != null) - { - // include addtional error details if missing from deserialization - reterr.Error.HttpErrorCode = (int)infoResult.StatusCode; - - return reterr.Error; - } - - return new DevCenterErrorDetails - { - Headers = infoResult.Headers, - HttpErrorCode = (int)infoResult.StatusCode, - Code = reterr.StatusCode, - Message = reterr.Message, - ValidationErrors = reterr.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( - HttpMethod method, string uri, object input, bool isMany) where Output : IArtifact - { - DevCenterResponse retval = new DevCenterResponse(); - retval.Error = await InvokeHdcService(method, uri, input, (content) => - { - if (isMany) - { - Response ret = JsonConvert.DeserializeObject>(content); - retval.ReturnValue = ret.Value; - } - else - { - Output ret = JsonConvert.DeserializeObject(content); - if (ret.Id != null) - { - retval.ReturnValue = new List { ret }; - } - } - }); - - retval.Trace = Trace; - return retval; - } - - /// - /// Invokes HDC GET request with the specified options - /// - /// URI of the service to invoke - /// Whether the result has a single entity or multiple - /// Dev Center response with either an error or a list of artifacts if queried successfully - public async Task> HdcGet(string uri, bool isMany) where Output : IArtifact - { - return await InvokeHdcService(HttpMethod.Get, uri, null, isMany); - } - - /// - /// Invokes HDC POST request with the specified options - /// - /// URI of the service to invoke - /// Options for the new artifact to be generated - /// Dev Center response with either an error or an artifact if created successfully - public async Task> HdcPost(string uri, object input) where Output : IArtifact - { - return await InvokeHdcService(HttpMethod.Post, uri, input, false); - } - - private const string DevCenterProductsUrl = "/hardware/products"; - - /// - /// Creates a new New Product in HWDC with the specified options - /// - /// Options for the new Product to be generated - /// Dev Center response with either an error or a Product if created successfully - public async Task> NewProduct(NewProduct input) - { - string newProductsUrl = GetDevCenterBaseUrl() + DevCenterProductsUrl; - return await HdcPost(newProductsUrl, input); - } - - /// - /// Gets a list of products or a specific product from HWDC - /// - /// Gets all products if null otherwise retrieves the specified product - /// Dev Center response with either an error or a Product if queried successfully - public async Task> GetProducts(string productId = null) - { - string getProductsUrl = GetDevCenterBaseUrl() + DevCenterProductsUrl; - - bool isMany = string.IsNullOrEmpty(productId); - if (!isMany) - { - getProductsUrl += "/" + Uri.EscapeDataString(productId); - } - - return await HdcGet(getProductsUrl, isMany); - } - - private const string DevCenterProductSubmissionUrl = "/hardware/products/{0}/submissions"; - - /// - /// Creates a new Submission in HWDC with the specified options - /// - /// Specifiy the Product ID for this Submission - /// Options for the new Submission to be generated - /// Dev Center response with either an error or a Submission if created successfully - public async Task> NewSubmission(string productId, NewSubmission submissionInfo) - { - string newProductSubmissionUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterProductSubmissionUrl, Uri.EscapeDataString(productId)); - return await HdcPost(newProductSubmissionUrl, submissionInfo); - } - - /// - /// Gets a list of submissions or a specific submission from HWDC - /// - /// Specifiy the Product ID for this Submission - /// Gets all submissions if null otherwise retrieves the specified submission - /// Dev Center response with either an error or a Submission if queried successfully - public async Task> GetSubmission(string productId, string submissionId = null) - { - string getProductSubmissionUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterProductSubmissionUrl, Uri.EscapeDataString(productId)); - - bool isMany = string.IsNullOrEmpty(submissionId); - if (!isMany) - { - getProductSubmissionUrl += "/" + Uri.EscapeDataString(submissionId); - } - - return await HdcGet(getProductSubmissionUrl, isMany); - } - - private const string DevCenterPartnerSubmissionUrl = - "/hardware/products/relationships/sourcepubliherid/{0}/sourceproductid/{1}/sourcesubmissionid/{2}"; - - /// - /// Gets shared submission info from a partner-shared Submission with partner ids - /// - /// Specifiy the Partner's Publisher ID for this Submission - /// Specifiy the Partner's Product ID for this Submission - /// Specifiy the Partner's Submission ID for this Submission - /// Dev Center response with either an error or a Submission if queried successfully with IDs for the querying account - public async Task> GetPartnerSubmission( - string publisherId, string productId, string submissionId) - { - string getProductSubmissionUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterPartnerSubmissionUrl, Uri.EscapeDataString(publisherId), - Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); - return await HdcGet(getProductSubmissionUrl, string.IsNullOrEmpty(submissionId)); - } - - private const string DevCenterProductSubmissionCommitUrl = "/hardware/products/{0}/submissions/{1}/commit"; - /// - /// Commits a Submission in HWDC - /// - /// Specifiy the Product ID for the Submission to commit - /// Specifiy the Submission ID for the Submission to commit - /// Dev Center response with either an error or a true if comitted successfully - public async Task> CommitSubmission(string productId, string submissionId) - { - string commitProductSubmissionUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterProductSubmissionCommitUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); - DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Post, commitProductSubmissionUrl, null, null); - DevCenterResponse ret = new DevCenterResponse() - { - Error = error, - ReturnValue = new List() - { - error == null - }, - Trace = Trace - }; - - if (error != null) - { - if ((error.HttpErrorCode.HasValue) && - (error.HttpErrorCode.Value == (int)System.Net.HttpStatusCode.BadGateway) && - (string.Compare(error.Code, "requestInvalidForCurrentState", true) == 0) - ) - { - // Communication issue likely caused the submission to already be done. Check. - DevCenterResponse SubmissionStatus = await GetSubmission(productId, submissionId); - if (SubmissionStatus.Error == null) - { - Submission s = SubmissionStatus.ReturnValue[0]; - if (string.Compare(s.CommitStatus, "commitComplete", true) == 0) - { - //Actually did commit - ret.Error = null; - ret.ReturnValue = new List() { true }; - } - } - } - } - - return ret; - } - - private const string DevCenterShippingLabelUrl = "/hardware/products/{0}/submissions/{1}/shippingLabels"; - - /// - /// Creates a new Shipping Label in HWDC with the specified options - /// - /// Specifiy the Product ID for this Shipping Label - /// Specifiy the Submission ID for this Shipping Label - /// Options for the new Shipping Label to be generated - /// Dev Center response with either an error or a ShippingLabel if created successfully - public async Task> NewShippingLabel( - string productId, string submissionId, NewShippingLabel shippingLabelInfo) - { - string shippingLabelUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterShippingLabelUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); - return await HdcPost(shippingLabelUrl, shippingLabelInfo); - } - - /// - /// Gets a list of shipping labels or a specific shipping label from HWDC - /// - /// Specifiy the Product ID for this Shipping Label - /// Specifiy the Submission ID for this Shipping Label - /// Gets all Shipping Labels if null otherwise retrieves the specified Shipping Label - /// Dev Center response with either an error or a ShippingLabel if queried successfully - public async Task> GetShippingLabels( - string productId, string submissionId, string shippingLabelId = null) - { - string getShippingLabelUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterShippingLabelUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); - - bool isMany = string.IsNullOrEmpty(shippingLabelId); - if (!isMany) - { - getShippingLabelUrl += "/" + Uri.EscapeDataString(shippingLabelId); - } - - getShippingLabelUrl += "?includeTargetingInfo=true"; - return await HdcGet(getShippingLabelUrl, isMany); - } - - private const string DevCenterAudienceUrl = "/hardware/audiences"; - - /// - /// Gets a list of valid audiences from HWDC - /// - /// Dev Center response with either an error or a Audience if queried successfully - public async Task> GetAudiences() - { - string getAudienceUrl = GetDevCenterBaseUrl() + DevCenterAudienceUrl; - return await HdcGet(getAudienceUrl, true); - } - - private const string DevCenterCreateMetaDataUrl = "/hardware/products/{0}/submissions/{1}/createpublishermetadata"; - - /// - /// Requests creation of driver metadata on older submissions to HWDC - /// - /// Dev Center response with either an error or ok if metadata was created successfully - public async Task> CreateMetaData(string productId, string submissionId) - { - string createMetaDataUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterCreateMetaDataUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); - DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Post, createMetaDataUrl, null, null); - DevCenterResponse ret = new DevCenterResponse() - { - Error = error, - ReturnValue = new List() - { - error == null - }, - Trace = Trace - }; - return ret; - } - - private const string DevCenterCancelShippingLabelUrl = "/hardware/products/{0}/submissions/{1}/shippingLabels/{2}/cancel"; - - /// - /// Requests cancellation of a shipping label - /// - /// Dev Center Response with Boolean value indicating a successful call to cancel a the shipping label - public async Task> CancelShippingLabel(string productId, string submissionId, string shippingLabelId) - { - string cancelShippingLabelUrl = GetDevCenterBaseUrl() + - string.Format(DevCenterCancelShippingLabelUrl, productId, submissionId, shippingLabelId); - - DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Put, cancelShippingLabelUrl, null, null); - DevCenterResponse ret = new DevCenterResponse() - { - Error = error, - ReturnValue = new List() - { - error == null - }, - Trace = Trace - }; - - return ret; - } - - public void Dispose() - { - AuthHandler.Dispose(); - } - } -} + Submission s = SubmissionStatus.ReturnValue[0]; + if (string.Compare(s.CommitStatus, "commitComplete", true) == 0) + { + //Actually did commit + ret.Error = null; + ret.ReturnValue = new List() { true }; + } + } + } + } + + return ret; + } + + private const string _devCenterShippingLabelUrl = "/hardware/products/{0}/submissions/{1}/shippingLabels"; + + /// + /// Creates a new Shipping Label in HDC with the specified options + /// + /// Specify the Product ID for this Shipping Label + /// Specify the Submission ID for this Shipping Label + /// Options for the new Shipping Label to be generated + /// Dev Center response with either an error or a ShippingLabel if created successfully + public async Task> NewShippingLabel( + string productId, string submissionId, NewShippingLabel shippingLabelInfo) + { + string shippingLabelUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterShippingLabelUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); + return await HdcPost(shippingLabelUrl, shippingLabelInfo); + } + + /// + /// Gets a list of shipping labels or a specific shipping label from HDC + /// + /// Specify the Product ID for this Shipping Label + /// Specify the Submission ID for this Shipping Label + /// Gets all Shipping Labels if null otherwise retrieves the specified Shipping Label + /// Dev Center response with either an error or a ShippingLabel if queried successfully + public async Task> GetShippingLabels( + string productId, string submissionId, string shippingLabelId = null) + { + string getShippingLabelUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterShippingLabelUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); + + bool isMany = string.IsNullOrEmpty(shippingLabelId); + if (!isMany) + { + getShippingLabelUrl += "/" + Uri.EscapeDataString(shippingLabelId); + } + + getShippingLabelUrl += "?includeTargetingInfo=true"; + return await HdcGet(getShippingLabelUrl, isMany); + } + + private const string _devCenterAudienceUrl = "/hardware/audiences"; + + /// + /// Gets a list of valid audiences from HDC + /// + /// Dev Center response with either an error or a Audience if queried successfully + public async Task> GetAudiences() + { + string getAudienceUrl = GetDevCenterBaseUrl() + _devCenterAudienceUrl; + return await HdcGet(getAudienceUrl, true); + } + + private const string _devCenterCreateMetaDataUrl = "/hardware/products/{0}/submissions/{1}/createpublishermetadata"; + + /// + /// Requests creation of driver metadata on older submissions to HDC + /// + /// Dev Center response with either an error or ok if metadata was created successfully + public async Task> CreateMetaData(string productId, string submissionId) + { + string createMetaDataUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterCreateMetaDataUrl, Uri.EscapeDataString(productId), Uri.EscapeDataString(submissionId)); + DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Post, createMetaDataUrl, null, null); + DevCenterResponse ret = new() + { + Error = error, + ReturnValue = new List() + { + error == null + }, + Trace = _trace + }; + return ret; + } + + private const string _devCenterCancelShippingLabelUrl = "/hardware/products/{0}/submissions/{1}/shippingLabels/{2}/cancel"; + + /// + /// Requests cancellation of a shipping label + /// + /// Dev Center Response with Boolean value indicating a successful call to cancel a the shipping label + public async Task> CancelShippingLabel(string productId, string submissionId, string shippingLabelId) + { + string cancelShippingLabelUrl = GetDevCenterBaseUrl() + + string.Format(_devCenterCancelShippingLabelUrl, productId, submissionId, shippingLabelId); + + DevCenterErrorDetails error = await InvokeHdcService(HttpMethod.Put, cancelShippingLabelUrl, null, null); + DevCenterResponse ret = new() + { + Error = error, + ReturnValue = new List() + { + error == null + }, + Trace = _trace + }; + + return ret; + } + + public void Dispose() + { + _authHandler.Dispose(); + } +}