Exemple #1
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                // Add an image to your media library.
                // The image asset is needed later to create the responsive ad.

                var landscapeImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + ResponsiveAdMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var media = new Media[]
                {
                    landscapeImageMedia,
                };

                OutputStatusMessage("-----\nAddMedia:");
                AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
                    accountId : authorizationData.AccountId,
                    media : media);

                long[] mediaIds = addMediaResponse.MediaIds.ToArray();
                OutputStatusMessage("MediaIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);

                // Create an Audience campaign with one ad group and a responsive ad.

                var campaigns = new[] {
                    new Campaign
                    {
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        // CampaignType must be set for Audience campaigns
                        CampaignType = CampaignType.Audience,
                        DailyBudget  = 50,
                        Description  = "Red shoes line.",
                        // Languages must be set for Audience campaigns
                        Languages = new string[] { "All" },
                        Name      = "Women's Shoes " + DateTime.UtcNow,
                        TimeZone  = "PacificTimeUSCanadaTijuana",
                    },
                };

                OutputStatusMessage("-----\nAddCampaigns:");
                AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(
                    accountId : authorizationData.AccountId,
                    campaigns : campaigns,
                    includeDynamicSearchAdsSource : false);

                long?[]      campaignIds    = addCampaignsResponse.CampaignIds.ToArray();
                BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray();
                OutputStatusMessage("CampaignIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors);

                // Add an ad group within the campaign.

                var adGroups = new[] {
                    new AdGroup
                    {
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Date {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                        // Network cannot be set for ad groups in Audience campaigns
                        Network = null,
                    }
                };

                OutputStatusMessage("-----\nAddAdGroups:");
                AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync(
                    campaignId : (long)campaignIds[0],
                    adGroups : adGroups,
                    returnInheritedBidStrategyTypes : false);

                long?[]      adGroupIds    = addAdGroupsResponse.AdGroupIds.ToArray();
                BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray();
                OutputStatusMessage("AdGroupIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors);

                // Add a responsive ad within the ad group.

                var ads = new Ad[] {
                    new ResponsiveAd
                    {
                        BusinessName = "Contoso",
                        CallToAction = CallToAction.AddToCart,
                        FinalUrls    = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                        Headline = "Fast & Easy Setup",
                        Images   = new []
                        {
                            // You are only required to provide a landscape image asset.
                            // Optionally you can include additional asset links, i.e., one image asset for each supported sub type.
                            // For any image asset sub types that you do not explicitly set,
                            // the service will automatically create image asset links by cropping the LandscapeImageMedia.
                            new AssetLink
                            {
                                Asset = new ImageAsset
                                {
                                    CropHeight = null,
                                    CropWidth  = null,
                                    CropX      = null,
                                    CropY      = null,
                                    Id         = mediaIds[0],
                                    Name       = "My LandscapeImageMedia",
                                    SubType    = "LandscapeImageMedia",
                                },
                            },
                        },
                        LongHeadline = "Find New Customers & Increase Sales!",
                        Text         = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                    },
                };

                OutputStatusMessage("-----\nAddAds:");
                AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync(
                    adGroupId : (long)adGroupIds[0],
                    ads : ads);

                long?[]      adIds    = addAdsResponse.AdIds.ToArray();
                BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray();
                OutputStatusMessage("AdIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors);

                // Delete the account's media.

                OutputStatusMessage("-----\nDeleteMedia:");
                await CampaignManagementExampleHelper.DeleteMediaAsync(
                    accountId : authorizationData.AccountId,
                    mediaIds : mediaIds);

                foreach (var id in mediaIds)
                {
                    OutputStatusMessage(string.Format("Deleted Media Id {0}", id));
                }

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

                OutputStatusMessage("-----\nDeleteCampaigns:");
                await CampaignManagementExampleHelper.DeleteCampaignsAsync(
                    accountId : authorizationData.AccountId,
                    campaignIds : new[] { (long)campaignIds[0] });

                OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0]));
            }
            // 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 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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper =
                    new CampaignManagementExampleHelper(this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService =
                    new ServiceClient <ICampaignManagementService>(authorizationData, environment);

                #region MediaRepresentations

                var landscapeImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + LandscapeImageMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var landscapeLogoMedia = GetImageMedia(
                    "Image4x1",
                    MediaFilePath + LandscapeLogoMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var squareImageMedia = GetImageMedia(
                    "Image1x1",
                    MediaFilePath + SquareImageMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var squareLogoMedia = GetImageMedia(
                    "Image1x1",
                    MediaFilePath + SquareLogoMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var imageAdExtensionMedia = GetImageMedia(
                    "Image15x10",
                    MediaFilePath + ImageAdExtensionMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var addMedia = new Media[]
                {
                    landscapeImageMedia,
                    landscapeLogoMedia,
                    squareImageMedia,
                    squareLogoMedia,
                    imageAdExtensionMedia
                };
                CampaignManagementExampleHelper.OutputArrayOfMedia(addMedia);

                var imageMediaIds = (await CampaignManagementExampleHelper.AddMediaAsync(
                                         authorizationData.AccountId,
                                         addMedia)).MediaIds;

                // The index of returned IDs is consistent with the order you submitted them in the request;
                // however, the sequence of the IDs themselves is not guaranteed. For example you might observe:
                // - Landscape Image Media Id == imageMediaIds[0] == 1
                // - Landscape Logo Media Id == imageMediaIds[1] == 4
                // - Square Image Media Id == imageMediaIds[2] == 3
                // - Square Logo Media Id == imageMediaIds[3] == 2
                // - Image Ad Extension Media Id == imageMediaIds[4] == 0

                // You can use the first four Media Ids when you add or update a Responsive Ad
                // in an Audience campaign e.g., see AudienceCampaigns.cs.

                var adMediaIds = new List <long> {
                    imageMediaIds[0], imageMediaIds[1], imageMediaIds[2], imageMediaIds[3]
                };
                OutputStatusMessage("Media Ids for Responsive Ad:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adMediaIds);

                // You can use the fifth Media Id when you add or update an Image Ad Extension
                // in a Search campaign e.g., see AdExtensions.cs.

                var extensionMediaIds = new List <long> {
                    imageMediaIds[4]
                };
                OutputStatusMessage("Media Ids for Image Ad Extension:");
                CampaignManagementExampleHelper.OutputArrayOfLong(extensionMediaIds);

                // Get the media representations to confirm the stored dimensions
                // and get the Url where you can later view or download the media.

                var getResponsiveAdMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                        MediaEnabledEntityFilter.ResponsiveAd)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getResponsiveAdMediaMetaData);

                var getImageAdExtensionMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                            MediaEnabledEntityFilter.ImageAdExtension)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getImageAdExtensionMediaMetaData);

                var getMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByIdsAsync(imageMediaIds)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getMediaMetaData);

                #endregion MediaRepresentations

                #region Delete

                // Comment out (disable) the delete operation if you want to use the media IDs
                // in another example e.g., AudienceCampaigns.cs.

                var deleteMediaResponse = (await CampaignManagementExampleHelper.DeleteMediaAsync(
                                               authorizationData.AccountId,
                                               imageMediaIds));

                foreach (var id in imageMediaIds)
                {
                    OutputStatusMessage(string.Format("Deleted Media Id {0}\n", id));
                }

                #endregion Delete
            }
            // 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 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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
Exemple #3
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                // Add a campaign to associate with ad extensions.

                var campaigns = new[] {
                    new Campaign
                    {
                        BudgetType  = BudgetLimitType.DailyBudgetStandard,
                        DailyBudget = 50,
                        Description = "Red shoes line.",
                        Languages   = new string[] { "All" },
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        TimeZone    = "PacificTimeUSCanadaTijuana",
                    }
                };

                OutputStatusMessage("-----\nAddCampaigns:");
                AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(
                    accountId : authorizationData.AccountId,
                    campaigns : campaigns,
                    includeDynamicSearchAdsSource : false);

                long?[]      campaignIds    = addCampaignsResponse.CampaignIds.ToArray();
                BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray();
                OutputStatusMessage("CampaignIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors);

                // Create media for the image ad extension that we'll add later.

                var imageAdExtensionMedia = GetImageMedia(
                    "Image15x10",
                    MediaFilePath + ImageAdExtensionMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var media = new Media[]
                {
                    imageAdExtensionMedia
                };

                // Add the media to the account's library.

                OutputStatusMessage("-----\nAddMedia:");
                AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
                    accountId : authorizationData.AccountId,
                    media : media);

                long[] mediaIds = addMediaResponse.MediaIds.ToArray();
                OutputStatusMessage("MediaIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);

                // Add the extensions to the account's library.

                var adExtensions = new AdExtension[] {
                    new ActionAdExtension
                    {
                        ActionType = ActionAdExtensionActionType.ActNow,
                        FinalUrls  = new string[]
                        {
                            "http://www.contoso.com/womenshoesale"
                        },
                        Language = "English",
                        Status   = AdExtensionStatus.Active,
                    },
                    //new AppAdExtension
                    //{
                    //    AppPlatform = "Windows",
                    //    AppStoreId = "AppStoreIdGoesHere",
                    //    DestinationUrl = "DestinationUrlGoesHere",
                    //    DisplayText = "Contoso",
                    //},
                    new CallAdExtension {
                        CountryCode = "US",
                        PhoneNumber = "2065550100",
                        IsCallOnly  = false,
                        // Include the call extension Monday - Friday from 9am - 9pm
                        // in the account's time zone.
                        Scheduling = new Schedule {
                            UseSearcherTimeZone = false,
                            DayTimeRanges       = new[]
                            {
                                new DayTime
                                {
                                    Day         = Day.Monday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Tuesday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Wednesday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Thursday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Friday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                            },
                            StartDate = null,
                            EndDate   = new Microsoft.BingAds.V12.CampaignManagement.Date {
                                Month = 12,
                                Day   = 31,
                                Year  = DateTime.UtcNow.Year + 1
                            },
                        }
                    },
                    new CalloutAdExtension
                    {
                        Text = "Callout Text"
                    },
                    new ImageAdExtension
                    {
                        AlternativeText = "Image Extension Alt Text",
                        ImageMediaIds   = mediaIds
                    },
                    new LocationAdExtension {
                        PhoneNumber = "206-555-0100",
                        CompanyName = "Contoso Shoes",
                        Address     = new Microsoft.BingAds.V12.CampaignManagement.Address {
                            StreetAddress  = "1234 Washington Place",
                            StreetAddress2 = "Suite 1210",
                            CityName       = "Woodinville",
                            ProvinceName   = "WA",
                            CountryCode    = "US",
                            PostalCode     = "98608"
                        },
                        // Include the location extension every Saturday morning
                        // in the search user's time zone.
                        Scheduling = new Schedule {
                            UseSearcherTimeZone = true,
                            DayTimeRanges       = new[]
                            {
                                new DayTime
                                {
                                    Day         = Day.Saturday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 12,
                                    EndMinute   = Minute.Zero,
                                },
                            },
                            StartDate = null,
                            EndDate   = new Microsoft.BingAds.V12.CampaignManagement.Date {
                                Month = 12,
                                Day   = 31,
                                Year  = DateTime.UtcNow.Year + 1
                            },
                        }
                    },
                    new PriceAdExtension
                    {
                        Language           = "English",
                        PriceExtensionType = PriceExtensionType.Events,
                        TableRows          = new PriceTableRow[]
                        {
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "New Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the next event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "Next Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the final event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "Final Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                        },
                    },
                    new ReviewAdExtension
                    {
                        IsExact = true,
                        Source  = "Review Source Name",
                        Text    = "Review Text",
                        // The Url of the third-party review. This is not your business Url.
                        Url = "http://review.contoso.com"
                    },
                    new SitelinkAdExtension {
                        Description1 = "Simple & Transparent.",
                        Description2 = "No Upfront Cost.",
                        DisplayText  = "Women's Shoe Sale",
                        FinalUrls    = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                    },
                    new StructuredSnippetAdExtension
                    {
                        Header = "Brands",
                        Values = new [] { "Windows", "Xbox", "Skype" }
                    }
                };

                OutputStatusMessage("-----\nAddAdExtensions:");
                var addAdExtensionsResponse = await CampaignManagementExampleHelper.AddAdExtensionsAsync(
                    accountId : authorizationData.AccountId,
                    adExtensions : adExtensions);

                OutputStatusMessage("AdExtensionIdentities:");
                var adExtensionIdentities = addAdExtensionsResponse?.AdExtensionIdentities;
                OutputStatusMessage("NestedPartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addAdExtensionsResponse?.NestedPartialErrors);

                // DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons
                // operations each require a list of type AdExtensionIdToEntityIdAssociation.
                var adExtensionIdToEntityIdAssociations = new List <AdExtensionIdToEntityIdAssociation>();

                // GetAdExtensionsByIds requires a list of type long.
                var adExtensionIds = new List <long>();

                // Loop through the list of extension IDs and build any required data structures
                // for subsequent operations.

                foreach (var adExtensionIdentity in adExtensionIdentities)
                {
                    if (adExtensionIdentity != null)
                    {
                        adExtensionIdToEntityIdAssociations.Add(new AdExtensionIdToEntityIdAssociation
                        {
                            AdExtensionId = adExtensionIdentity.Id,
                            EntityId      = (long)campaignIds[0]
                        });

                        adExtensionIds.Add(adExtensionIdentity.Id);
                    }
                }

                // Associate the ad extensions with the campaign.

                OutputStatusMessage("-----\nSetAdExtensionsAssociations:");
                var setAdExtensionsAssociationsResponse = await CampaignManagementExampleHelper.SetAdExtensionsAssociationsAsync(
                    accountId : authorizationData.AccountId,
                    adExtensionIdToEntityIdAssociations : adExtensionIdToEntityIdAssociations,
                    associationType : AssociationType.Campaign);

                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(setAdExtensionsAssociationsResponse?.PartialErrors);

                // Get editorial rejection reasons for the ad extension and entity associations.

                OutputStatusMessage("-----\nGetAdExtensionsEditorialReasons:");
                var getAdExtensionsEditorialReasonsResponse = await CampaignManagementExampleHelper.GetAdExtensionsEditorialReasonsAsync(
                    accountId : authorizationData.AccountId,
                    adExtensionIdToEntityIdAssociations : adExtensionIdToEntityIdAssociations,
                    associationType : AssociationType.Campaign);

                OutputStatusMessage("EditorialReasons:");
                var adExtensionEditorialReasonCollection =
                    (AdExtensionEditorialReasonCollection[])getAdExtensionsEditorialReasonsResponse?.EditorialReasons;
                CampaignManagementExampleHelper.OutputArrayOfAdExtensionEditorialReasonCollection(adExtensionEditorialReasonCollection);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsEditorialReasonsResponse?.PartialErrors);

                // Get only the location ad extensions and then remove scheduling.

                AdExtensionsTypeFilter adExtensionsTypeFilter = AdExtensionsTypeFilter.LocationAdExtension;

                // In this example partial errors will be returned for indices where the ad extensions
                // are not location ad extensions.
                // This is an example, and ideally you would only send the required ad extension IDs.

                OutputStatusMessage("-----\nGetAdExtensionsByIds:");
                var getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
                                                        accountId: authorizationData.AccountId,
                                                        adExtensionIds: adExtensionIds,
                                                        adExtensionType: adExtensionsTypeFilter));
                adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
                BatchError[] getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray();
                OutputStatusMessage("AdExtensions:");
                CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors);

                var updateExtensions   = new List <AdExtension>();
                var updateExtensionIds = new List <long>();

                foreach (var extension in adExtensions)
                {
                    // GetAdExtensionsByIds will return a nil element if the request conditions were not met.
                    if (extension != null && extension.Id != null)
                    {
                        // Remove read-only elements that would otherwise cause the update operation to fail.
                        var updateExtension = SetReadOnlyAdExtensionElementsToNull(extension);

                        // If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged.
                        // If you set this to any non-null Schedule object, you are effectively replacing existing scheduling
                        // for the ad extension. In this example, we will remove any existing scheduling by setting this element
                        // to an empty Schedule object.
                        updateExtension.Scheduling = new Schedule {
                        };
                        updateExtensions.Add(updateExtension);
                        updateExtensionIds.Add((long)updateExtension.Id);
                    }
                }

                OutputStatusMessage("-----\nUpdateAdExtensions:");
                await CampaignManagementExampleHelper.UpdateAdExtensionsAsync(
                    accountId : authorizationData.AccountId,
                    adExtensions : updateExtensions);

                OutputStatusMessage("Removed scheduling from the location ad extensions.");

                // Get only the location extensions to output the result.

                OutputStatusMessage("-----\nGetAdExtensionsByIds:");
                getAdExtensionsByIdsResponse = await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
                    accountId : authorizationData.AccountId,
                    adExtensionIds : updateExtensionIds,
                    adExtensionType : adExtensionsTypeFilter);

                adExtensions         = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
                getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray();
                OutputStatusMessage("AdExtensions:");
                CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors);

                // Delete the ad extension associations, ad extensions, and campaign, that were previously added.
                // At this point the ad extensions are still available in the account's ad extensions library.

                OutputStatusMessage("-----\nDeleteAdExtensionsAssociations:");
                await CampaignManagementExampleHelper.DeleteAdExtensionsAssociationsAsync(
                    authorizationData.AccountId,
                    adExtensionIdToEntityIdAssociations,
                    AssociationType.Campaign);

                OutputStatusMessage("Deleted ad extension associations.");

                // Delete the ad extensions from the account's ad extension library.

                OutputStatusMessage("-----\nDeleteAdExtensions:");
                await CampaignManagementExampleHelper.DeleteAdExtensionsAsync(
                    authorizationData.AccountId,
                    adExtensionIds);

                OutputStatusMessage("Deleted ad extensions.");

                // Delete the account's media that was used for the image ad extension.

                OutputStatusMessage("-----\nDeleteMedia:");
                await CampaignManagementExampleHelper.DeleteMediaAsync(
                    accountId : authorizationData.AccountId,
                    mediaIds : mediaIds);

                foreach (var id in mediaIds)
                {
                    OutputStatusMessage(string.Format("Deleted Media Id {0}", id));
                }

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

                OutputStatusMessage("-----\nDeleteCampaigns:");
                await CampaignManagementExampleHelper.DeleteCampaignsAsync(
                    accountId : authorizationData.AccountId,
                    campaignIds : new[] { (long)campaignIds[0] });

                OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0]));
            }
            // 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 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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 Customer Management service exceptions
            catch (FaultException <Microsoft.BingAds.V12.CustomerManagement.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.CustomerManagement.ApiFault> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Media cannot be added via the Bulk service, so we'll use the Campaign Management service
                // i.e., the AddMedia service operation below.

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

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

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

                // Add an image to your media library.
                // The image asset is needed later to create the responsive ad.
                var landscapeImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + ResponsiveAdMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var media = new Media[]
                {
                    landscapeImageMedia,
                };

                OutputStatusMessage("-----\nAddMedia:");
                AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
                    accountId : authorizationData.AccountId,
                    media : media);

                long[] mediaIds = addMediaResponse.MediaIds.ToArray();
                OutputStatusMessage("MediaIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);

                var uploadEntities = new List <BulkEntity>();

                // Create an Audience campaign with one ad group and a responsive ad.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id = campaignIdKey,
                        // CampaignType must be set for Audience campaigns
                        CampaignType = CampaignType.Audience,
                        // Languages must be set for Audience campaigns
                        Languages   = new string[] { "All" },
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        DailyBudget = 50,
                        BudgetType  = BudgetLimitType.DailyBudgetStandard,
                        Settings    = null,
                        TimeZone    = "PacificTimeUSCanadaTijuana",
                    }
                };
                uploadEntities.Add(bulkCampaign);

                // Specify one or more ad groups.

                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
                        },
                        // Language cannot be set for ad groups in Audience campaigns
                        Language = null,
                        // Network cannot be set for ad groups in Audience campaigns
                        Network = null,
                    },
                };
                uploadEntities.Add(bulkAdGroup);

                var bulkResponsiveAd = new BulkResponsiveAd
                {
                    AdGroupId    = adGroupIdKey,
                    ResponsiveAd = new ResponsiveAd
                    {
                        Id           = responsiveAdIdKey,
                        BusinessName = "Contoso",
                        CallToAction = CallToAction.AddToCart,
                        FinalUrls    = new[] {
                            "https://www.contoso.com/womenshoesale"
                        },
                        ForwardCompatibilityMap = null,
                        Headline = "Fast & Easy Setup",
                        Images   = new[]
                        {
                            // You are only required to provide a landscape image asset.
                            // Optionally you can include additional asset links, i.e., one image asset for each supported sub type.
                            // For any image asset sub types that you do not explicitly set,
                            // the service will automatically create image asset links by cropping the LandscapeImageMedia.
                            new AssetLink
                            {
                                Asset = new ImageAsset
                                {
                                    CropHeight = null,
                                    CropWidth  = null,
                                    CropX      = null,
                                    CropY      = null,
                                    Id         = mediaIds[0],
                                    Name       = "My LandscapeImageMedia",
                                    SubType    = "LandscapeImageMedia",
                                    Type       = null
                                },
                            },
                        },
                        LongHeadlineString = "Find New Customers & Increase Sales!",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                    },
                };
                uploadEntities.Add(bulkResponsiveAd);

                // Upload and write the output

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

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

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

                OutputStatusMessage("Upload results:");

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

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

                var responsiveAdResults = downloadEntities.OfType <BulkResponsiveAd>().ToList();
                OutputBulkResponsiveAds(responsiveAdResults);

                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);
                }

                OutputStatusMessage("-----\nDeleting campaign, ad group, and ad...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

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

                OutputStatusMessage("Upload results:");

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

                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();
                }
            }
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                var responsiveAdImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + ResponsiveAdMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var imageAdExtensionMedia = GetImageMedia(
                    "Image15x10",
                    MediaFilePath + ImageAdExtensionMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var addMedia = new Media[]
                {
                    responsiveAdImageMedia,
                    imageAdExtensionMedia
                };
                OutputStatusMessage("Ready to upload image media:");
                CampaignManagementExampleHelper.OutputArrayOfMedia(addMedia);

                OutputStatusMessage("-----\nAddMedia:");
                AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
                    accountId : authorizationData.AccountId,
                    media : addMedia);

                long[] mediaIds = addMediaResponse.MediaIds.ToArray();
                OutputStatusMessage("MediaIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);

                // Get the media representations to confirm the stored dimensions
                // and get the Url where you can later view or download the media.

                OutputStatusMessage("-----\nGetMediaMetaDataByAccountId:");
                var getResponsiveAdMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                        mediaEnabledEntities: MediaEnabledEntityFilter.ResponsiveAd,
                                                        pageInfo: null)).MediaMetaData;
                OutputStatusMessage("MediaMetaData:");
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getResponsiveAdMediaMetaData);

                OutputStatusMessage("-----\nGetMediaMetaDataByAccountId:");
                var getImageAdExtensionMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                            mediaEnabledEntities: MediaEnabledEntityFilter.ImageAdExtension,
                                                            pageInfo: null)).MediaMetaData;
                OutputStatusMessage("MediaMetaData:");
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getImageAdExtensionMediaMetaData);

                OutputStatusMessage("-----\nGetMediaMetaDataByIds:");
                var getMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByIdsAsync(
                                            mediaIds: mediaIds)).MediaMetaData;
                OutputStatusMessage("MediaMetaData:");
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getMediaMetaData);

                // Delete the account's media.

                OutputStatusMessage("-----\nDeleteMedia:");
                await CampaignManagementExampleHelper.DeleteMediaAsync(
                    accountId : authorizationData.AccountId,
                    mediaIds : mediaIds);

                foreach (var id in mediaIds)
                {
                    OutputStatusMessage(string.Format("Deleted Media Id {0}", id));
                }
            }
            // 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 Campaign Management service exceptions
            catch (FaultException <AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <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 (FaultException <EditorialApiFaultDetail> 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 (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }