Procédure pas à pas : Application web API Bing Ads en C#

Cet exemple d’application web C# demande le consentement de l’utilisateur via les informations d’identification que vous fournissez, puis obtient les comptes auxquels l’utilisateur authentifié peut accéder.

Vous devez d’abord inscrire une application et prendre note de l’ID client (ID d’application inscrit), de la clé secrète client (mot de passe inscrit) et de l’URI de redirection. Pour plus d’informations sur l’inscription d’une application et le flux d’octroi du code d’autorisation, consultez Authentification avec OAuth.

Vous aurez également besoin de votre jeton de développeur de production. Vous pouvez créer l’exemple étape par étape comme décrit ci-dessous ou télécharger d’autres exemples à partir de GitHub.

Conseil

Cet exemple fait référence aux étapes de La création d’une application web ASP.NET Framework dans Azure. Pour plus d’informations sur le déploiement d’applications web sur Azure, consultez la documentation Azure.

Procédure pas à pas du code

  1. Ouvrez l’environnement de développement Visual Studio Community 2017. Si vous avez déjà installé Visual Studio, ajoutez les charges de travail ASP.NET et développement web et Développement Azure dans Visual Studio en cliquant sur Outils>Obtenir des outils et des fonctionnalités.

  2. Créez un projet en sélectionnant Fichier > Nouveau > projet. Dans la fenêtre Nouveau projet, choisissez .NET Framework 4.7.1 dans la liste déroulante, puis sélectionnez Application web ASP.NET Web > Visual C# > (.NET Framework). Nommez le projet BingAdsWebApp et cliquez sur OK.

  3. Vous pouvez déployer n’importe quel type d’application web ASP.NET sur Azure. Pour ce guide de démarrage rapide, sélectionnez le modèle MVC , vérifiez que l’authentification est définie sur Aucune authentification, puis cliquez sur OK.

  4. Installez le Kit de développement logiciel (SDK) via NuGet pour BingAdsWebApp. Pour plus d’informations sur les dépendances, consultez Installer le Kit de développement logiciel (SDK). Cliquez sur Outils ->Gestionnaire de package NuGet ->Console du Gestionnaire de package. À l’invite, tapez ces commandes pour installer les packages un par un : Install-Package Microsoft.BingAds.SDK, Install-Package System.ServiceModel.Primitives -Version 4.4.1, Install-Package System.ServiceModel.Http -Version 4.4.1et Install-Package System.Configuration.ConfigurationManager -Version 4.4.1.

  5. Ouvrez le fichier Web.config et remplacez son contenu par le bloc de code suivant. Modifiez BingAdsEnvironment pour passer du bac à sable à la production et définissez le jeton de développeur de production en fonction des besoins. Vous devez modifier les valeurs ClientId, ClientSecret et RedirectionUri avec les valeurs ID d’application, Secret de l’application et URL de redirection correspondantes qui ont été configurées lors de l’inscription de votre application.

Remarque

