Exemplo n.º 1
0
        /// <summary>
        /// Gets the list of BulkAdGroupProductPartition that represent a product partition tree for the specified ad group.
        /// </summary>
        /// <param name="adGroupId">The identifier of the ad group whose product partition tree you want to get.</param>
        /// <returns>The BulkAdGroupProductPartition download results, filtered by the specified ad group ID.</returns>
        private async Task <IList <BulkAdGroupProductPartition> > GetBulkAdGroupProductPartitionTree(long adGroupId)
        {
            var downloadParameters = new DownloadParameters
            {
                DownloadEntities    = new[] { DownloadEntity.AdGroupProductPartitions },
                ResultFileDirectory = FileDirectory,
                ResultFileName      = DownloadFileName,
                OverwriteResultFile = true,
                LastSyncTimeInUTC   = null
            };

            var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

            Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
            var downloadEntities = Reader.ReadEntities().ToList();
            var bulkAdGroupProductPartitionResults = downloadEntities.OfType <BulkAdGroupProductPartition>().ToList();

            Reader.Dispose();

            IList <BulkAdGroupProductPartition> bulkAdGroupProductPartitions = new List <BulkAdGroupProductPartition>();

            foreach (var bulkAdGroupProductPartitionResult in bulkAdGroupProductPartitionResults)
            {
                if (bulkAdGroupProductPartitionResult.AdGroupCriterion != null &&
                    bulkAdGroupProductPartitionResult.AdGroupCriterion.AdGroupId == adGroupId)
                {
                    bulkAdGroupProductPartitions.Add(bulkAdGroupProductPartitionResult);
                }
            }

            return(bulkAdGroupProductPartitions);
        }
        /// <summary>
        /// You can submit a download or upload request and the BulkServiceManager will automatically
        /// return results. The BulkServiceManager abstracts the details of checking for result file
        /// completion, and you don't have to write any code for results polling.
        /// </summary>
        /// <param name="downloadParameters"></param>
        /// <param name="progress"></param>
        /// <returns></returns>
        private async Task BackgroundCompletionAsync(
            DownloadParameters downloadParameters,
            Progress <BulkOperationProgressInfo> progress,
            CancellationToken cancellationToken)
        {
            var resultFilePath = await BulkServiceManager.DownloadFileAsync(
                parameters : downloadParameters,
                progress : progress,
                cancellationToken : cancellationToken);

            OutputStatusMessage(string.Format("Download result file: {0}", resultFilePath));
        }
        /// <summary>
        /// You can submit a download or upload request and the BulkServiceManager will automatically
        /// return results. The BulkServiceManager abstracts the details of checking for result file
        /// completion, and you don't have to write any code for results polling.
        /// </summary>
        /// <param name="downloadParameters"></param>
        /// <param name="progress"></param>
        /// <returns></returns>
        private async Task BackgroundCompletionAsync(
            DownloadParameters downloadParameters,
            Progress <BulkOperationProgressInfo> progress)
        {
            // You may optionally cancel the DownloadFileAsync operation after a specified time interval.
            var tokenSource = new CancellationTokenSource();

            tokenSource.CancelAfter(TimeoutInMilliseconds);

            var resultFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters, progress, tokenSource.Token);

            OutputStatusMessage(string.Format("Download result file: {0}\n", resultFilePath));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Downloads all target criterions in the account. You can use this method
        /// to sync criterion identifiers and map them to your campaigns and ad groups.
        /// </summary>
        /// <returns>The string result of the Task is the local path to the downloaded bulk file.</returns>
        private async Task <string> DownloadTargetsAsCriterions(IList <long> campaignIds)
        {
            var downloadParameters = new DownloadParameters
            {
                CampaignIds      = campaignIds,
                DownloadEntities = new List <DownloadEntity> {
                    DownloadEntity.AdGroupTargetCriterions,
                    DownloadEntity.CampaignTargetCriterions
                },
                ResultFileDirectory = FileDirectory,
                ResultFileName      = DownloadFileName,
                OverwriteResultFile = true,
                LastSyncTimeInUTC   = null
            };

            OutputStatusMessage("Downloading targets as criterions . . . \n");
            return(await BulkServiceManager.DownloadFileAsync(downloadParameters).ConfigureAwait(continueOnCapturedContext: false));
        }
