Example #1
0
        /// <summary>
        /// Uploads a list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree for one ad group. You can include BulkAdGroupProductPartition records for more than one
        /// ad group per upload, however, this code example assumes that only one ad group is in scope.
        /// </summary>
        /// <param name="partitionActions">The list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree.</param>
        /// <returns>The BulkAdGroupProductPartition upload results.</returns>
        private async Task <IList <BulkAdGroupProductPartition> > ApplyBulkProductPartitionActions(
            IList <BulkAdGroupProductPartition> partitionActions)
        {
            var fileUploadParameters = new FileUploadParameters
            {
                ResultFileDirectory = FileDirectory,
                ResultFileName      = ResultFileName,
                OverwriteResultFile = true,
                UploadFilePath      = FileDirectory + UploadFileName,
                ResponseMode        = ResponseMode.ErrorsAndResults
            };

            Writer = new BulkFileWriter(FileDirectory + UploadFileName);
            foreach (var partitionAction in partitionActions)
            {
                Writer.WriteEntity(partitionAction);
            }
            Writer.Dispose();

            var bulkFilePath =
                await BulkServiceManager.UploadFileAsync(fileUploadParameters);

            Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);

            var downloadEntities = Reader.ReadEntities().ToList();
            var bulkAdGroupProductPartitionResults = downloadEntities.OfType <BulkAdGroupProductPartition>().ToList();

            // Add this output line if you want to view details of each BulkAdGroupProductPartition.
            //OutputBulkAdGroupProductPartitions(bulkAdGroupProductPartitionResults);

            Reader.Dispose();

            return(bulkAdGroupProductPartitionResults);
        }
Example #2
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);
        }
