Tutorial: Aplicación de escritorio de la API de Bing Ads en C#
En este ejemplo, la aplicación de consola de C# solicita el consentimiento del usuario a través de las credenciales que proporcione y, a continuación, obtiene las cuentas a las que el usuario autenticado puede acceder.
Primero debe registrar una aplicación y tomar nota del identificador de cliente (id. de aplicación registrado). Para obtener más información sobre cómo registrar una aplicación y el flujo de concesión de código de autorización, consulte Autenticación con OAuth.
También necesitará el token de desarrollador de producción. Puede crear el ejemplo paso a paso como se describe a continuación o descargar más ejemplos de GitHub.
Tutorial de código
Abra el entorno de desarrollo de Visual Studio .
Creación de un nuevo proyecto a través de Archivo ->Nuevo ->Proyecto
En la ventana Nuevo proyecto, elija .NET Framework 4.8 en la lista desplegable y, a continuación, haga clic en la plantilla Aplicación de consola (.NET Framework). Asigne al proyecto el nombre BingAdsConsoleApp y haga clic en Aceptar.
Instale el SDK a través de NuGet para BingAdsConsoleApp. Para obtener más información sobre las dependencias, consulte Instalación del SDK. Haga clic en Herramientas ->Administrador de paquetes NuGet ->Consola del Administrador de paquetes. En el símbolo del sistema, escriba estos comandos para instalar los paquetes de uno en uno:
Install-Package Microsoft.BingAds.SDK
yInstall-Package System.Configuration.ConfigurationManager
.Abra el archivo App.config y reemplace su contenido por el siguiente bloque de código. Edite BingAdsEnvironment para pasar del espacio aislado a la producción. Si tiene como destino el entorno de producción, debe reemplazar 4c0b021c-00c3-4508-838f-d3127e8167ff por el identificador de aplicación que se aprovisionó al registrar la aplicación de producción y reemplazar BBD37VB98 por el token de desarrollador de producción.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="BingAdsConsoleApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" /> </startup> <appSettings> <!-- To use the production environment, set this value to "Production". --> <add key="BingAdsEnvironment" value="Sandbox"/> <add key="ClientSettingsProvider.ServiceUri" value=""/> </appSettings> <userSettings> <BingAdsConsoleApp.Properties.Settings> <setting name="DeveloperToken" serializeAs="String"> <value>BBD37VB98</value> </setting> <setting name="ClientId" serializeAs="String"> <value>4c0b021c-00c3-4508-838f-d3127e8167ff</value> </setting> </BingAdsConsoleApp.Properties.Settings> </userSettings> </configuration>
Cree un archivo de configuración. En la vista de proyecto de BingAdsConsoleApp, haga clic con el botón derecho en Propiedades y haga clic en Abrir. Haga clic en Configuración y, a continuación, haga clic en el texto El proyecto no contiene un archivo de configuración predeterminado. Haga clic aquí para crear uno. Se agregarán automáticamente nuevos valores de app.config.
Abra el archivo Program.cs y reemplace su contenido por el siguiente bloque de código.
using System; using System.Linq; using System.Configuration; using System.Net.Http; using System.ServiceModel; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.BingAds; using Microsoft.BingAds.V13.CustomerManagement; using BingAdsConsoleApp.Properties; using System.IO; namespace BingAdsConsoleApp { class Program { private static AuthorizationData _authorizationData; private static ServiceClient<ICustomerManagementService> _customerManagementService; private static string ClientState = "ClientStateGoesHere"; static void Main(string[] args) { try { Authentication authentication = AuthenticateWithOAuth(); // Most Bing Ads API service operations require account and customer ID. // This utiltiy operation sets the global authorization data instance // to the first account that the current authenticated user can access. SetAuthorizationDataAsync(authentication).Wait(); // You can extend the console app with the examples library at: // https://github.com/BingAds/BingAds-dotNet-SDK/tree/main/examples/BingAdsExamples } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("OAuthTokenRequestException Message:\n{0}", ex.Message)); if (ex.Details != null) { OutputStatusMessage(string.Format("OAuthTokenRequestException Details:\nError: {0}\nDescription: {1}", ex.Details.Error, ex.Details.Description)); } } // Catch Customer Management service exceptions catch (FaultException<AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => { if ((error.Code == 105) || (error.Code == 106)) { return "Authorization data is missing or incomplete for the specified environment.\n" + "To run the examples switch users or contact support for help with the following error.\n"; } return string.Format("{0}: {1}", error.Code, error.Message); }))); OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.ApiFault> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (HttpRequestException ex) { OutputStatusMessage(ex.Message); } } /// <summary> /// Utility method for setting the customer and account identifiers within the global /// <see cref="_authorizationData"/> instance. /// </summary> /// <param name="authentication">The OAuth authentication credentials.</param> /// <returns></returns> private static async Task SetAuthorizationDataAsync(Authentication authentication) { _authorizationData = new AuthorizationData { Authentication = authentication, DeveloperToken = Settings.Default["DeveloperToken"].ToString() }; var apiEnvironment = ConfigurationManager.AppSettings["BingAdsEnvironment"] == ApiEnvironment.Sandbox.ToString() ? ApiEnvironment.Sandbox : ApiEnvironment.Production; _customerManagementService = new ServiceClient<ICustomerManagementService>( _authorizationData, apiEnvironment ); var getUserRequest = new GetUserRequest { UserId = null }; var getUserResponse = (await _customerManagementService.CallAsync((s, r) => s.GetUserAsync(r), getUserRequest)); var user = getUserResponse.User; var predicate = new Predicate { Field = "UserId", Operator = PredicateOperator.Equals, Value = user.Id.ToString() }; var paging = new Paging { Index = 0, Size = 10 }; var searchAccountsRequest = new SearchAccountsRequest { Ordering = null, PageInfo = paging, Predicates = new[] { predicate } }; var searchAccountsResponse = (await _customerManagementService.CallAsync((s, r) => s.SearchAccountsAsync(r), searchAccountsRequest)); var accounts = searchAccountsResponse.Accounts.ToArray(); if (accounts.Length <= 0) return; _authorizationData.AccountId = (long)accounts[0].Id; _authorizationData.CustomerId = (int)accounts[0].ParentCustomerId; OutputArrayOfAdvertiserAccount(accounts); return; } /// <summary> /// Authenticates the current user via OAuth. /// </summary> /// <returns>The OAuth authentication instance for a user.</returns> private static Authentication AuthenticateWithOAuth() { var apiEnvironment = ConfigurationManager.AppSettings["BingAdsEnvironment"] == ApiEnvironment.Sandbox.ToString() ? ApiEnvironment.Sandbox : ApiEnvironment.Production; var oAuthDesktopMobileAuthCodeGrant = new OAuthDesktopMobileAuthCodeGrant( Settings.Default["ClientId"].ToString(), apiEnvironment ); // It is recommended that you specify a non guessable 'state' request parameter to help prevent // cross site request forgery (CSRF). oAuthDesktopMobileAuthCodeGrant.State = ClientState; string refreshToken; // If you have previously securely stored a refresh token, try to use it. if (GetRefreshToken(out refreshToken)) { AuthorizeWithRefreshTokenAsync(oAuthDesktopMobileAuthCodeGrant, refreshToken).Wait(); } else { // You must request user consent at least once through a web browser control. Console.WriteLine(string.Format( "Open a new web browser and navigate to {0}\n\n" + "Grant consent in the web browser for the application to access " + "your advertising accounts, and then enter the response URI that includes " + "the authorization 'code' parameter: \n", oAuthDesktopMobileAuthCodeGrant.GetAuthorizationEndpoint()) ); // Request access and refresh tokens using the URI that you provided manually during program execution. var responseUri = new Uri(Console.ReadLine()); if (oAuthDesktopMobileAuthCodeGrant.State != ClientState) throw new HttpRequestException("The OAuth response state does not match the client request state."); oAuthDesktopMobileAuthCodeGrant.RequestAccessAndRefreshTokensAsync(responseUri).Wait(); SaveRefreshToken(oAuthDesktopMobileAuthCodeGrant.OAuthTokens.RefreshToken); } // It is important to save the most recent refresh token whenever new OAuth tokens are received. // You will want to subscribe to the NewOAuthTokensReceived event handler. // When calling Bing Ads API service operations with ServiceClient<TService>, BulkServiceManager, or ReportingServiceManager, // each instance will refresh your access token automatically if they detect the AuthenticationTokenExpired (109) error code. oAuthDesktopMobileAuthCodeGrant.NewOAuthTokensReceived += (sender, tokens) => SaveRefreshToken(tokens.NewRefreshToken); return oAuthDesktopMobileAuthCodeGrant; } /// <summary> /// Requests new access and refresh tokens given an existing refresh token. /// </summary> /// <param name="authentication">The OAuth authentication instance for a user.</param> /// <param name="refreshToken">The previous refresh token.</param> /// <returns></returns> private static Task<OAuthTokens> AuthorizeWithRefreshTokenAsync( OAuthDesktopMobileAuthCodeGrant authentication, string refreshToken) { return authentication.RequestAccessAndRefreshTokensAsync(refreshToken); } /// <summary> /// You should modify the example, and store the refresh token securely. /// </summary> /// <param name="newRefreshtoken">The refresh token to save.</param> private static void SaveRefreshToken(string newRefreshtoken) { if (newRefreshtoken != null) { using (StreamWriter outputFile = new StreamWriter( Environment.CurrentDirectory + @"\refreshtoken.txt", false)) { outputFile.WriteLine(newRefreshtoken); } } } /// <summary> /// Returns the prior refresh token if available. /// </summary> /// <param name="refreshToken"></param> /// <returns>The latest stored refresh token.</returns> private static bool GetRefreshToken(out string refreshToken) { var filePath = Environment.CurrentDirectory + @"\refreshtoken.txt"; if (!File.Exists(filePath)) { refreshToken = null; return false; } String fileContents; using (StreamReader sr = new StreamReader(filePath)) { fileContents = sr.ReadToEnd(); } if (string.IsNullOrEmpty(fileContents)) { refreshToken = null; return false; } try { refreshToken = fileContents; return true; } catch (FormatException) { refreshToken = null; return false; } } #region OutputHelpers /** * You can extend the console app with the example helpers at: * https://github.com/BingAds/BingAds-dotNet-SDK/tree/main/examples/BingAdsExamples **/ private static void OutputArrayOfAdvertiserAccount(IList<AdvertiserAccount> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputAdvertiserAccount(dataObject); OutputStatusMessage("\n"); } } } private static void OutputAdvertiserAccount(AdvertiserAccount dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("BillToCustomerId: {0}", dataObject.BillToCustomerId)); OutputStatusMessage(string.Format("CurrencyCode: {0}", dataObject.CurrencyCode)); OutputStatusMessage(string.Format("AccountFinancialStatus: {0}", dataObject.AccountFinancialStatus)); OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Language: {0}", dataObject.Language)); OutputStatusMessage(string.Format("LastModifiedByUserId: {0}", dataObject.LastModifiedByUserId)); OutputStatusMessage(string.Format("LastModifiedTime: {0}", dataObject.LastModifiedTime)); OutputStatusMessage(string.Format("Name: {0}", dataObject.Name)); OutputStatusMessage(string.Format("Number: {0}", dataObject.Number)); OutputStatusMessage(string.Format("ParentCustomerId: {0}", dataObject.ParentCustomerId)); OutputStatusMessage(string.Format("PaymentMethodId: {0}", dataObject.PaymentMethodId)); OutputStatusMessage(string.Format("PaymentMethodType: {0}", dataObject.PaymentMethodType)); OutputStatusMessage(string.Format("PrimaryUserId: {0}", dataObject.PrimaryUserId)); OutputStatusMessage(string.Format("AccountLifeCycleStatus: {0}", dataObject.AccountLifeCycleStatus)); OutputStatusMessage(string.Format("TimeStamp: {0}", dataObject.TimeStamp)); OutputStatusMessage(string.Format("TimeZone: {0}", dataObject.TimeZone)); OutputStatusMessage(string.Format("PauseReason: {0}", dataObject.PauseReason)); OutputArrayOfKeyValuePairOfstringstring(dataObject.ForwardCompatibilityMap); OutputArrayOfCustomerInfo(dataObject.LinkedAgencies); OutputStatusMessage(string.Format("SalesHouseCustomerId: {0}", dataObject.SalesHouseCustomerId)); OutputArrayOfKeyValuePairOfstringstring(dataObject.TaxInformation); OutputStatusMessage(string.Format("BackUpPaymentInstrumentId: {0}", dataObject.BackUpPaymentInstrumentId)); OutputStatusMessage(string.Format("BillingThresholdAmount: {0}", dataObject.BillingThresholdAmount)); OutputAddress(dataObject.BusinessAddress); OutputStatusMessage(string.Format("AutoTagType: {0}", dataObject.AutoTagType)); OutputStatusMessage(string.Format("SoldToPaymentInstrumentId: {0}", dataObject.SoldToPaymentInstrumentId)); } } private static void OutputAddress(Address dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("City: {0}", dataObject.City)); OutputStatusMessage(string.Format("CountryCode: {0}", dataObject.CountryCode)); OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Line1: {0}", dataObject.Line1)); OutputStatusMessage(string.Format("Line2: {0}", dataObject.Line2)); OutputStatusMessage(string.Format("Line3: {0}", dataObject.Line3)); OutputStatusMessage(string.Format("Line4: {0}", dataObject.Line4)); OutputStatusMessage(string.Format("PostalCode: {0}", dataObject.PostalCode)); OutputStatusMessage(string.Format("StateOrProvince: {0}", dataObject.StateOrProvince)); OutputStatusMessage(string.Format("TimeStamp: {0}", dataObject.TimeStamp)); OutputStatusMessage(string.Format("BusinessName: {0}", dataObject.BusinessName)); } } private static void OutputArrayOfKeyValuePairOfstringstring(IList<KeyValuePair<string, string>> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputKeyValuePairOfstringstring(dataObject); } } } private static void OutputKeyValuePairOfstringstring(KeyValuePair<string, string> dataObject) { if (null != dataObject.Key) { OutputStatusMessage(string.Format("key: {0}", dataObject.Key)); OutputStatusMessage(string.Format("value: {0}", dataObject.Value)); } } private static void OutputCustomerInfo(CustomerInfo dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Name: {0}", dataObject.Name)); } } private static void OutputArrayOfCustomerInfo(IList<CustomerInfo> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputCustomerInfo(dataObject); OutputStatusMessage("\n"); } } } private static void OutputStatusMessage(String msg) { Console.WriteLine(msg); } #endregion OutputHelpers } }
Haga clic en Build ->Build BingAdsConsoleApp y, a continuación, ejecute la aplicación. Al iniciar la aplicación, se le pedirán de forma predeterminada las credenciales de la cuenta microsoft para autenticarse en producción.
Configuración del espacio aislado
Para usar el espacio aislado, establezca la clave BingAdsEnvironment en Espacio aislado dentro del <nodo appSettings> del archivo deApp.config raíz del proyecto.
<add key="BingAdsEnvironment" value ="Sandbox"/>
También puede establecer el entorno para cada ServiceClient individualmente de la siguiente manera.
_customerManagementService = new ServiceClient<ICustomerManagementService>(
_authorizationData,
ApiEnvironment.Sandbox
);
Tanto si establece el entorno ServiceClient globalmente como individualmente, por separado también tendrá que establecer el entorno de OAuth en espacio aislado.
var oAuthDesktopMobileAuthCodeGrant = new OAuthDesktopMobileAuthCodeGrant(
ClientId,
ApiEnvironment.Sandbox
);
Consulta también
Espacio aislado
Ejemplos de código de api de Bing Ads
Direcciones del servicio web de la API de Bing Ads