/// <summary>
        /// Submits an upload request to the Bing Ads bulk service with the specified parameters.
        /// </summary>
        /// <param name="parameters">Determines various upload parameters, for example what file to upload. Please see <see cref="SubmitUploadParameters"/> for more information about available parameters.</param>
        /// <returns>A task that represents the asynchronous operation. The task result will be the submitted upload operation.</returns>
        /// <exception cref="FaultException{TDetail}">Thrown if a fault is returned from the Bing Ads service.</exception>
        /// <exception cref="OAuthTokenRequestException">Thrown if tokens can't be refreshed due to an error received from the Microsoft Account authorization server.</exception>
        public Task <BulkUploadOperation> SubmitUploadAsync(SubmitUploadParameters parameters)
        {
            ValidateSubmitUploadParameters(parameters);

            ValidateUserData();

            return(SubmitUploadAsyncImpl(parameters));
        }
        private static void ValidateSubmitUploadParameters(SubmitUploadParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            if (parameters.UploadFilePath == null)
            {
                throw new InvalidOperationException(ErrorMessages.UploadFilePathMustNotBeNull);
            }
        }
        private async Task <BulkUploadOperation> SubmitUploadAsyncImpl(SubmitUploadParameters parameters)
        {
            var request = new GetBulkUploadUrlRequest
            {
                ResponseMode = parameters.ResponseMode
            };

            GetBulkUploadUrlResponse getUploadUrlResponse;

            using (var apiService = new ServiceClient <IBulkService>(_authorizationData, _apiEnvironment))
            {
                try
                {
                    getUploadUrlResponse = await apiService.CallAsync((s, r) => s.GetBulkUploadUrlAsync(r), request).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    throw new CouldNotSubmitBulkUploadException("Get upload url failed.", e);
                }
            }

            var uploadUrl = getUploadUrlResponse.UploadUrl;

            Action <HttpRequestHeaders> addHeaders = headers =>
            {
                headers.Add("DeveloperToken", _authorizationData.DeveloperToken);
                headers.Add("CustomerId", _authorizationData.CustomerId.ToString());
                headers.Add("AccountId", _authorizationData.AccountId.ToString());

                _authorizationData.Authentication.AddAuthenticationHeaders(headers);
            };

            string effectiveFileUploadPath = parameters.UploadFilePath;

            if (parameters.RenameUploadFileToMatchRequestId)
            {
                effectiveFileUploadPath = RenameUploadFileToMatchRequestId(effectiveFileUploadPath, getUploadUrlResponse);
            }

            var shouldCompress = parameters.CompressUploadFile && Path.GetExtension(effectiveFileUploadPath) != ".zip";

            string compressedFilePath = null;

            if (shouldCompress)
            {
                compressedFilePath = CompressUploadFile(effectiveFileUploadPath);

                effectiveFileUploadPath = compressedFilePath;
            }

            await HttpService.UploadFileAsync(new Uri(uploadUrl), effectiveFileUploadPath, addHeaders, UploadHttpTimeout).ConfigureAwait(false);

            if (shouldCompress && compressedFilePath != null)
            {
                FileSystem.DeleteFile(compressedFilePath);
            }

            return(new BulkUploadOperation(getUploadUrlResponse.RequestId, _authorizationData, getUploadUrlResponse.TrackingId, _apiEnvironment)
            {
                StatusPollIntervalInMilliseconds = StatusPollIntervalInMilliseconds,
                DownloadHttpTimeout = DownloadHttpTimeout
            });
        }