Si vous envisagez de déployer sur localhost avant de passer en ligne, veillez également à inscrire l’URL ssl locale et le port, par exemple, https://localhost:44383/. Dans ce cas, vous devez également définir SSL Activé sur True dans la fenêtre des propriétés du projet BingAdsWebApp, puis vous pouvez copier le port localhost à partir de la même fenêtre de propriétés.

  <?xml version="1.0" encoding="utf-8"?>
  <!--
      For more information on how to configure your ASP.NET application, please visit
      https://go.microsoft.com/fwlink/?LinkId=301880
      -->
  <configuration>
      <configSections>
      <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <section name="BingAdsWebApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </sectionGroup>
      </configSections>
      <appSettings>
      <!-- To use the production environment, set this value to "Production". -->
      <add key="BingAdsEnvironment" value="Sandbox"/>
      <add key="webpages:Version" value="3.0.0.0" />
      <add key="webpages:Enabled" value="false" />
      <add key="ClientValidationEnabled" value="true" />
      <add key="UnobtrusiveJavaScriptEnabled" value="true" />
      </appSettings>
      <system.web>
      <compilation debug="true" targetFramework="4.7.1" />
      <httpRuntime targetFramework="4.7.1" />
      <httpModules>
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
      </httpModules>
      </system.web>
      <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
          <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
          <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
          <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
          <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
          <dependentAssembly>
          <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
          <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
          </dependentAssembly>
          <dependentAssembly>
          <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
          <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
          <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
          <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
          <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
          <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
          </dependentAssembly>
      </assemblyBinding>
      </runtime>
      <system.webServer>
      <validation validateIntegratedModeConfiguration="false" />
      <modules>
          <remove name="ApplicationInsightsWebTracking" />
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
      </modules>
      </system.webServer>
      <system.codedom>
      <compilers>
          <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
          <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
      </compilers>
      </system.codedom>
      <applicationSettings>
      <BingAdsWebApp.Properties.Settings>
          <setting name="RefreshToken" serializeAs="String">
          <value />
          </setting>
          <setting name="ClientId" serializeAs="String">
          <value>ClientIdGoesHere</value>
          </setting>
          <setting name="ClientSecret" serializeAs="String">
          <value>ClientSecretGoesHere</value>
          </setting>
          <setting name="RedirectionUri" serializeAs="String">
          <value>RedirectionUriGoesHere</value>
          </setting>
          <setting name="DeveloperToken" serializeAs="String">
          <value>DeveloperTokenGoesHere</value>
          </setting>
      </BingAdsWebApp.Properties.Settings>
      </applicationSettings>
  </configuration>
  1. Créez un fichier de paramètres. Dans l’affichage projet pour BingAdsWebApp, cliquez avec le bouton droit sur Propriétés , puis cliquez sur Ouvrir. Cliquez sur Paramètres, puis sur le texte Le projet ne contient pas de fichier de paramètres par défaut. Cliquez ici pour en créer un. Les nouvelles valeurs de Web.config sont automatiquement ajoutées.

  2. Dans le dossier Views ->Home du projet BingAdsWebApp, ouvrez le fichier Index.cshtml et remplacez son contenu par le bloc de code suivant. Cela définit la vue de page web qui affiche les résultats des appels de service qui seront écrits plus loin ci-dessous.

    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    <h4>Accounts</h4>
    <p>@Html.Raw(@ViewBag.Accounts)</p>
    
    <p><b style="color: red">@ViewBag.Errors</b></p>
    
  3. Dans le dossier Controllers du projet BingAdsWebApp, ouvrez le fichier HomeController.cs et remplacez son contenu par le bloc de code suivant. Cela définit les appels de service qui déterminent les résultats affichés dans la vue définie ci-dessus.

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Net.Http;
    using System.ServiceModel;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    using BingAdsWebApp.Properties;
    using Microsoft.BingAds;
    using Microsoft.BingAds.V13.CustomerManagement;
    
    namespace BingAdsWebApp.Controllers
    {
        public class HomeController : Controller
        {
            private static AuthorizationData _authorizationData;
            private static ServiceClient<ICustomerManagementService> _customerManagementService;
            private static string ClientState = "ClientStateGoesHere";
            private static string _output = "";
    
            /// <summary>
            /// Controls the contents displayed at Index.cshtml.
            /// </summary>
            public async Task<ActionResult> Index()
            {
                try
                {
                    // If there is already an authenticated Microsoft account during this HTTP session, 
                    // go ahead and call Bing Ads API service operations.
    
                    if (Session["auth"] != null)
                    {
                        return await SetAuthorizationDataAsync((OAuthWebAuthCodeGrant)Session["auth"]);
                    }
    
                    // Prepare the OAuth object for use with the authorization code grant flow. 
    
                    var apiEnvironment =
                        ConfigurationManager.AppSettings["BingAdsEnvironment"] == ApiEnvironment.Sandbox.ToString() ?
                        ApiEnvironment.Sandbox : ApiEnvironment.Production;
                    var oAuthWebAuthCodeGrant = new OAuthWebAuthCodeGrant(
                        Settings.Default["ClientId"].ToString(),
                        Settings.Default["ClientSecret"].ToString(), 
                        new Uri(Settings.Default["RedirectionUri"].ToString()),
                        apiEnvironment);
    
                    // It is recommended that you specify a non guessable 'state' request parameter to help prevent
                    // cross site request forgery (CSRF). 
                    oAuthWebAuthCodeGrant.State = ClientState;
    
                    // When calling Bing Ads API service operations with ServiceClient or BulkServiceManager, each will refresh your access token 
                    // automatically if they detect the AuthenticationTokenExpired (109) error code. 
                    // As a best practice you should always use the most recent provided refresh token.
                    // Save the refresh token whenever new OAuth tokens are received by subscribing to the NewOAuthTokensReceived event handler. 
    
                    oAuthWebAuthCodeGrant.NewOAuthTokensReceived +=
                        (sender, args) => SaveRefreshToken(args.NewRefreshToken);
    
                    // If a refresh token is already present, use it to request new access and refresh tokens.
    
                    if (RefreshTokenExists())
                    {
                        await oAuthWebAuthCodeGrant.RequestAccessAndRefreshTokensAsync(GetRefreshToken());
    
                        // Save the authentication object in a session for future requests.
                        Session["auth"] = oAuthWebAuthCodeGrant;
    
                        return await SetAuthorizationDataAsync((OAuthWebAuthCodeGrant)Session["auth"]);
                    }
    
                    // If the current HTTP request is a callback from the Microsoft Account authorization server,
                    // use the current request url containing authorization code to request new access and refresh tokens
                    if (Request["code"] != null)
                    {
                        if (oAuthWebAuthCodeGrant.State != ClientState)
                            throw new HttpRequestException("The OAuth response state does not match the client request state.");
    
                        await oAuthWebAuthCodeGrant.RequestAccessAndRefreshTokensAsync(Request.Url);
    
                        // Save the authentication object in a session for future requests. 
                        Session["auth"] = oAuthWebAuthCodeGrant;
    
                        return await SetAuthorizationDataAsync((OAuthWebAuthCodeGrant)Session["auth"]);
                    }
    
                    SaveRefreshToken(oAuthWebAuthCodeGrant.OAuthTokens?.RefreshToken);
    
                    // If there is no refresh token saved and no callback from the authorization server, 
                    // then connect to the authorization server and request user consent. 
                    return Redirect(oAuthWebAuthCodeGrant.GetAuthorizationEndpoint().ToString());
                }
                // Catch authentication exceptions
                catch (OAuthTokenRequestException ex)
                {
                    ViewBag.Errors = (string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", 
                        ex.Details.Error, ex.Details.Description));
                    return View();
                }
                // Catch Customer Management service exceptions
                catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.AdApiFaultDetail> ex)
                {
                    ViewBag.Errors = (string.Join("; ", ex.Detail.Errors.Select(
                        error => string.Format("{0}: {1}", error.Code, error.Message))));
                    return View();
                }
                catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.ApiFault> ex)
                {
                    ViewBag.Errors = (string.Join("; ", ex.Detail.OperationErrors.Select(
                        error => string.Format("{0}: {1}", error.Code, error.Message))));
                    return View();
                }            
                catch (Exception ex)
                {
                    ViewBag.Errors = ex.Message;
                    return View();
                }
            }
    
            /// <summary>
            /// Adds a campaign to an account of the current authenticated user. 
            /// </summary>
            private async Task<ActionResult> SetAuthorizationDataAsync(Authentication authentication)
            {
                _authorizationData = new AuthorizationData
                {
                    Authentication = authentication,
                    DeveloperToken = Settings.Default["DeveloperToken"].ToString()
                };
    
                _customerManagementService = new ServiceClient<ICustomerManagementService>(_authorizationData);
    
                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 View();
    
                _authorizationData.AccountId = (long)accounts[0].Id;
                _authorizationData.CustomerId = (int)accounts[0].ParentCustomerId;
    
                OutputArrayOfAdvertiserAccount(accounts);
    
                ViewBag.Accounts = _output;
                _output = null;
    
                return View();
            }
    
            /// <summary>
            /// Saves the refresh token
            /// </summary>
            /// <param name="refreshToken">The refresh token to save</param>
            private static void SaveRefreshToken(string refreshToken)
            {
                Settings.Default["RefreshToken"] = refreshToken;
                Settings.Default.Save();
            }
    
            /// <summary>
            /// Deletes the contents in the refresh token file
            /// </summary>
            private static void DeleteRefreshToken()
            {
                Settings.Default["RefreshToken"] = "";
                Settings.Default.Save();
            }
    
            /// <summary>
            /// Determines whether the global refresh token exists.
            /// </summary>
            /// <returns>Returns true if the global refresh token exists.</returns>
            private bool RefreshTokenExists()
            {
                return Settings.Default["RefreshToken"] != null 
                    && Settings.Default["RefreshToken"].ToString().Length > 0;
            }
    
            /// <summary>
            /// Gets the global refresh token.
            /// </summary>
            /// <returns>The global refresh token.</returns>
            private string GetRefreshToken()
            {
                return Settings.Default["RefreshToken"].ToString();
            }
    
            #region OutputHelpers
    
            /**
             * You can extend the app with example output helpers at:
             * https://github.com/BingAds/BingAds-dotNet-SDK/tree/main/examples/BingAdsExamples/BingAdsExamplesLibrary/v13
             * 
             * AdInsightExampleHelper.cs
             * BulkExampleHelper.cs
             * CampaignManagementExampleHelper.cs
             * CustomerBillingExampleHelper.cs
             * CustomerManagementExampleHelper.cs
             * ReportingExampleHelper.cs
             **/
    
            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)
            {
                _output += (msg + "<br/>");
            }
    
            #endregion OutputHelpers
        }
    }
    
  4. Pour déployer l’application web sur l’ordinateur local, vous devez d’abord définir SSL Activé sur True dans la fenêtre des propriétés du projet BingAdsWebApp. Si vous ne l’avez pas déjà fait, l’URL de redirection de votre application inscrite doit inclure l’URL SSL et le port, par exemple, https://localhost:44383/. Dans le menu, sélectionnez Déboguer > Démarrer sans débogage pour exécuter l’application web localement.

  5. Pour déployer votre application web en direct à l’aide du Azure App Service consultez les instructions relatives à l’abonnement et au déploiement dans la documentation Azure, par exemple, Créer une application web ASP.NET Framework dans Azure.

Configuration du bac à sable

Pour utiliser le bac à sable, définissez la clé BingAdsEnvironment sur Bac à sable dans le <nœud appSettings> du fichier Web.config de la racine de votre projet.

<add key="BingAdsEnvironment" value ="Sandbox"/>

Vous pouvez également définir l’environnement pour chaque ServiceClient individuellement comme suit.

_customerService = new ServiceClient<ICustomerManagementService>(_authorizationData, ApiEnvironment.Sandbox);

Que vous définissiez l’environnement ServiceClient globalement ou individuellement, vous devez également définir l’environnement OAuth sur bac à sable.

var oAuthWebAuthCodeGrant = new OAuthWebAuthCodeGrant(ClientId, ClientSecret, new Uri(RedirectionUri), ApiEnvironment.Sandbox);

Voir aussi

Bac à sable
Exemples de code de l’API Bing Ads
Adresses du service web de l’API Bing Ads