Example #3
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_bulkFileReader != null)
                {
                    _bulkFileReader.Dispose();

                    _bulkFileReader = null;
                }
            }
        }
        /// <summary>
        /// Uploads a list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree for one ad group. You can include BulkAdGroupProductPartition records for more than one
        /// ad group per upload, however, this code example assumes that only one ad group is in scope.
        /// </summary>
        /// <param name="partitionActions">The list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree.</param>
        /// <returns>The BulkAdGroupProductPartition upload results.</returns>
        private async Task <IList <BulkAdGroupProductPartition> > ApplyBulkProductPartitionActions(
            IList <BulkAdGroupProductPartition> partitionActions)
        {
            var fileUploadParameters = new FileUploadParameters
            {
                ResultFileDirectory = FileDirectory,
                ResultFileName      = ResultFileName,
                OverwriteResultFile = true,
                UploadFilePath      = FileDirectory + UploadFileName,
                ResponseMode        = ResponseMode.ErrorsAndResults
            };

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

            var tokenSource = new CancellationTokenSource();

            tokenSource.CancelAfter(TimeoutInMilliseconds);

            Writer = new BulkFileWriter(
                filePath: FileDirectory + UploadFileName);

            foreach (var partitionAction in partitionActions)
            {
                Writer.WriteEntity(partitionAction);
            }
            Writer.Dispose();

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

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

            OutputStatusMessage("Upload results:");

            var downloadEntities = Reader.ReadEntities().ToList();
            var bulkAdGroupProductPartitionResults = downloadEntities.OfType <BulkAdGroupProductPartition>().ToList();

            OutputBulkAdGroupProductPartitions(bulkAdGroupProductPartitionResults);

            Reader.Dispose();

            return(bulkAdGroupProductPartitionResults);
        }
 public BulkFileReaderEnumerable(BulkFileReader bulkFileReader)
 {
     _bulkFileReader = bulkFileReader;
 }
        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))));

                #region Add

                const int appAdExtensionIdKey = -11;
                const int callAdExtensionIdKey = -12;
                const int locationAdExtensionIdKey = -13;
                const int siteLinksAdExtensionIdKey = -14;
                const int campaignIdKey = -123;

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object, 
                // and additional elements needed to read from and write to a bulk file. 

                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.",
                        BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted,
                        MonthlyBudget = 1000.00,
                        TimeZone = "PacificTimeUSCanadaTijuana",
                    }
                };

                // Prepare ad extensions for upload

                var bulkAppAdExtension = new BulkAppAdExtension
                {
                    AccountId = authorizationData.AccountId,
                    AppAdExtension = new AppAdExtension
                    {
                        AppPlatform = "Windows",
                        AppStoreId = "AppStoreIdGoesHere",
                        DestinationUrl = "DestinationUrlGoesHere",
                        DisplayText = "Contoso",
                        Id = appAdExtensionIdKey,
                    }
                };

                var bulkCallAdExtension = new BulkCallAdExtension
                {
                    AccountId = authorizationData.AccountId,
                    CallAdExtension = new CallAdExtension
                    {
                        CountryCode = "US",
                        PhoneNumber = "2065550100",
                        IsCallOnly = false,
                        Id = callAdExtensionIdKey
                    }
                };

                var bulkLocationAdExtension = new BulkLocationAdExtension
                {
                    AccountId = authorizationData.AccountId,
                    LocationAdExtension = new LocationAdExtension
                    {
                        Id = locationAdExtensionIdKey,
                        PhoneNumber = "206-555-0100",
                        CompanyName = "Contoso Shoes",
                        IconMediaId = null,
                        ImageMediaId = null,
                        Address = new Address
                        {
                            StreetAddress = "1234 Washington Place",
                            StreetAddress2 = "Suite 1210",
                            CityName = "Woodinville",
                            ProvinceName = "WA",
                            CountryCode = "US",
                            PostalCode = "98608"
                        }
                    }
                };

                // Note that when written to file using the BulkFileWriter, an extra Sitelink Ad Extension record with Deleted
                // status precedes the actual site link record or records that you want to upload. All bulk entities 
                // that are derived from MultiRecordBulkEntiy are preceded with a Deleted record using the BulkFileWriter. 
                // In this example it is a moot point because we are creating a new ad extension. If the specified
                // ad extension Id already exists in your account, the Deleted record effectively deletes the existing
                // extension and replaces it with the SiteLinksAdExtension specified below.

                var bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension
                {
                    AccountId = authorizationData.AccountId,
                    SiteLinksAdExtension = new SiteLinksAdExtension
                    {
                        // Note that if you do not specify a negative Id as reference key, each of SiteLinks items will
                        // be split during upload into separate sitelink ad extensions with unique ad extension identifiers.
                        Id = siteLinksAdExtensionIdKey,
                        SiteLinks = new List<SiteLink>
                                {
                                    new SiteLink
                                        {
                                            DestinationUrl = "Contoso.com",
                                            DisplayText = "Women's Shoe Sale 1"
                                        },
                                    new SiteLink
                                        {
                                            DestinationUrl = "Contoso.com/WomenShoeSale/2",
                                            DisplayText = "Women's Shoe Sale 2"
                                        }
                                }
                    }
                    // Note that BulkSiteLinkAdExtension.SiteLinks is read only and only 
                    // accessible when reading results from the download or upload results file.
                    // To upload new site links for a new site links ad extension, you should specify
                    // BulkSiteLinkAdExtension.SiteLinksAdExtension.SiteLinks as shown above.
                };

                // Prepare ad extension associations for upload

                var bulkCampaignAppAdExtension = new BulkCampaignAppAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = appAdExtensionIdKey,
                        EntityId = campaignIdKey
                    }
                };

                var bulkCampaignCallAdExtension = new BulkCampaignCallAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = callAdExtensionIdKey,
                        EntityId = campaignIdKey
                    }
                };

                var bulkCampaignLocationAdExtension = new BulkCampaignLocationAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = locationAdExtensionIdKey,
                        EntityId = campaignIdKey
                    }
                };

                var bulkCampaignSiteLinkAdExtension = new BulkCampaignSiteLinkAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = siteLinksAdExtensionIdKey,
                        EntityId = campaignIdKey
                    }
                };


                // Write the entities created above, to the specified file.
                // Dependent entities such as BulkCampaignCallAdExtension must be written after any dependencies,  
                // for example the BulkCampaign and BulkCallAdExtension. 

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkAppAdExtension);
                Writer.WriteEntity(bulkCallAdExtension);
                Writer.WriteEntity(bulkLocationAdExtension);
                Writer.WriteEntity(bulkSiteLinkAdExtension);

                Writer.WriteEntity(bulkCampaignAppAdExtension);
                Writer.WriteEntity(bulkCampaignCallAdExtension);
                Writer.WriteEntity(bulkCampaignLocationAdExtension);
                Writer.WriteEntity(bulkCampaignSiteLinkAdExtension);


                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("\nAdding campaign, ad extensions, and associations . . .\n");
                var bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");

                // Write the upload output

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

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

                var appAdExtensionResults = bulkEntities.OfType<BulkAppAdExtension>().ToList();
                OutputBulkAppAdExtensions(appAdExtensionResults);

                var callAdExtensionResults = bulkEntities.OfType<BulkCallAdExtension>().ToList();
                OutputBulkCallAdExtensions(callAdExtensionResults);

                var locationAdExtensionResults = bulkEntities.OfType<BulkLocationAdExtension>().ToList();
                OutputBulkLocationAdExtensions(locationAdExtensionResults);

                var siteLinkAdExtensionResults = bulkEntities.OfType<BulkSiteLinkAdExtension>().ToList();
                OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults);

                OutputBulkCampaignAppAdExtensions(bulkEntities.OfType<BulkCampaignAppAdExtension>().ToList());
                OutputBulkCampaignCallAdExtensions(bulkEntities.OfType<BulkCampaignCallAdExtension>().ToList());
                OutputBulkCampaignLocationAdExtensions(bulkEntities.OfType<BulkCampaignLocationAdExtension>().ToList());
                OutputBulkCampaignSiteLinkAdExtensions(bulkEntities.OfType<BulkCampaignSiteLinkAdExtension>().ToList());

                Reader.Dispose();

                #endregion Add

                #region Update

                // Update the site links ad extension. 
                // Do not create a BulkSiteLinkAdExtension for update, unless you want to replace all existing SiteLinks
                // with the specified SiteLinks for the specified ad extension. 
                // Instead you should upload one or more site links as a list of BulkSiteLink.

                var bulkSiteLinks = new List<BulkSiteLink>
                    {
                        new BulkSiteLink
                            {
                                SiteLink = new SiteLink
                                    {
                                        DestinationUrl = "Contoso.com",
                                        DisplayText = "Red Shoe Sale"
                                    }
                            }
                    };

                // Add an additional site link, and update an existing site link

                if (siteLinkAdExtensionResults.ToArray().Any() &&
                    siteLinkAdExtensionResults.ToArray()[0].SiteLinks.ToArray().Any())
                {
                    var existingSiteLink = siteLinkAdExtensionResults.ToArray()[0].SiteLinks[0];
                    existingSiteLink.SiteLink.DisplayText = "Red Shoes Super Sale";

                    // Associate the new site links with the identifier of the existing site links ad extension

                    foreach (var bulkSiteLink in bulkSiteLinks)
                    {
                        bulkSiteLink.AdExtensionId = existingSiteLink.AdExtensionId;
                    }

                    bulkSiteLinks.Add(existingSiteLink);
                }

                // Write the new site link and updated site link to the file

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                foreach (var bulkSiteLink in bulkSiteLinks)
                {
                    Writer.WriteEntity(bulkSiteLink);
                }

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("\nUpdating sitelinks . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");

                // Write any upload errors

                bulkEntities = Reader.ReadEntities().ToList();
                var siteLinkResults = bulkEntities.OfType<BulkSiteLink>().ToList();
                OutputBulkSiteLinks(siteLinkResults);

                Reader.Dispose();

                #endregion Update

                #region Delete

                // Prepare the bulk entities that you want to delete. You must set the Id field to the corresponding 
                // entity identifier, and the Status field to Deleted. 

                var campaignId = campaignResults[0].Campaign.Id;
                bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id = campaignId,
                        Status = CampaignStatus.Deleted
                    }
                };

                var appAdExtensionId = appAdExtensionResults[0].AppAdExtension.Id;
                bulkAppAdExtension = new BulkAppAdExtension
                {
                    AppAdExtension = new AppAdExtension
                    {
                        Id = appAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };

                var callAdExtensionId = callAdExtensionResults[0].CallAdExtension.Id;
                bulkCallAdExtension = new BulkCallAdExtension
                {
                    CallAdExtension = new CallAdExtension
                    {
                        Id = callAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };

                var locationAdExtensionId = locationAdExtensionResults[0].LocationAdExtension.Id;
                bulkLocationAdExtension = new BulkLocationAdExtension
                {
                    LocationAdExtension = new LocationAdExtension
                    {
                        Id = locationAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };


                var siteLinkAdExtensionId = siteLinkAdExtensionResults[0].SiteLinksAdExtension.Id;
                bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension
                {
                    SiteLinksAdExtension = new SiteLinksAdExtension
                    {
                        Id = siteLinkAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };

                // Write the entities that you want deleted, to the specified file.
                // Dependent entities such as BulkCampaignCallAdExtension are deleted without being specified explicitly.  
                // For example, if you delete either BulkCampaign or BulkCallAdExtension, then the equivalent of 
                // BulkCampaignCallAdExtension is effectively deleted. 

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkAppAdExtension);
                Writer.WriteEntity(bulkCallAdExtension);
                Writer.WriteEntity(bulkLocationAdExtension);
                Writer.WriteEntity(bulkSiteLinkAdExtension);


                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("\nDeleting campaign and ad extensions . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");

                // Write the upload output

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

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

                appAdExtensionResults = bulkEntities.OfType<BulkAppAdExtension>().ToList();
                OutputBulkAppAdExtensions(appAdExtensionResults);

                callAdExtensionResults = bulkEntities.OfType<BulkCallAdExtension>().ToList();
                OutputBulkCallAdExtensions(callAdExtensionResults);

                locationAdExtensionResults = bulkEntities.OfType<BulkLocationAdExtension>().ToList();
                OutputBulkLocationAdExtensions(locationAdExtensionResults);

                siteLinkAdExtensionResults = bulkEntities.OfType<BulkSiteLinkAdExtension>().ToList();
                OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults);

                OutputBulkCampaignAppAdExtensions(bulkEntities.OfType<BulkCampaignAppAdExtension>().ToList());
                OutputBulkCampaignCallAdExtensions(bulkEntities.OfType<BulkCampaignCallAdExtension>().ToList());
                OutputBulkCampaignLocationAdExtensions(bulkEntities.OfType<BulkCampaignLocationAdExtension>().ToList());
                OutputBulkCampaignSiteLinkAdExtensions(bulkEntities.OfType<BulkCampaignSiteLinkAdExtension>().ToList());

                Reader.Dispose();

                #endregion Delete

            }
            // 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.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.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))));

                #region Add

                const int callAdExtensionIdKey      = -12;
                const int locationAdExtensionIdKey  = -13;
                const int siteLinksAdExtensionIdKey = -14;
                const int campaignIdKey             = -123;

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object,
                // and additional elements needed to read from and write to a bulk file.

                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.",
                        BudgetType     = BudgetLimitType.MonthlyBudgetSpendUntilDepleted,
                        MonthlyBudget  = 1000.00,
                        TimeZone       = "PacificTimeUSCanadaTijuana",
                        DaylightSaving = true
                    }
                };

                // Prepare ad extensions for upload

                var bulkCallAdExtension = new BulkCallAdExtension
                {
                    AccountId       = authorizationData.AccountId,
                    CallAdExtension = new CallAdExtension
                    {
                        CountryCode = "US",
                        PhoneNumber = "2065550100",
                        IsCallOnly  = false,
                        Id          = callAdExtensionIdKey
                    }
                };

                var bulkLocationAdExtension = new BulkLocationAdExtension
                {
                    AccountId           = authorizationData.AccountId,
                    LocationAdExtension = new LocationAdExtension
                    {
                        Id           = locationAdExtensionIdKey,
                        PhoneNumber  = "206-555-0100",
                        CompanyName  = "Contoso Shoes",
                        IconMediaId  = null,
                        ImageMediaId = null,
                        Address      = new Address
                        {
                            StreetAddress  = "1234 Washington Place",
                            StreetAddress2 = "Suite 1210",
                            CityName       = "Woodinville",
                            ProvinceName   = "WA",
                            CountryCode    = "US",
                            PostalCode     = "98608"
                        }
                    }
                };

                // Note that when written to file using the BulkFileWriter, an extra Sitelink Ad Extension record with Deleted
                // status precedes the actual site link record or records that you want to upload. All bulk entities
                // that are derived from MultiRecordBulkEntiy are preceded with a Deleted record using the BulkFileWriter.
                // In this example it is a moot point because we are creating a new ad extension. If the specified
                // ad extension Id already exists in your account, the Deleted record effectively deletes the existing
                // extension and replaces it with the SiteLinksAdExtension specified below.

                var bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension
                {
                    AccountId            = authorizationData.AccountId,
                    SiteLinksAdExtension = new SiteLinksAdExtension
                    {
                        // Note that if you do not specify a negative Id as reference key, each of SiteLinks items will
                        // be split during upload into separate sitelink ad extensions with unique ad extension identifiers.
                        Id        = siteLinksAdExtensionIdKey,
                        SiteLinks = new List <SiteLink>
                        {
                            new SiteLink
                            {
                                DestinationUrl = "Contoso.com",
                                DisplayText    = "Women's Shoe Sale 1"
                            },
                            new SiteLink
                            {
                                DestinationUrl = "Contoso.com/WomenShoeSale/2",
                                DisplayText    = "Women's Shoe Sale 2"
                            }
                        }
                    }
                    // Note that BulkSiteLinkAdExtension.SiteLinks is read only and only
                    // accessible when reading results from the download or upload results file.
                    // To upload new site links for a new site links ad extension, you should specify
                    // BulkSiteLinkAdExtension.SiteLinksAdExtension.SiteLinks as shown above.
                };

                // Prepare ad extension associations for upload

                var bulkCampaignCallAdExtension = new BulkCampaignCallAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = callAdExtensionIdKey,
                        EntityId      = campaignIdKey
                    }
                };

                var bulkCampaignLocationAdExtension = new BulkCampaignLocationAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = locationAdExtensionIdKey,
                        EntityId      = campaignIdKey
                    }
                };

                var bulkCampaignSiteLinkAdExtension = new BulkCampaignSiteLinkAdExtension
                {
                    AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation
                    {
                        AdExtensionId = siteLinksAdExtensionIdKey,
                        EntityId      = campaignIdKey
                    }
                };


                // Write the entities created above, to the specified file.
                // Dependent entities such as BulkCampaignCallAdExtension must be written after any dependencies,
                // for example the BulkCampaign and BulkCallAdExtension.

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCallAdExtension);
                Writer.WriteEntity(bulkLocationAdExtension);
                Writer.WriteEntity(bulkSiteLinkAdExtension);

                Writer.WriteEntity(bulkCampaignCallAdExtension);
                Writer.WriteEntity(bulkCampaignLocationAdExtension);
                Writer.WriteEntity(bulkCampaignSiteLinkAdExtension);


                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                var bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Added Entities\n");

                // Write the upload output

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

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

                var callAdExtensionResults = bulkEntities.OfType <BulkCallAdExtension>().ToList();
                OutputBulkCallAdExtensions(callAdExtensionResults);

                var locationAdExtensionResults = bulkEntities.OfType <BulkLocationAdExtension>().ToList();
                OutputBulkLocationAdExtensions(locationAdExtensionResults);

                var siteLinkAdExtensionResults = bulkEntities.OfType <BulkSiteLinkAdExtension>().ToList();
                OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                // Update the site links ad extension.
                // Do not create a BulkSiteLinkAdExtension for update, unless you want to replace all existing SiteLinks
                // with the specified SiteLinks for the specified ad extension.
                // Instead you should upload one or more site links as a list of BulkSiteLink.

                var bulkSiteLinks = new List <BulkSiteLink>
                {
                    new BulkSiteLink
                    {
                        SiteLink = new SiteLink
                        {
                            DestinationUrl = "Contoso.com",
                            DisplayText    = "Red Shoe Sale"
                        }
                    }
                };

                // Add an additional site link, and update an existing site link

                if (siteLinkAdExtensionResults.ToArray().Any() &&
                    siteLinkAdExtensionResults.ToArray()[0].SiteLinks.ToArray().Any())
                {
                    var existingSiteLink = siteLinkAdExtensionResults.ToArray()[0].SiteLinks[0];
                    existingSiteLink.SiteLink.DisplayText = "Red Shoes Super Sale";

                    // Associate the new site links with the identifier of the existing site links ad extension

                    foreach (var bulkSiteLink in bulkSiteLinks)
                    {
                        bulkSiteLink.AdExtensionId = existingSiteLink.AdExtensionId;
                    }

                    bulkSiteLinks.Add(existingSiteLink);
                }

                // Write the new site link and updated site link to the file

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                foreach (var bulkSiteLink in bulkSiteLinks)
                {
                    Writer.WriteEntity(bulkSiteLink);
                }

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Updated Entities\n");

                // Write any upload errors

                bulkEntities = Reader.ReadEntities().ToList();
                var siteLinkResults = bulkEntities.OfType <BulkSiteLink>().ToList();
                OutputBulkSiteLinks(siteLinkResults);

                Reader.Dispose();

                #endregion Update

                #region Delete

                // Prepare the bulk entities that you want to delete. You must set the Id field to the corresponding
                // entity identifier, and the Status field to Deleted.

                var campaignId = campaignResults[0].Campaign.Id;
                bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id     = campaignId,
                        Status = CampaignStatus.Deleted
                    }
                };

                var callAdExtensionId = callAdExtensionResults[0].CallAdExtension.Id;
                bulkCallAdExtension = new BulkCallAdExtension
                {
                    CallAdExtension = new CallAdExtension
                    {
                        Id     = callAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };

                var locationAdExtensionId = locationAdExtensionResults[0].LocationAdExtension.Id;
                bulkLocationAdExtension = new BulkLocationAdExtension
                {
                    LocationAdExtension = new LocationAdExtension
                    {
                        Id     = locationAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };


                var siteLinkAdExtensionId = siteLinkAdExtensionResults[0].SiteLinksAdExtension.Id;
                bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension
                {
                    SiteLinksAdExtension = new SiteLinksAdExtension
                    {
                        Id     = siteLinkAdExtensionId,
                        Status = AdExtensionStatus.Deleted
                    }
                };

                // Write the entities that you want deleted, to the specified file.
                // Dependent entities such as BulkCampaignCallAdExtension are deleted without being specified explicitly.
                // For example, if you delete either BulkCampaign or BulkCallAdExtension, then the equivalent of
                // BulkCampaignCallAdExtension is effectively deleted.

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCallAdExtension);
                Writer.WriteEntity(bulkLocationAdExtension);
                Writer.WriteEntity(bulkSiteLinkAdExtension);


                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Deleted Entities\n");

                // Write the upload output

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

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

                callAdExtensionResults = bulkEntities.OfType <BulkCallAdExtension>().ToList();
                OutputBulkCallAdExtensions(callAdExtensionResults);

                locationAdExtensionResults = bulkEntities.OfType <BulkLocationAdExtension>().ToList();
                OutputBulkLocationAdExtensions(locationAdExtensionResults);

                siteLinkAdExtensionResults = bulkEntities.OfType <BulkSiteLinkAdExtension>().ToList();
                OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults);

                Reader.Dispose();

                #endregion Delete
            }
            // 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.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.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();
                }
            }
        }