Exemplo n.º 5
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);
                BulkServiceManager.StatusPollIntervalInMilliseconds = 5000;

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                #region Download

                // In this example we will download all ad groups in the account.

                var entities = new[] {
                    DownloadEntity.AdGroups,
                };

                // You can limit by specific campaign IDs and request performance data.

                var downloadParameters = new DownloadParameters
                {
                    CampaignIds = null,
                    DataScope   = DataScope.EntityData,
                    PerformanceStatsDateRange = null,
                    DownloadEntities          = entities,
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                // You can submit a download or upload request and the BulkServiceManager will automatically
                // return results. The BulkServiceManager abstracts the details of checking for result file
                // completion, and you don't have to write any code for results polling.

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("Downloaded all ad groups in the account.\n");

                #endregion Download

                #region Parse

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                // We will activate ad groups for one month starting from today as an example.

                var nextMonth = DateTime.UtcNow.AddMonths(1);

                // Within the downloaded records, find all ad groups that you want to update.

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.IsExpired)
                    {
                        // For best performance, only upload the properties that you want to update.

                        Writer.WriteEntity(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                Reader.Dispose();
                Writer.Dispose();

                #endregion Parse

                #region Upload

                // Upload the local file that we already prepared

                var fileUploadParameters = new FileUploadParameters
                {
                    ResultFileDirectory = FileDirectory,
                    CompressUploadFile  = true,
                    ResultFileName      = ResultFileName,
                    OverwriteResultFile = true,
                    UploadFilePath      = FileDirectory + UploadFileName,
                    ResponseMode        = ResponseMode.ErrorsAndResults
                };

                var resultFilePath = await BulkServiceManager.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                OutputStatusMessage("Updated ad groups.\n");

                Reader       = new BulkFileReader(resultFilePath, ResultFileType.Upload, FileType);
                bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);
                Reader.Dispose();

                #endregion Upload


                #region Entities

                // We can make the same update without explicitly reading or writing a local file.
                // When working with entities a file is downloaded to the temp directory,
                // although you don't need to manage it.

                var downloadEntities = await BulkServiceManager.DownloadEntitiesAsync(downloadParameters);

                OutputStatusMessage("Downloaded all ad groups in the account.\n");
                bulkAdGroups = downloadEntities.ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                var uploadEntities = new List <BulkEntity>();

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.IsExpired)
                    {
                        // Instead of Writer.WriteEntity, we will add to the in-memory list

                        uploadEntities.Add(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                var entityUploadParameters = new EntityUploadParameters
                {
                    Entities     = uploadEntities,
                    ResponseMode = ResponseMode.ErrorsAndResults,
                };

                var resultEntities = await BulkServiceManager.UploadEntitiesAsync(entityUploadParameters, progress, CancellationToken.None);

                OutputStatusMessage("Updated ad groups.\n");

                bulkAdGroups = resultEntities.ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                #endregion Entities
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
Exemplo n.º 6
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var downloadParameters = new DownloadParameters
                {
                    DownloadEntities    = new[] { DownloadEntity.RemarketingLists },
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC   = null
                };

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("Downloaded all remarketing lists that the current user can associate with ad groups.\n");
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var downloadEntities = Reader.ReadEntities().ToList();

                var remarketingListResults = downloadEntities.OfType <BulkRemarketingList>().ToList();
                OutputBulkRemarketingLists(remarketingListResults);

                Reader.Dispose();

                // You must already have at least one remarketing list.
                if (remarketingListResults.Count < 1)
                {
                    OutputStatusMessage("You do not have any remarketing lists that the current user can associate with ad groups.\n");
                    return;
                }

                var uploadEntities = new List <BulkEntity>();

                #region Add

                // Prepare the bulk entities that you want to upload.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id          = campaignIdKey,
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId      = null,
                        DailyBudget   = 50,
                        BudgetType    = BudgetLimitType.DailyBudgetStandard,
                        BiddingScheme = new EnhancedCpcBiddingScheme(),

                        TimeZone = "PacificTimeUSCanadaTijuana",

                        TrackingUrlTemplate = null
                    }
                };

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId   = "YourClientIdGoesHere",
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkAdGroup, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the
                        // ad group Id will be used when associating this new ad group with a new ad group remarketing list association
                        // in the BulkAdGroupRemarketingListAssociation object below.
                        Id             = adGroupIdKey,
                        Name           = "Women's Red Shoe Sale",
                        AdDistribution = AdDistribution.Search,
                        BiddingScheme  = new InheritFromParentBiddingScheme(),
                        PricingModel   = PricingModel.Cpc,
                        StartDate      = null,
                        EndDate        = new Microsoft.BingAds.V11.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        Language            = "English",
                        Status              = AdGroupStatus.Active,
                        TrackingUrlTemplate = null,

                        // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates
                        // that you want to show ads only to people included in the remarketing list, with the option to change
                        // the bid amount. Ads in this ad group will only show to people included in the remarketing list.
                        RemarketingTargetingSetting = RemarketingTargetingSetting.TargetAndBid,
                    },
                };

                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);

                // This example associates all of the remarketing lists with the new ad group.

                foreach (var remarketingList in remarketingListResults)
                {
                    if (remarketingList.RemarketingList != null && remarketingList.RemarketingList.Id != null)
                    {
                        var bulkAdGroupRemarketingListAssociation = new BulkAdGroupRemarketingListAssociation
                        {
                            ClientId = "MyBulkAdGroupRemarketingListAssociation " + remarketingList.RemarketingList.Id,
                            BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                            {
                                AdGroupId = adGroupIdKey,
                                Criterion = new AudienceCriterion
                                {
                                    AudienceId   = (long)remarketingList.RemarketingList.Id,
                                    AudienceType = AudienceType.RemarketingList,
                                },
                                CriterionBid = new BidMultiplier
                                {
                                    Multiplier = 20.00,
                                },
                                Status = AdGroupCriterionStatus.Paused,
                            },
                            // Read-only properties
                            AdGroupName         = null,
                            CampaignName        = null,
                            RemarketingListName = null,
                        };

                        uploadEntities.Add(bulkAdGroupRemarketingListAssociation);
                    }
                }

                // Upload and write the output

                OutputStatusMessage("\nAdding campaign, ad group, and ad group remarketing list associations...\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var adGroupRemarketingListResults = downloadEntities.OfType <BulkAdGroupRemarketingListAssociation>().ToList();
                OutputBulkAdGroupRemarketingListAssociations(adGroupRemarketingListResults);

                Reader.Dispose();

                #endregion Add

                #region CleanUp

                // Delete the campaign, ad group, and ad group remarketing list associations that were previously added.
                // The remarketing lists will not be deleted.
                // You should remove this region if you want to view the added entities in the
                // Bing Ads web application or another tool.

                // You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                // When you delete a BulkCampaign, the dependent entities such as BulkAdGroup and BulkAdGroupRemarketingListAssociation
                // are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign, ad group, and ad group remarketing list associations . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V11.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V11.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
Exemplo n.º 7
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var tokenSource = new CancellationTokenSource();
                tokenSource.CancelAfter(TimeoutInMilliseconds);

                // In this example we will download all ad groups in the account.

                var downloadParameters = new DownloadParameters
                {
                    DataScope           = DataScope.EntityData,
                    DownloadEntities    = new[] { DownloadEntity.AdGroups },
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                OutputStatusMessage("-----\nDownloading all ad groups in the account.");

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(
                    parameters : downloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                OutputStatusMessage("Download results:");

                Reader = new BulkFileReader(
                    filePath: bulkFilePath,
                    resultFileType: ResultFileType.FullDownload,
                    fileFormat: FileType);

                var bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                // We will activate ad groups for one month starting from today as an example.

                var nextMonth = DateTime.UtcNow.AddMonths(1);

                // Within the downloaded records, find all ad groups that you want to update.

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.AdGroup.Status.ToString().CompareTo("Active") != 0)
                    {
                        // For best performance, only upload the properties that you want to update.

                        Writer.WriteEntity(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V13.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                Reader.Dispose();
                Writer.Dispose();

                // Upload the local file that we already prepared

                var fileUploadParameters = new FileUploadParameters
                {
                    ResultFileDirectory = FileDirectory,
                    CompressUploadFile  = true,
                    ResultFileName      = ResultFileName,
                    OverwriteResultFile = true,
                    UploadFilePath      = FileDirectory + UploadFileName,
                    ResponseMode        = ResponseMode.ErrorsAndResults
                };

                OutputStatusMessage("-----\nActivating the ad groups...");

                var resultFilePath = await BulkServiceManager.UploadFileAsync(
                    parameters : fileUploadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                Reader = new BulkFileReader(
                    filePath: resultFilePath,
                    resultFileType: ResultFileType.Upload,
                    fileFormat: FileType);

                OutputStatusMessage("Upload results:");

                bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Reader.Dispose();
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                BulkService = new BulkServiceManager(authorizationData);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List <BulkEntity>();

                #region Add

                // Let's create a new budget and share it with a new campaign.

                var bulkBudget = new BulkBudget
                {
                    ClientId = "YourClientIdGoesHere",
                    Budget   = new Budget
                    {
                        Amount     = 50,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        Id         = budgetIdKey,
                        Name       = "My Shared Budget " + DateTime.UtcNow,
                    }
                };

                var bulkCampaign = new BulkCampaign
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id
                        // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below.
                        Id          = campaignIdKey,
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId    = budgetIdKey,
                        DailyBudget = null,
                        BudgetType  = BudgetLimitType.DailyBudgetStandard,

                        TimeZone = "PacificTimeUSCanadaTijuana",

                        // DaylightSaving is not supported in the Bulk file schema. Whether or not you specify it in a BulkCampaign,
                        // the value is not written to the Bulk file, and by default DaylightSaving is set to true.
                        DaylightSaving = true,

                        // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme)
                        // and then, at any time, set an individual ad group or keyword bid strategy to
                        // Manual CPC (ManualCpcBiddingScheme).
                        // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects.
                        // If you do not set this element, then ManualCpcBiddingScheme is used by default.
                        BiddingScheme = new EnhancedCpcBiddingScheme {
                        },

                        Status = CampaignStatus.Paused,

                        // Used with FinalUrls shown in the expanded text ads that we will add below.
                        TrackingUrlTemplate =
                            "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
                    }
                };

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id             = adGroupIdKey,
                        Name           = "Women's Red Shoe Sale",
                        AdDistribution = AdDistribution.Search,
                        BiddingModel   = BiddingModel.Keyword,
                        PricingModel   = PricingModel.Cpc,
                        StartDate      = null,
                        EndDate        = new Microsoft.BingAds.V10.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        Language = "English",
                        Status   = AdGroupStatus.Active,

                        // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects.
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new ManualCpcBiddingScheme {
                        },

                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,
                    },
                };

                // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit,
                // and the third keyword is a duplicate of the second keyword.

                var bulkKeywords = new [] {
                    new BulkKeyword {
                        AdGroupId = adGroupIdKey,
                        Keyword   = new Keyword
                        {
                            Bid = new Bid {
                                Amount = 0.47
                            },
                            Param2    = "10% Off",
                            MatchType = MatchType.Broad,
                            Text      = "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                                        "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                                        "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects.
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme {
                            },
                        },
                    },
                    new BulkKeyword {
                        AdGroupId = adGroupIdKey,
                        Keyword   = new Keyword
                        {
                            Bid = new Bid {
                                Amount = 0.47
                            },
                            Param2    = "10% Off",
                            MatchType = MatchType.Phrase,
                            Text      = "Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects.
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme {
                            },
                        },
                    },
                    new BulkKeyword {
                        AdGroupId = adGroupIdKey,
                        Keyword   = new Keyword
                        {
                            Bid = new Bid {
                                Amount = 0.47
                            },
                            Param2    = "10% Off",
                            MatchType = MatchType.Phrase,
                            Text      = "Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects.
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme {
                            },
                        },
                    },
                };

                // In this example only the first 3 ads should succeed.
                // The TitlePart2 of the fourth ad is empty and not valid,
                // and the fifth ad is a duplicate of the second ad.

                var bulkExpandedTextAds = new [] {
                    new BulkExpandedTextAd
                    {
                        AdGroupId      = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Fast & Easy Setup",
                            Text       = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1      = "seattle",
                            Path2      = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and
                            // landing page URLs.
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale",
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale",
                            },
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad,
                            // and can be used by the ad, ad group, campaign, or account level tracking template.
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter()
                                    {
                                        Key   = "promoCode",
                                        Value = "PROMO1"
                                    },
                                    new CustomParameter()
                                    {
                                        Key   = "season",
                                        Value = "summer"
                                    },
                                }
                            }
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId      = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Quick & Easy Setup",
                            Text       = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1      = "seattle",
                            Path2      = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and
                            // landing page URLs.
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            },
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad,
                            // and can be used by the ad, ad group, campaign, or account level tracking template.
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter()
                                    {
                                        Key   = "promoCode",
                                        Value = "PROMO2"
                                    },
                                    new CustomParameter()
                                    {
                                        Key   = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId      = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Fast & Simple Setup",
                            Text       = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1      = "seattle",
                            Path2      = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and
                            // landing page URLs.
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            },
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad,
                            // and can be used by the ad, ad group, campaign, or account level tracking template.
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter()
                                    {
                                        Key   = "promoCode",
                                        Value = "PROMO3"
                                    },
                                    new CustomParameter()
                                    {
                                        Key   = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId      = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "",
                            Text       = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1      = "seattle",
                            Path2      = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and
                            // landing page URLs.
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            },
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad,
                            // and can be used by the ad, ad group, campaign, or account level tracking template.
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter()
                                    {
                                        Key   = "promoCode",
                                        Value = "PROMO4"
                                    },
                                    new CustomParameter()
                                    {
                                        Key   = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId      = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Quick & Easy Setup",
                            Text       = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1      = "seattle",
                            Path2      = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and
                            // landing page URLs.
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            },
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad,
                            // and can be used by the ad, ad group, campaign, or account level tracking template.
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter()
                                    {
                                        Key   = "promoCode",
                                        Value = "PROMO5"
                                    },
                                    new CustomParameter()
                                    {
                                        Key   = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                };

                uploadEntities.Add(bulkBudget);
                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);

                foreach (var bulkKeyword in bulkKeywords)
                {
                    uploadEntities.Add(bulkKeyword);
                }

                foreach (var bulkExpandedTextAd in bulkExpandedTextAds)
                {
                    uploadEntities.Add(bulkExpandedTextAd);
                }

                // Upload and write the output

                OutputStatusMessage("Adding campaign, budget, ad group, ads, and keywords...\n");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                var budgetResults = downloadEntities.OfType <BulkBudget>().ToList();
                OutputBulkBudgets(budgetResults);

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var keywordResults = downloadEntities.OfType <BulkKeyword>().ToList();
                OutputBulkKeywords(keywordResults);

                var expandedTextAdResults = downloadEntities.OfType <BulkExpandedTextAd>().ToList();
                OutputBulkExpandedTextAds(expandedTextAdResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                // Here is a simple example that updates the campaign budget.

                var downloadParameters = new DownloadParameters
                {
                    Entities            = BulkDownloadEntity.Budgets | BulkDownloadEntity.Campaigns,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC   = null
                };

                // Download all campaigns and shared budgets in the account.
                var bulkFilePath = await BulkService.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("\nDownloaded all campaigns and shared budgets in the account.\n");
                Reader           = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                downloadEntities = Reader.ReadEntities().ToList();
                var getBudgetResults = downloadEntities.OfType <BulkBudget>().ToList();
                OutputBulkBudgets(getBudgetResults);
                var getCampaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(getCampaignResults);

                uploadEntities = new List <BulkEntity>();

                // If the campaign has a shared budget you cannot update the Campaign budget amount,
                // and you must instead update the amount in the Budget record. If you try to update
                // the budget amount of a Campaign that has a shared budget, the service will return
                // the CampaignServiceCannotUpdateSharedBudget error code.

                foreach (var entity in getBudgetResults)
                {
                    if (entity.Budget.Id > 0)
                    {
                        // Increase budget by 20 %
                        entity.Budget.Amount *= 1.2m;
                        uploadEntities.Add(entity);
                    }
                }

                foreach (var entity in getCampaignResults)
                {
                    if (entity.Campaign.BudgetId == null || entity.Campaign.BudgetId <= 0)
                    {
                        // Increase existing budgets by 20%
                        // Monthly budgets are deprecated and there will be a forced migration to daily budgets in calendar year 2017.
                        // Shared budgets do not support the monthly budget type, so this is only applicable to unshared budgets.
                        // During the migration all campaign level unshared budgets will be rationalized as daily.
                        // The formula that will be used to convert monthly to daily budgets is: Monthly budget amount / 30.4.
                        // Moving campaign monthly budget to daily budget is encouraged before monthly budgets are migrated.

                        if (entity.Campaign.BudgetType == BudgetLimitType.MonthlyBudgetSpendUntilDepleted)
                        {
                            // Increase budget by 20 %
                            entity.Campaign.BudgetType  = BudgetLimitType.DailyBudgetStandard;
                            entity.Campaign.DailyBudget = entity.Campaign.MonthlyBudget / 30.4 * 1.2;
                        }
                        else
                        {
                            // Increase budget by 20 %
                            entity.Campaign.DailyBudget *= 1.2;
                        }
                        uploadEntities.Add(entity);
                    }
                }

                Reader.Dispose();

                if (uploadEntities.Count > 0)
                {
                    OutputStatusMessage("\nChanged local campaign budget amounts. Starting upload.\n");

                    Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                    downloadEntities = Reader.ReadEntities().ToList();
                    getBudgetResults = downloadEntities.OfType <BulkBudget>().ToList();
                    OutputBulkBudgets(getBudgetResults);
                    getCampaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                    OutputBulkCampaigns(getCampaignResults);
                    Reader.Dispose();
                }
                else
                {
                    OutputStatusMessage("\nNo campaigns or shared budgets in account.\n");
                }

                #endregion Update

                #region CleanUp

                //Delete the campaign, ad group, ads, and keywords that were previously added.
                //You should remove this region if you want to view the added entities in the
                //Bing Ads web application or another tool.

                //You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                //When you delete a BulkCampaign, the dependent entities such as BulkAdGroup, BulkKeyword,
                //and BulkExpandedTextAd are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var budgetResult in budgetResults)
                {
                    budgetResult.Status = Status.Deleted;
                    uploadEntities.Add(budgetResult);
                }

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign, budget, ad group, keywords, and ads . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                getBudgetResults = downloadEntities.OfType <BulkBudget>().ToList();
                OutputBulkBudgets(getBudgetResults);
                getCampaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(getCampaignResults);

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V10.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V10.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
Exemplo n.º 9
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var tokenSource = new CancellationTokenSource();
                tokenSource.CancelAfter(TimeoutInMilliseconds);

                var downloadParameters = new DownloadParameters
                {
                    DownloadEntities    = new[] { DownloadEntity.RemarketingLists },
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC   = null
                };

                OutputStatusMessage("-----\nDownloading all remarketing lists that the current user can associate with ad groups.");

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(
                    parameters : downloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                OutputStatusMessage("Download results:");

                Reader = new BulkFileReader(
                    filePath: bulkFilePath,
                    resultFileType: ResultFileType.FullDownload,
                    fileFormat: FileType);

                var downloadEntities = Reader.ReadEntities().ToList();

                var remarketingListResults = downloadEntities.OfType <BulkRemarketingList>().ToList();
                OutputBulkRemarketingLists(remarketingListResults);

                Reader.Dispose();

                // You must have at least one remarketing list.

                if (remarketingListResults.Count < 1)
                {
                    OutputStatusMessage("There are no remarketing lists in the account.");
                    return;
                }

                var uploadEntities = new List <BulkEntity>();

                // Add an ad group in a campaign. The ad group will later be associated with remarketing lists.

                var bulkCampaign = new BulkCampaign
                {
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        Id          = campaignIdKey,
                        BudgetType  = BudgetLimitType.DailyBudgetStandard,
                        DailyBudget = 50,
                        Languages   = new string[] { "All" },
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        TimeZone    = "PacificTimeUSCanadaTijuana",
                    }
                };
                uploadEntities.Add(bulkCampaign);

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V13.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                        // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates
                        // that you want to show ads only to people included in the remarketing list, with the option to change
                        // the bid amount. Ads in this ad group will only show to people included in the remarketing list.
                        Settings = new[]
                        {
                            new TargetSetting
                            {
                                Details = new []
                                {
                                    new TargetSettingDetail
                                    {
                                        CriterionTypeGroup = CriterionTypeGroup.Audience,
                                        TargetAndBid       = true
                                    }
                                }
                            }
                        },
                    },
                };

                uploadEntities.Add(bulkAdGroup);

                // For example, associate all of the remarketing lists with the new ad group.

                foreach (var remarketingList in remarketingListResults)
                {
                    if (remarketingList.RemarketingList != null && remarketingList.RemarketingList.Id != null)
                    {
                        var bulkAdGroupRemarketingListAssociation = new BulkAdGroupRemarketingListAssociation
                        {
                            ClientId = "MyBulkAdGroupRemarketingListAssociation " + remarketingList.RemarketingList.Id,
                            BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                            {
                                AdGroupId = adGroupIdKey,
                                Criterion = new AudienceCriterion
                                {
                                    AudienceId   = (long)remarketingList.RemarketingList.Id,
                                    AudienceType = AudienceType.RemarketingList,
                                },
                                CriterionBid = new BidMultiplier
                                {
                                    Multiplier = 20.00,
                                },
                                Status = AdGroupCriterionStatus.Paused,
                            },
                        };
                        uploadEntities.Add(bulkAdGroupRemarketingListAssociation);
                    }
                }

                // Upload and write the output

                OutputStatusMessage("-----\nAdding campaign, ad group, and ad group remarketing list associations...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var adGroupRemarketingListResults = downloadEntities.OfType <BulkAdGroupRemarketingListAssociation>().ToList();
                OutputBulkAdGroupRemarketingListAssociations(adGroupRemarketingListResults);

                Reader.Dispose();

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("-----\nDeleting the campaign and everything it contains e.g., ad groups and ads...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());
                OutputBulkNegativeKeywordLists(downloadEntities.OfType <BulkNegativeKeywordList>().ToList());

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
Exemplo n.º 10
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                AdInsightExampleHelper AdInsightExampleHelper =
                    new AdInsightExampleHelper(this.OutputStatusMessage);
                AdInsightExampleHelper.AdInsightService =
                    new ServiceClient <IAdInsightService>(authorizationData, environment);

                CampaignManagementExampleHelper CampaignManagementExampleHelper =
                    new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(String.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List <BulkEntity>();

                #region Add

                // To get started with dynamic search ads, first you'll need to add a new Campaign
                // with its type set to DynamicSearchAds. When you create the campaign, you'll need to
                // include a DynamicSearchAdsSetting that specifies the target website domain and language.

                var bulkCampaign = new BulkCampaign
                {
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        Id           = campaignIdKey,
                        CampaignType = CampaignType.DynamicSearchAds,
                        Settings     = new[] {
                            new DynamicSearchAdsSetting
                            {
                                DomainName = "contoso.com",
                                Language   = "English"
                            }
                        },

                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId    = null,
                        DailyBudget = 50,
                        BudgetType  = Microsoft.BingAds.V12.CampaignManagement.BudgetLimitType.DailyBudgetStandard,

                        // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme)
                        // and then, at any time, set an individual ad group bid strategy to
                        // Manual CPC (ManualCpcBiddingScheme).
                        BiddingScheme = new EnhancedCpcBiddingScheme {
                        },

                        TimeZone = "PacificTimeUSCanadaTijuana",

                        // Used with CustomParameters defined in lower level entities such as ads.
                        TrackingUrlTemplate =
                            "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
                    },
                };

                uploadEntities.Add(bulkCampaign);

                // Next, create a new AdGroup within the dynamic search ads campaign.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V12.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        Language = "English",
                        Status   = AdGroupStatus.Active,

                        // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects.
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new ManualCpcBiddingScheme {
                        },
                    },
                };

                uploadEntities.Add(bulkAdGroup);

                // You can add one or more Webpage criterion to each ad group that helps determine
                // whether or not to serve dynamic search ads.

                var adGroupWebpagePositivePageContent = new BulkAdGroupDynamicSearchAdTarget
                {
                    BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                    {
                        AdGroupId    = adGroupIdKey,
                        CriterionBid = new FixedBid
                        {
                            Amount = 0.50
                        },
                        Criterion = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = "flowers",
                                        Operand  = WebpageConditionOperand.PageContent,
                                    }
                                },
                                CriterionName = "Ad Group Webpage Positive Page Content Criterion"
                            },
                        },
                        // DestinationUrl and FinalUrls are not supported with Webpage criterion.
                        // The Final URL is dynamically created at the ad level.
                        DestinationUrl = null,
                        FinalUrls      = null,

                        // In this example we are deferring to the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this webpage criterion.
                        UrlCustomParameters = new CustomParameters
                        {
                            Parameters = new[] {
                                new CustomParameter()
                                {
                                    Key   = "promoCode",
                                    Value = "PROMO1"
                                },
                                new CustomParameter()
                                {
                                    Key   = "season",
                                    Value = "summer"
                                },
                            }
                        }
                    }
                };
                uploadEntities.Add(adGroupWebpagePositivePageContent);

                // To discover the categories that you can use for Webpage criterion (positive or negative),
                // use the GetDomainCategories operation with the Ad Insight service.

                var getDomainCategoriesResponse = await AdInsightExampleHelper.GetDomainCategoriesAsync(
                    categoryName : null,
                    domainName : DOMAIN_NAME,
                    language : LANGUAGE);

                var categories = getDomainCategoriesResponse.Categories;

                // If any categories are available let's use one as a condition.
                if (categories.Count > 0)
                {
                    var adGroupWebpagePositiveCategory = new BulkAdGroupDynamicSearchAdTarget
                    {
                        BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                        {
                            AdGroupId    = adGroupIdKey,
                            CriterionBid = new FixedBid
                            {
                                Amount = 0.50
                            },
                            Criterion = new Webpage
                            {
                                Parameter = new WebpageParameter
                                {
                                    Conditions = new[]
                                    {
                                        new WebpageCondition
                                        {
                                            Argument = categories[0].CategoryName,
                                            Operand  = WebpageConditionOperand.Category,
                                        }
                                    },
                                    CriterionName = "Ad Group Webpage Positive Category Criterion"
                                },
                            }
                        }
                    };
                    uploadEntities.Add(adGroupWebpagePositiveCategory);
                }

                // If you want to exclude certain portions of your website, you can add negative Webpage
                // criterion at the campaign and ad group level.

                var adGroupWebpageNegativeUrl = new BulkAdGroupNegativeDynamicSearchAdTarget
                {
                    NegativeAdGroupCriterion = new NegativeAdGroupCriterion
                    {
                        AdGroupId = adGroupIdKey,
                        Criterion = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                // You can choose whether you want the criterion argument to match partial URLs,
                                // page content, page title, or categories that Bing thinks applies to your website.
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = DOMAIN_NAME,
                                        Operand  = WebpageConditionOperand.Url,
                                    }
                                },
                                // If you do not specify any name, then it will be set to a concatenated list of conditions.
                                CriterionName = null
                            }
                        }
                    }
                };
                uploadEntities.Add(adGroupWebpageNegativeUrl);

                // The negative Webpage criterion at the campaign level applies to all ad groups
                // within the campaign; however, if you define ad group level negative Webpage criterion,
                // the campaign criterion is ignored for that ad group.

                var campaignWebpageNegative = new BulkCampaignNegativeDynamicSearchAdTarget
                {
                    NegativeCampaignCriterion = new NegativeCampaignCriterion
                    {
                        CampaignId = campaignIdKey,
                        Criterion  = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = DOMAIN_NAME + "\\seattle",
                                        Operand  = WebpageConditionOperand.Url,
                                    }
                                },
                                CriterionName = "Campaign Negative Webpage Url Criterion"
                            }
                        }
                    }
                };
                uploadEntities.Add(campaignWebpageNegative);


                // Finally you can add a DynamicSearchAd into the ad group. The ad title and display URL
                // are generated automatically based on the website domain and language that you want to target.

                var bulkDynamicSearchAd = new BulkDynamicSearchAd
                {
                    ClientId        = "here",
                    AdGroupId       = adGroupIdKey,
                    DynamicSearchAd = new DynamicSearchAd
                    {
                        Text  = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",

                        // You cannot set FinalUrls. The Final URL will be a dynamically selected landing page.
                        // The final URL is distinct from the path that customers will see and click on in your ad.
                        FinalUrls = null,

                        // In this example we are deferring to the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this ad.
                        UrlCustomParameters = new CustomParameters
                        {
                            Parameters = new[] {
                                new CustomParameter()
                                {
                                    Key   = "promoCode",
                                    Value = "PROMO1"
                                },
                                new CustomParameter()
                                {
                                    Key   = "season",
                                    Value = "summer"
                                },
                            }
                        }
                    },
                };

                uploadEntities.Add(bulkDynamicSearchAd);

                // Upload and write the output

                OutputStatusMessage("Adding campaign, ad group, criterions, and ads . . .\n");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var campaignNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkCampaignNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkCampaignNegativeDynamicSearchAdTargets(campaignNegativeDynamicSearchAdTargetResults);

                var adGroupDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupDynamicSearchAdTargets(adGroupDynamicSearchAdTargetResults);

                var adGroupNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupNegativeDynamicSearchAdTargets(adGroupNegativeDynamicSearchAdTargetResults);

                var dynamicSearchAdResults = downloadEntities.OfType <BulkDynamicSearchAd>().ToList();
                OutputBulkDynamicSearchAds(dynamicSearchAdResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                uploadEntities = new List <BulkEntity>();

                // You can update the bid for BiddableAdGroupCriterion

                var updateBid = new FixedBid
                {
                    Amount = 0.75
                };

                // You can update the Webpage criterion name but cannot update the conditions.
                // To update the conditions you must delete the criterion and add a new criterion.
                // This update attempt will return an error.

                var updateCriterionAttemptFailure = new Webpage
                {
                    Parameter = new WebpageParameter
                    {
                        Conditions = new[]
                        {
                            new WebpageCondition
                            {
                                Argument = "Books",
                                Operand  = WebpageConditionOperand.PageContent,
                            }
                        },
                        CriterionName = "Update Attempt Failure"
                    },
                };

                var updateCriterionAttemptSuccess = new Webpage
                {
                    Parameter = new WebpageParameter
                    {
                        CriterionName = "Update Attempt Success"
                    },
                };

                foreach (var adGroupDynamicSearchAdTargetResult in adGroupDynamicSearchAdTargetResults)
                {
                    var biddableAdGroupCriterion = adGroupDynamicSearchAdTargetResult.BiddableAdGroupCriterion as BiddableAdGroupCriterion;
                    if (biddableAdGroupCriterion != null)
                    {
                        ((BiddableAdGroupCriterion)adGroupDynamicSearchAdTargetResult.BiddableAdGroupCriterion).CriterionBid = updateBid;
                        adGroupDynamicSearchAdTargetResult.BiddableAdGroupCriterion.Criterion = updateCriterionAttemptSuccess;
                        uploadEntities.Add(adGroupDynamicSearchAdTargetResult);
                    }
                }

                foreach (var adGroupNegativeDynamicSearchAdTargetResult in adGroupNegativeDynamicSearchAdTargetResults)
                {
                    var negativeAdGroupCriterion = adGroupNegativeDynamicSearchAdTargetResult.NegativeAdGroupCriterion as NegativeAdGroupCriterion;
                    if (negativeAdGroupCriterion != null)
                    {
                        adGroupNegativeDynamicSearchAdTargetResult.NegativeAdGroupCriterion.Criterion = updateCriterionAttemptFailure;
                        uploadEntities.Add(adGroupNegativeDynamicSearchAdTargetResult);
                    }
                }

                OutputStatusMessage("Updating Ad Group Webpage Criterion . . . \n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                adGroupDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupDynamicSearchAdTargets(adGroupDynamicSearchAdTargetResults);

                adGroupNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupNegativeDynamicSearchAdTargets(adGroupNegativeDynamicSearchAdTargetResults);

                Reader.Dispose();


                #endregion Update

                #region Get

                var entities = new[] {
                    DownloadEntity.AdGroupDynamicSearchAdTargets,
                    DownloadEntity.AdGroupNegativeDynamicSearchAdTargets
                };

                var downloadParameters = new DownloadParameters
                {
                    CampaignIds = null,
                    DataScope   = DataScope.EntityData | DataScope.EntityPerformanceData,
                    PerformanceStatsDateRange = new PerformanceStatsDateRange {
                        PredefinedTime = ReportTimePeriod.LastFourWeeks
                    },
                    DownloadEntities    = entities,
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                // You may optionally cancel the DownloadFileAsync operation after a specified time interval.
                var tokenSource = new CancellationTokenSource();
                tokenSource.CancelAfter(TimeoutInMilliseconds);

                var resultFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters, progress, tokenSource.Token);

                OutputStatusMessage(String.Format("Download result file: {0}\n", resultFilePath));

                #endregion Get

                #region CleanUp

                // Delete the campaign, ad group, criterion, and ad that were previously added.
                // You should remove this operation if you want to view the added entities in the
                // Bing Ads web application or another tool.

                // You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                // When you delete a BulkCampaign, the dependent entities such as BulkAdGroup
                // are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                OutputStatusMessage("\nDeleting DSA campaign, criterions, and ad . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                campaignResults  = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
Exemplo n.º 11
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var downloadParameters = new DownloadParameters
                {
                    DownloadEntities    = new[] { DownloadEntity.AdGroupProductPartitions },
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC   = null
                };

                // Download all product partitions across all ad groups in the account.
                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("Downloaded all product partitions across all ad groups in the account.\n");

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var bulkAdGroupProductPartitions = Reader.ReadEntities().ToList().OfType <BulkAdGroupProductPartition>().ToList();
                OutputBulkAdGroupProductPartitions(bulkAdGroupProductPartitions);

                var uploadEntities = new List <BulkEntity>();

                // Within the downloaded records, find all product partition leaf nodes that have bids.

                foreach (var bulkAdGroupProductPartition in bulkAdGroupProductPartitions)
                {
                    var biddableAdGroupCriterion = (bulkAdGroupProductPartition).AdGroupCriterion as BiddableAdGroupCriterion;
                    if (biddableAdGroupCriterion != null &&
                        (((ProductPartition)biddableAdGroupCriterion.Criterion).PartitionType == ProductPartitionType.Unit))
                    {
                        // We will increase all bids by some predetermined amount or percentage as an example.
                        // For best performance, only upload the properties that you want to update.

                        uploadEntities.Add(new BulkAdGroupProductPartition
                        {
                            AdGroupCriterion = new BiddableAdGroupCriterion
                            {
                                AdGroupId    = bulkAdGroupProductPartition.AdGroupCriterion.AdGroupId,
                                CriterionBid = new FixedBid
                                {
                                    Amount = ((FixedBid)biddableAdGroupCriterion.CriterionBid).Amount + 0.01
                                },
                                Id = bulkAdGroupProductPartition.AdGroupCriterion.Id,
                            }
                        });
                    }
                }

                Reader.Dispose();

                if (uploadEntities.Count > 0)
                {
                    OutputStatusMessage("Changed local bid of all product partitions. Starting upload.\n");

                    Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                    bulkAdGroupProductPartitions = Reader.ReadEntities().ToList().OfType <BulkAdGroupProductPartition>().ToList();
                    OutputBulkAdGroupProductPartitions(bulkAdGroupProductPartitions);
                    Reader.Dispose();
                }
                else
                {
                    OutputStatusMessage("No product partitions in account. \n");
                }

                OutputStatusMessage("Program execution completed\n");
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            // Catch Campaign Management service exceptions
            catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
Exemplo n.º 12
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                BulkService = new BulkServiceManager(authorizationData);

                var progress = new Progress<BulkOperationProgressInfo>(x =>
                    OutputStatusMessage(String.Format("{0} % Complete",
                        x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List<BulkEntity>();

                #region Add

                // Let's create a new budget and share it with a new campaign.

                var bulkBudget = new BulkBudget
                {
                    ClientId = "YourClientIdGoesHere",
                    Budget = new Budget
                    {
                        Amount = 50,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        Id = budgetIdKey,
                        Name = "My Shared Budget " + DateTime.UtcNow,
                    }
                };
                
                var bulkCampaign = new BulkCampaign
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field 
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth. 
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional 
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id 
                        // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below. 
                        Id = campaignIdKey,
                        Name = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId = budgetIdKey,
                        DailyBudget = null,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,

                        TimeZone = "PacificTimeUSCanadaTijuana",

                        // DaylightSaving is not supported in the Bulk file schema. Whether or not you specify it in a BulkCampaign,
                        // the value is not written to the Bulk file, and by default DaylightSaving is set to true.
                        DaylightSaving = true,

                        // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) 
                        // and then, at any time, set an individual ad group or keyword bid strategy to 
                        // Manual CPC (ManualCpcBiddingScheme).
                        // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then ManualCpcBiddingScheme is used by default.
                        BiddingScheme = new EnhancedCpcBiddingScheme { },

                        Status = CampaignStatus.Paused,
                        
                        // Used with FinalUrls shown in the expanded text ads that we will add below.
                        TrackingUrlTemplate =
                            "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
                    }
                };

                // Specify one or more ad groups.
                
                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup = new AdGroup
                    {
                        Id = adGroupIdKey,
                        Name = "Women's Red Shoe Sale",
                        AdDistribution = AdDistribution.Search,
                        BiddingModel = BiddingModel.Keyword,
                        PricingModel = PricingModel.Cpc,
                        StartDate = null,
                        EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date
                        {
                            Month = 12,
                            Day = 31,
                            Year = DateTime.UtcNow.Year + 1
                        },
                        Language = "English",
                        Status = AdGroupStatus.Active,

                        // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new ManualCpcBiddingScheme { },

                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities 
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,
                    },
                };

                // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit,
                // and the third keyword is a duplicate of the second keyword. 

                var bulkKeywords = new [] {
                    new BulkKeyword{
                        AdGroupId = adGroupIdKey,
                        Keyword = new Keyword
                        {
                            Bid = new Bid { Amount = 0.47 },
                            Param2 = "10% Off",
                            MatchType = MatchType.Broad,
                            Text = "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                                   "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                                   "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme { },
                        },
                    },
                    new BulkKeyword{
                        AdGroupId = adGroupIdKey,
                        Keyword = new Keyword
                        {
                            Bid = new Bid { Amount = 0.47 },
                            Param2 = "10% Off",
                            MatchType = MatchType.Phrase,
                            Text = "Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme { },
                        },
                    },
                    new BulkKeyword{
                        AdGroupId = adGroupIdKey,
                        Keyword = new Keyword
                        {
                            Bid = new Bid { Amount = 0.47 },
                            Param2 = "10% Off",
                            MatchType = MatchType.Phrase,
                            Text = "Brand-A Shoes",
                            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                            BiddingScheme = new InheritFromParentBiddingScheme { },
                        },
                    },
                };

                // In this example only the first 3 ads should succeed. 
                // The TitlePart2 of the fourth ad is empty and not valid,
                // and the fifth ad is a duplicate of the second ad. 

                var bulkExpandedTextAds = new [] {
                    new BulkExpandedTextAd
                    {
                        AdGroupId = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Fast & Easy Setup",
                            Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1 = "seattle",
                            Path2 = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and 
                            // landing page URLs. 
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale",
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page 
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale",
                            }, 
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities 
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad, 
                            // and can be used by the ad, ad group, campaign, or account level tracking template. 
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter(){
                                        Key = "promoCode",
                                        Value = "PROMO1"
                                    },
                                    new CustomParameter(){
                                        Key = "season",
                                        Value = "summer"
                                    },
                                }
                            }
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Quick & Easy Setup",
                            Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1 = "seattle",
                            Path2 = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and 
                            // landing page URLs. 
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page 
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            }, 
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities 
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad, 
                            // and can be used by the ad, ad group, campaign, or account level tracking template. 
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter(){
                                        Key = "promoCode",
                                        Value = "PROMO2"
                                    },
                                    new CustomParameter(){
                                        Key = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Fast & Simple Setup",
                            Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1 = "seattle",
                            Path2 = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and 
                            // landing page URLs. 
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page 
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            }, 
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities 
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad, 
                            // and can be used by the ad, ad group, campaign, or account level tracking template. 
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter(){
                                        Key = "promoCode",
                                        Value = "PROMO3"
                                    },
                                    new CustomParameter(){
                                        Key = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "",
                            Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1 = "seattle",
                            Path2 = "shoe sale",  

                            // With FinalUrls you can separate the tracking template, custom parameters, and 
                            // landing page URLs. 
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page 
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            }, 
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities 
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad, 
                            // and can be used by the ad, ad group, campaign, or account level tracking template. 
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter(){
                                        Key = "promoCode",
                                        Value = "PROMO4"
                                    },
                                    new CustomParameter(){
                                        Key = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                    new BulkExpandedTextAd
                    {
                        AdGroupId = adGroupIdKey,
                        ExpandedTextAd = new ExpandedTextAd
                        {
                            TitlePart1 = "Contoso",
                            TitlePart2 = "Quick & Easy Setup",
                            Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                            Path1 = "seattle",
                            Path2 = "shoe sale",

                            // With FinalUrls you can separate the tracking template, custom parameters, and 
                            // landing page URLs. 
                            FinalUrls = new[] {
                                "http://www.contoso.com/womenshoesale"
                            },
                            // Final Mobile URLs can also be used if you want to direct the user to a different page 
                            // for mobile devices.
                            FinalMobileUrls = new[] {
                                "http://mobile.contoso.com/womenshoesale"
                            }, 
                            // You could use a tracking template which would override the campaign level
                            // tracking template. Tracking templates defined for lower level entities 
                            // override those set for higher level entities.
                            // In this example we are using the campaign level tracking template.
                            TrackingUrlTemplate = null,

                            // Set custom parameters that are specific to this ad, 
                            // and can be used by the ad, ad group, campaign, or account level tracking template. 
                            // In this example we are using the campaign level tracking template.
                            UrlCustomParameters = new CustomParameters {
                                Parameters = new[] {
                                    new CustomParameter(){
                                        Key = "promoCode",
                                        Value = "PROMO5"
                                    },
                                    new CustomParameter(){
                                        Key = "season",
                                        Value = "summer"
                                    },
                                }
                            },
                        },
                    },
                };

                uploadEntities.Add(bulkBudget);
                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);

                foreach (var bulkKeyword in bulkKeywords)
                {
                    uploadEntities.Add(bulkKeyword);
                }

                foreach (var bulkExpandedTextAd in bulkExpandedTextAds)
                {
                    uploadEntities.Add(bulkExpandedTextAd);
                }

                // Upload and write the output

                OutputStatusMessage("Adding campaign, budget, ad group, ads, and keywords...\n");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                var downloadEntities = Reader.ReadEntities().ToList();

                var budgetResults = downloadEntities.OfType<BulkBudget>().ToList();
                OutputBulkBudgets(budgetResults);

                var campaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType<BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var keywordResults = downloadEntities.OfType<BulkKeyword>().ToList();
                OutputBulkKeywords(keywordResults);

                var expandedTextAdResults = downloadEntities.OfType<BulkExpandedTextAd>().ToList();
                OutputBulkExpandedTextAds(expandedTextAdResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                // Here is a simple example that updates the campaign budget.
                
                var downloadParameters = new DownloadParameters
                {
                    Entities = BulkDownloadEntity.Budgets | BulkDownloadEntity.Campaigns,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC = null
                };

                // Download all campaigns and shared budgets in the account.
                var bulkFilePath = await BulkService.DownloadFileAsync(downloadParameters);
                OutputStatusMessage("\nDownloaded all campaigns and shared budgets in the account.\n");
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                downloadEntities = Reader.ReadEntities().ToList();
                var getBudgetResults = downloadEntities.OfType<BulkBudget>().ToList();
                OutputBulkBudgets(getBudgetResults);
                var getCampaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(getCampaignResults);

                uploadEntities = new List<BulkEntity>();

                // If the campaign has a shared budget you cannot update the Campaign budget amount,
                // and you must instead update the amount in the Budget record. If you try to update 
                // the budget amount of a Campaign that has a shared budget, the service will return 
                // the CampaignServiceCannotUpdateSharedBudget error code.

                foreach (var entity in getBudgetResults)
                {
                    if (entity.Budget.Id > 0)
                    {
                        // Increase budget by 20 %
                        entity.Budget.Amount *= 1.2m;
                        uploadEntities.Add(entity);
                    }
                }

                foreach (var entity in getCampaignResults)
                {
                    if (entity.Campaign.BudgetId == null || entity.Campaign.BudgetId <= 0)
                    {
                        // Increase existing budgets by 20%
                        // Monthly budgets are deprecated and there will be a forced migration to daily budgets in calendar year 2017. 
                        // Shared budgets do not support the monthly budget type, so this is only applicable to unshared budgets. 
                        // During the migration all campaign level unshared budgets will be rationalized as daily. 
                        // The formula that will be used to convert monthly to daily budgets is: Monthly budget amount / 30.4.
                        // Moving campaign monthly budget to daily budget is encouraged before monthly budgets are migrated. 

                        if (entity.Campaign.BudgetType == BudgetLimitType.MonthlyBudgetSpendUntilDepleted)
                        {
                            // Increase budget by 20 %
                            entity.Campaign.BudgetType = BudgetLimitType.DailyBudgetStandard;
                            entity.Campaign.DailyBudget = entity.Campaign.MonthlyBudget / 30.4 * 1.2;
                        }
                        else
                        {
                            // Increase budget by 20 %
                            entity.Campaign.DailyBudget *= 1.2;
                        }
                        uploadEntities.Add(entity);
                    }
                }

                Reader.Dispose();

                if (uploadEntities.Count > 0)
                {
                    OutputStatusMessage("\nChanged local campaign budget amounts. Starting upload.\n");

                    Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                    downloadEntities = Reader.ReadEntities().ToList();
                    getBudgetResults = downloadEntities.OfType<BulkBudget>().ToList();
                    OutputBulkBudgets(getBudgetResults);
                    getCampaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                    OutputBulkCampaigns(getCampaignResults);
                    Reader.Dispose();
                }
                else
                {
                    OutputStatusMessage("\nNo campaigns or shared budgets in account.\n");
                }

                #endregion Update

                #region CleanUp

                //Delete the campaign, ad group, ads, and keywords that were previously added. 
                //You should remove this region if you want to view the added entities in the 
                //Bing Ads web application or another tool.

                //You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                //When you delete a BulkCampaign, the dependent entities such as BulkAdGroup, BulkKeyword, 
                //and BulkExpandedTextAd are deleted without being specified explicitly.  

                uploadEntities = new List<BulkEntity>();

                foreach (var budgetResult in budgetResults)
                {
                    budgetResult.Status = Status.Deleted;
                    uploadEntities.Add(budgetResult);
                }

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }
                
                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign, budget, ad group, keywords, and ads . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                downloadEntities = Reader.ReadEntities().ToList();
                getBudgetResults = downloadEntities.OfType<BulkBudget>().ToList();
                OutputBulkBudgets(getBudgetResults);
                getCampaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(getCampaignResults);

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException<Microsoft.BingAds.V10.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V10.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null) { Reader.Dispose(); }
                if (Writer != null) { Writer.Dispose(); }
            }
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                BulkService = new BulkServiceManager(authorizationData);

                var progress = new Progress<BulkOperationProgressInfo>(x =>
                    OutputStatusMessage(String.Format("{0} % Complete",
                        x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var downloadParameters = new DownloadParameters
                {
                    Entities = BulkDownloadEntity.RemarketingLists,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC = null
                };

                var bulkFilePath = await BulkService.DownloadFileAsync(downloadParameters);
                OutputStatusMessage("Downloaded all remarketing lists that the current user can associate with ad groups.\n");
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var downloadEntities = Reader.ReadEntities().ToList();

                var remarketingListResults = downloadEntities.OfType<BulkRemarketingList>().ToList();
                OutputBulkRemarketingLists(remarketingListResults);

                Reader.Dispose();

                // You must already have at least one remarketing list. The Bing Ads API does not support
                // remarketing list add, update, or delete operations.
                if (remarketingListResults.Count < 1)
                {
                    OutputStatusMessage("You do not have any remarketing lists that the current user can associate with ad groups.\n");
                    return;
                }

                var uploadEntities = new List<BulkEntity>();

                #region Add

                // Prepare the bulk entities that you want to upload.  

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id = campaignIdKey,
                        Name = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId = null,
                        DailyBudget = 50,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        BiddingScheme = new EnhancedCpcBiddingScheme(),

                        TimeZone = "PacificTimeUSCanadaTijuana",

                        // DaylightSaving is not supported in the Bulk file schema. Whether or not you specify it in a BulkCampaign,
                        // the value is not written to the Bulk file, and by default DaylightSaving is set to true.
                        DaylightSaving = true,

                        TrackingUrlTemplate = null
                    }
                };

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field 
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth. 
                    ClientId = "YourClientIdGoesHere",
                    CampaignId = campaignIdKey,
                    AdGroup = new AdGroup
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkAdGroup, the Id is optional 
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the  
                        // ad group Id will be used when associating this new ad group with a new ad group remarketing list association
                        // in the BulkAdGroupRemarketingListAssociation object below. 
                        Id = adGroupIdKey,
                        Name = "Women's Red Shoe Sale",
                        AdDistribution = AdDistribution.Search,
                        BiddingModel = BiddingModel.Keyword,
                        BiddingScheme = new InheritFromParentBiddingScheme(),
                        PricingModel = PricingModel.Cpc,
                        StartDate = null,
                        EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date
                        {
                            Month = 12,
                            Day = 31,
                            Year = DateTime.UtcNow.Year + 1
                        },
                        Language = "English",
                        Status = AdGroupStatus.Active,
                        TrackingUrlTemplate = null,

                        // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates 
                        // that you want to show ads only to people included in the remarketing list, with the option to change
                        // the bid amount. Ads in this ad group will only show to people included in the remarketing list.
                        RemarketingTargetingSetting = RemarketingTargetingSetting.TargetAndBid,
                    },
                };

                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);

                // This example associates all of the remarketing lists with the new ad group.

                foreach (var remarketingList in remarketingListResults)
                {
                    if (remarketingList.RemarketingList != null && remarketingList.RemarketingList.Id != null)
                    {
                        var BulkAdGroupRemarketingListAssociation = new BulkAdGroupRemarketingListAssociation
                        {
                            ClientId = "MyBulkAdGroupRemarketingListAssociation " + remarketingList.RemarketingList.Id,
                            AdGroupRemarketingListAssociation = new AdGroupRemarketingListAssociation
                            {
                                AdGroupId = adGroupIdKey,
                                BidAdjustment = 20.00,
                                RemarketingListId = (long)remarketingList.RemarketingList.Id,
                                Status = AdGroupRemarketingListAssociationStatus.Paused
                            },
                        };

                        uploadEntities.Add(BulkAdGroupRemarketingListAssociation);
                    }
                }

                // Upload and write the output

                OutputStatusMessage("\nAdding campaign, ad group, and ad group remarketing list associations...\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType<BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var adGroupRemarketingListResults = downloadEntities.OfType<BulkAdGroupRemarketingListAssociation>().ToList();
                OutputBulkAdGroupRemarketingListAssociations(adGroupRemarketingListResults);

                Reader.Dispose();

                #endregion Add

                #region CleanUp

                // Delete the campaign, ad group, and ad group remarketing list associations that were previously added.
                // The remarketing lists will not be deleted. 
                // You should remove this region if you want to view the added entities in the 
                // Bing Ads web application or another tool.

                // You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                // When you delete a BulkCampaign, the dependent entities such as BulkAdGroup and BulkAdGroupRemarketingListAssociation 
                // are deleted without being specified explicitly.  

                uploadEntities = new List<BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign, ad group, and ad group remarketing list associations . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType<BulkCampaign>().ToList());

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException<Microsoft.BingAds.V10.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V10.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null) { Reader.Dispose(); }
                if (Writer != null) { Writer.Dispose(); }
            }
        }