Example #8
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();
                }
            }
        }
Example #9
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))));

                #region Add

                const int targetIdKey   = -1;
                const int campaignIdKey = -123;

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object,
                // and additional elements needed to read from and write to a bulk file.

                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.",
                        BudgetType     = BudgetLimitType.MonthlyBudgetSpendUntilDepleted,
                        MonthlyBudget  = 1000.00,
                        TimeZone       = "PacificTimeUSCanadaTijuana",
                        DaylightSaving = true
                    }
                };

                // Prepare targets for upload

                var bulkCampaignDayTimeTarget = new BulkCampaignDayTimeTarget
                {
                    CampaignId    = campaignIdKey,
                    TargetId      = targetIdKey,
                    DayTimeTarget = new DayTimeTarget
                    {
                        Bids = new List <DayTimeTargetBid>
                        {
                            new DayTimeTargetBid
                            {
                                BidAdjustment = 10,
                                Day           = Day.Friday,
                                FromHour      = 11,
                                FromMinute    = Minute.Zero,
                                ToHour        = 13,
                                ToMinute      = Minute.Fifteen
                            },
                            new DayTimeTargetBid
                            {
                                BidAdjustment = 20,
                                Day           = Day.Saturday,
                                FromHour      = 11,
                                FromMinute    = Minute.Zero,
                                ToHour        = 13,
                                ToMinute      = Minute.Fifteen
                            }
                        }
                    }
                };

                var bulkCampaignLocationTarget = new BulkCampaignLocationTarget
                {
                    CampaignId = campaignIdKey,
                    TargetId   = targetIdKey,

                    IntentOption = IntentOption.PeopleIn,
                    CityTarget   = new CityTarget
                    {
                        Bids = new List <CityTargetBid>
                        {
                            new CityTargetBid
                            {
                                BidAdjustment = 15,
                                City          = "Toronto, Toronto ON CA",
                                IsExcluded    = false
                            }
                        }
                    },
                    CountryTarget = new CountryTarget
                    {
                        Bids = new List <CountryTargetBid>
                        {
                            new CountryTargetBid
                            {
                                BidAdjustment    = 15,
                                CountryAndRegion = "CA",
                                IsExcluded       = false
                            }
                        }
                    },
                    MetroAreaTarget = new MetroAreaTarget
                    {
                        Bids = new List <MetroAreaTargetBid>
                        {
                            new MetroAreaTargetBid
                            {
                                BidAdjustment = 15,
                                MetroArea     = "Seattle-Tacoma, WA, WA US",
                                IsExcluded    = false
                            }
                        }
                    },
                    StateTarget = new StateTarget
                    {
                        Bids = new List <StateTargetBid>
                        {
                            new StateTargetBid
                            {
                                BidAdjustment = 15,
                                State         = "US-WA",
                                IsExcluded    = false
                            }
                        }
                    },
                    PostalCodeTarget = new PostalCodeTarget
                    {
                        Bids = new List <PostalCodeTargetBid>
                        {
                            new PostalCodeTargetBid
                            {
                                // Bid adjustments are not allowed for location exclusions.
                                // If IsExcluded is true, this element will be ignored.
                                BidAdjustment = 10,
                                PostalCode    = "98052, WA US",
                                IsExcluded    = false
                            }
                        }
                    }
                };

                var bulkCampaignRadiusTarget = new BulkCampaignRadiusTarget
                {
                    CampaignId = campaignIdKey,
                    TargetId   = targetIdKey,

                    RadiusTarget = new RadiusTarget2
                    {
                        Bids = new List <RadiusTargetBid2>
                        {
                            new RadiusTargetBid2
                            {
                                BidAdjustment    = 50,
                                LatitudeDegrees  = 47.755367,
                                LongitudeDegrees = -122.091827,
                                Radius           = 11,
                                RadiusUnit       = DistanceUnit.Kilometers
                            }
                        }
                    }
                };


                // Write the entities created above, to the specified file.
                // Dependent entities such as BulkCampaignLocationTarget must be written after any dependencies,
                // for example a BulkCampaign.

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCampaignDayTimeTarget);
                Writer.WriteEntity(bulkCampaignLocationTarget);
                Writer.WriteEntity(bulkCampaignRadiusTarget);

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                var bulkFilePath =
                    await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path" + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Added Entities\n");

                // Write the upload output

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

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

                var campaignDayTimeTargetResults = bulkEntities.OfType <BulkCampaignDayTimeTarget>().ToList();
                OutputBulkCampaignDayTimeTargets(campaignDayTimeTargetResults);

                var campaignLocationTargetResults = bulkEntities.OfType <BulkCampaignLocationTarget>().ToList();
                OutputBulkCampaignLocationTargets(campaignLocationTargetResults);

                var campaignRadiusTargetResults = bulkEntities.OfType <BulkCampaignRadiusTarget>().ToList();
                OutputBulkCampaignRadiusTargets(campaignRadiusTargetResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                // Update the day and time target.
                // Do not create a BulkAdGroupDayTimeTarget for update, unless you want to replace all existing DayTime target bids
                // with the specified day and time target set for the current bulk upload.
                // Instead you should upload one or more bids as a list of BulkCampaignDayTimeTargetBid.

                var bulkCampaignDayTimeTargetBids = new List <BulkCampaignDayTimeTargetBid>
                {
                    new BulkCampaignDayTimeTargetBid
                    {
                        CampaignId       = campaignDayTimeTargetResults[0].CampaignId,
                        TargetId         = targetIdKey,
                        DayTimeTargetBid = new DayTimeTargetBid
                        {
                            BidAdjustment = 15,
                            Day           = Day.Friday,
                            FromHour      = 11,
                            FromMinute    = Minute.Zero,
                            ToHour        = 13,
                            ToMinute      = Minute.Fifteen
                        }
                    }
                };

                // Write the updated target to the file

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                foreach (var bulkCampaignDayTimeTargetBid in bulkCampaignDayTimeTargetBids)
                {
                    Writer.WriteEntity(bulkCampaignDayTimeTargetBid);
                }

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Updated Entities\n");


                // Write any upload errors

                var campaignDayTimeTargetBidResults =
                    Reader.ReadEntities().OfType <BulkCampaignDayTimeTargetBid>().ToList();
                OutputBulkCampaignDayTimeTargetBids(campaignDayTimeTargetBidResults);

                Reader.Dispose();

                #endregion Update

                #region Delete

                // Prepare the bulk entities that you want to delete. You must set the Id field to the corresponding
                // entity identifier, and the Status field to Deleted.

                var campaignId = campaignResults[0].Campaign.Id;
                bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id     = campaignId,
                        Status = CampaignStatus.Deleted
                    }
                };

                var targetId = campaignDayTimeTargetResults[0].TargetId;

                bulkCampaignDayTimeTarget = new BulkCampaignDayTimeTarget
                {
                    Status     = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId   = targetId
                };

                bulkCampaignLocationTarget = new BulkCampaignLocationTarget
                {
                    Status     = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId   = targetId
                };

                bulkCampaignRadiusTarget = new BulkCampaignRadiusTarget
                {
                    Status     = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId   = targetId
                };


                // Write the entities that you want deleted, to the specified file.

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCampaignDayTimeTarget);
                Writer.WriteEntity(bulkCampaignLocationTarget);
                Writer.WriteEntity(bulkCampaignRadiusTarget);

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path" + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Deleted Entities\n");

                // Write the upload output

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

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

                campaignDayTimeTargetResults = bulkEntities.OfType <BulkCampaignDayTimeTarget>().ToList();
                OutputBulkCampaignDayTimeTargets(campaignDayTimeTargetResults);

                campaignLocationTargetResults = bulkEntities.OfType <BulkCampaignLocationTarget>().ToList();
                OutputBulkCampaignLocationTargets(campaignLocationTargetResults);

                campaignRadiusTargetResults = bulkEntities.OfType <BulkCampaignRadiusTarget>().ToList();
                OutputBulkCampaignRadiusTargets(campaignRadiusTargetResults);

                Reader.Dispose();

                #endregion Delete
            }
            // 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.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.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 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();
                }
            }
        }
Example #11
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);
            }
        }
Example #12
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();
                }
            }
        }
        /// <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
            {
                Entities = BulkDownloadEntity.AdGroupProductPartitions,
                ResultFileDirectory = FileDirectory,
                ResultFileName = ResultFileName,
                OverwriteResultFile = true,
                LastSyncTimeInUTC = null
            };

            var bulkFilePath = await BulkService.DownloadFileAsync(downloadParameters);
            Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
            var bulkEntities = Reader.ReadEntities().ToList();
            var bulkAdGroupProductPartitionResults = bulkEntities.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>
        /// Uploads a list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree for one ad group. You can include BulkAdGroupProductPartition records for more than one
        /// ad group per upload, however, this code example assumes that only one ad group is in scope. 
        /// </summary>
        /// <param name="partitionActions">The list of BulkAdGroupProductPartition objects that must represent
        /// a product partition tree.</param>
        /// <returns>The BulkAdGroupProductPartition upload results.</returns>
        private async Task<IList<BulkAdGroupProductPartition>> ApplyBulkProductPartitionActions(
            IList<BulkAdGroupProductPartition> partitionActions)
        {
            var fileUploadParameters = new FileUploadParameters
            {
                ResultFileDirectory = FileDirectory,
                ResultFileName = ResultFileName,
                OverwriteResultFile = true,
                UploadFilePath = FileDirectory + UploadFileName,
                ResponseMode = ResponseMode.ErrorsAndResults
            };

            Writer = new BulkFileWriter(FileDirectory + UploadFileName);
            foreach (var partitionAction in partitionActions)
            {
                Writer.WriteEntity(partitionAction);
            }
            Writer.Dispose();

            var bulkFilePath =
                await BulkService.UploadFileAsync(fileUploadParameters);
            Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
            
            var bulkEntities = Reader.ReadEntities().ToList();
            var bulkAdGroupProductPartitionResults = bulkEntities.OfType<BulkAdGroupProductPartition>().ToList();
            OutputBulkAdGroupProductPartitions(bulkAdGroupProductPartitionResults);

            Reader.Dispose();

            return bulkAdGroupProductPartitionResults;
        }
Example #15
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();
                }
            }
        }
Example #16
0
        public BulkFileReaderIEnumerator(BulkFileReader bulkFileReader)
        {
            _bulkFileReader = bulkFileReader;

            _readEntities = _bulkFileReader.ReadEntities().GetEnumerator();
        }
Example #17
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);
            }
        }
Example #18
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))));

                #region Add

                const int targetIdKey = -1;
                const int campaignIdKey = -123;

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object, 
                // and additional elements needed to read from and write to a bulk file. 

                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.",
                        BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted,
                        MonthlyBudget = 1000.00,
                        TimeZone = "PacificTimeUSCanadaTijuana",
                        DaylightSaving = true
                    }
                };

                // Prepare targets for upload

                var bulkCampaignDayTimeTarget = new BulkCampaignDayTimeTarget
                {
                    CampaignId = campaignIdKey,
                    TargetId = targetIdKey,
                    DayTimeTarget = new DayTimeTarget
                    {
                        Bids = new List<DayTimeTargetBid>
                        {
                            new DayTimeTargetBid
                            {
                                BidAdjustment = 10,
                                Day = Day.Friday,
                                FromHour = 11,
                                FromMinute = Minute.Zero,
                                ToHour = 13,
                                ToMinute = Minute.Fifteen
                            },
                            new DayTimeTargetBid
                            {
                                BidAdjustment = 20,
                                Day = Day.Saturday,
                                FromHour = 11,
                                FromMinute = Minute.Zero,
                                ToHour = 13,
                                ToMinute = Minute.Fifteen
                            }
                        }
                    }
                };

                var bulkCampaignLocationTarget = new BulkCampaignLocationTarget
                {
                    CampaignId = campaignIdKey,
                    TargetId = targetIdKey,

                    IntentOption = IntentOption.PeopleIn,
                    CityTarget = new CityTarget
                    {
                        Bids = new List<CityTargetBid>
                        {
                            new CityTargetBid
                            {
                                BidAdjustment = 15,
                                City = "Toronto, Toronto ON CA",
                                IsExcluded = false
                            }
                        }
                    },
                    CountryTarget = new CountryTarget
                    {
                        Bids = new List<CountryTargetBid>
                        {
                            new CountryTargetBid
                            {
                                BidAdjustment = 15,
                                CountryAndRegion = "CA",
                                IsExcluded = false
                            }
                        }
                    },
                    MetroAreaTarget = new MetroAreaTarget
                    {
                        Bids = new List<MetroAreaTargetBid>
                        {
                            new MetroAreaTargetBid
                            {
                                BidAdjustment = 15,
                                MetroArea = "Seattle-Tacoma, WA, WA US",
                                IsExcluded = false
                            }
                        }
                    },
                    StateTarget = new StateTarget
                    {
                        Bids = new List<StateTargetBid>
                        {
                            new StateTargetBid
                            {
                                BidAdjustment = 15,
                                State = "US-WA",
                                IsExcluded = false
                            }
                        }
                    },
                    PostalCodeTarget = new PostalCodeTarget
                    {
                        Bids = new List<PostalCodeTargetBid>
                        {
                            new PostalCodeTargetBid
                            {
                                // Bid adjustments are not allowed for location exclusions. 
                                // If IsExcluded is true, this element will be ignored.
                                BidAdjustment = 10,
                                PostalCode = "98052, WA US",
                                IsExcluded = false
                            }
                        }
                    }
                };

                var bulkCampaignRadiusTarget = new BulkCampaignRadiusTarget
                {
                    CampaignId = campaignIdKey,
                    TargetId = targetIdKey,

                    RadiusTarget = new RadiusTarget2
                    {
                        Bids = new List<RadiusTargetBid2>
                        {
                            new RadiusTargetBid2
                            {
                                BidAdjustment = 50,
                                LatitudeDegrees = 47.755367,
                                LongitudeDegrees = -122.091827,
                                Radius = 11,
                                RadiusUnit = DistanceUnit.Kilometers
                            }
                        }
                    }
                };


                // Write the entities created above, to the specified file.
                // Dependent entities such as BulkCampaignLocationTarget must be written after any dependencies,  
                // for example a BulkCampaign. 

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCampaignDayTimeTarget);
                Writer.WriteEntity(bulkCampaignLocationTarget);
                Writer.WriteEntity(bulkCampaignRadiusTarget);

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                var bulkFilePath =
                    await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path" + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Added Entities\n");

                // Write the upload output

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

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

                var campaignDayTimeTargetResults = bulkEntities.OfType<BulkCampaignDayTimeTarget>().ToList();
                OutputBulkCampaignDayTimeTargets(campaignDayTimeTargetResults);

                var campaignLocationTargetResults = bulkEntities.OfType<BulkCampaignLocationTarget>().ToList();
                OutputBulkCampaignLocationTargets(campaignLocationTargetResults);

                var campaignRadiusTargetResults = bulkEntities.OfType<BulkCampaignRadiusTarget>().ToList();
                OutputBulkCampaignRadiusTargets(campaignRadiusTargetResults);

                Reader.Dispose();

                #endregion Add

                #region Update

                // Update the day and time target. 
                // Do not create a BulkAdGroupDayTimeTarget for update, unless you want to replace all existing DayTime target bids
                // with the specified day and time target set for the current bulk upload. 
                // Instead you should upload one or more bids as a list of BulkCampaignDayTimeTargetBid.

                var bulkCampaignDayTimeTargetBids = new List<BulkCampaignDayTimeTargetBid>
                {
                    new BulkCampaignDayTimeTargetBid
                    {
                        CampaignId = campaignDayTimeTargetResults[0].CampaignId,
                        TargetId = targetIdKey,
                        DayTimeTargetBid = new DayTimeTargetBid
                        {
                            BidAdjustment = 15,
                            Day = Day.Friday,
                            FromHour = 11,
                            FromMinute = Minute.Zero,
                            ToHour = 13,
                            ToMinute = Minute.Fifteen
                        }
                    }
                };

                // Write the updated target to the file

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                foreach (var bulkCampaignDayTimeTargetBid in bulkCampaignDayTimeTargetBids)
                {
                    Writer.WriteEntity(bulkCampaignDayTimeTargetBid);
                }

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Updated Entities\n");


                // Write any upload errors

                var campaignDayTimeTargetBidResults =
                    Reader.ReadEntities().OfType<BulkCampaignDayTimeTargetBid>().ToList();
                OutputBulkCampaignDayTimeTargetBids(campaignDayTimeTargetBidResults);

                Reader.Dispose();

                #endregion Update

                #region Delete

                // Prepare the bulk entities that you want to delete. You must set the Id field to the corresponding 
                // entity identifier, and the Status field to Deleted. 

                var campaignId = campaignResults[0].Campaign.Id;
                bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id = campaignId,
                        Status = CampaignStatus.Deleted
                    }
                };

                var targetId = campaignDayTimeTargetResults[0].TargetId;

                bulkCampaignDayTimeTarget = new BulkCampaignDayTimeTarget
                {
                    Status = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId = targetId
                };

                bulkCampaignLocationTarget = new BulkCampaignLocationTarget
                {
                    Status = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId = targetId
                };

                bulkCampaignRadiusTarget = new BulkCampaignRadiusTarget
                {
                    Status = Status.Deleted,
                    CampaignId = campaignId,
                    TargetId = targetId
                };
                

                // Write the entities that you want deleted, to the specified file.

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                Writer.WriteEntity(bulkCampaign);

                Writer.WriteEntity(bulkCampaignDayTimeTarget);
                Writer.WriteEntity(bulkCampaignLocationTarget);
                Writer.WriteEntity(bulkCampaignRadiusTarget);

                Writer.Dispose();

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

                // UploadFileAsync will upload the file you finished writing and will download the results file

                OutputStatusMessage("Starting UploadFileAsync . . .\n");
                bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType);
                OutputStatusMessage("Upload Results Bulk File Path" + Reader.BulkFilePath + "\n");
                OutputStatusMessage("Deleted Entities\n");

                // Write the upload output

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

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

                campaignDayTimeTargetResults = bulkEntities.OfType<BulkCampaignDayTimeTarget>().ToList();
                OutputBulkCampaignDayTimeTargets(campaignDayTimeTargetResults);

                campaignLocationTargetResults = bulkEntities.OfType<BulkCampaignLocationTarget>().ToList();
                OutputBulkCampaignLocationTargets(campaignLocationTargetResults);

                campaignRadiusTargetResults = bulkEntities.OfType<BulkCampaignRadiusTarget>().ToList();
                OutputBulkCampaignRadiusTargets(campaignRadiusTargetResults);

                Reader.Dispose();

                #endregion Delete
            }
            // 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.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.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(); }
            }
        }