共用方式為


逐步解說:C 中的 Bing 廣告 API Web 應用程式#

此範例 C# Web 應用程式會透過您提供的認證提示使用者同意,然後取得已驗證使用者可以存取的帳戶。

您必須先註冊應用程式,並記下用戶端識別碼 (已註冊的應用程式識別碼) 、用戶端密碼 (已註冊的密碼) ,以及重新導向 URI。 如需註冊應用程式和授權碼授與流程的詳細資訊,請參閱 使用 OAuth 進行驗證

您也需要生產 開發人員權杖。 您可以依照下面所述逐步建立範例,或從 GitHub下載更多範例。

提示

此範例參考在 Azure 中建立 ASP.NET Framework Web 應用程式中的步驟。 如需將 Web 應用程式部署至 Azure 的詳細資訊,您可以參閱 Azure 檔。

程式碼逐步解說

  1. 開啟Visual Studio Community 2017開發環境。 如果您已安裝 Visual Studio,請按一下 [工具> 取得工具和功能],在 Visual Studio 中新增ASP.NET 和 Web 開發Azure 開發工作負

  2. 選取 [ 檔案 > 新專案] 來建立新 > 專案。 在 [新增專案]視窗的下拉式清單中選擇[.NET Framework 4.7.1],然後選取 [Visual C# > Web > ASP.NET Web 應用程式 (.NET Framework) ]。 將專案命名為 BingAdsWebApp ,然後按一下 [ 確定]

  3. 您可以將任何類型的 ASP.NET Web 應用程式部署至 Azure。 在本快速入門中,選取 MVC 範本,確定驗證已設定為 [無驗證],然後按一下 [ 確定]

  4. 透過適用于 BingAdsWebApp 的 NuGet 安裝 SDK。 如需相依性的詳細資訊,請 參閱安裝 SDK。 按一下[工具- >NuGet 套件管理員- >套件管理員主控台]。 在提示字元中,輸入下列命令,一次安裝一個套件: Install-Package Microsoft.BingAds.SDKInstall-Package System.ServiceModel.Primitives -Version 4.4.1Install-Package System.ServiceModel.Http -Version 4.4.1Install-Package System.Configuration.ConfigurationManager -Version 4.4.1

  5. 開啟 Web.config 檔案,並以下列程式碼區塊取代其內容。 編輯 BingAdsEnvironment 以從沙箱移至生產環境,並視需要設定生產 開發人員權杖 。 您必須使用註冊應用程式時所布建的對應應用程式識別碼應用程式密碼重新導向 URL值來編輯ClientIdClientSecretRedirectionUri

注意事項

如果您想要在上線之前先在 localhost 上部署,請務必也註冊本機 SSL URL 和埠,例如 https://localhost:44383/. 在此情況下,您也必須在 BingAdsWebApp 專案屬性視窗中將 [已啟用 SSL ] 設定為 [True ],然後您可以從相同的屬性視窗複製 localhost 埠。

  <?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. 建立設定檔案。 在 BingAdsWebApp 的專案檢視中,以滑鼠右鍵按一下 [ 屬性] ,然後按一下 [ 開啟]。 按一下 [ 設定],然後按一下文字 [專案不包含預設設定檔案]。按一下這裡建立一個。 系統會自動新增來自 Web.config 的新值。

  2. BingAdsWebApp 專案的 Views - >Home資料夾中,開啟 Index.cshtml 檔案,並將其內容取代為下列程式碼區塊。 這會定義網頁檢視,以顯示將在下方進一步寫入的服務呼叫結果。

    @{
        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. 在 BingAdsWebApp 專案的 Controllers 資料夾中,開啟 HomeController.cs 檔案,並將其內容取代為下列程式碼區塊。 這會定義服務呼叫,以決定要在上面定義的檢視中顯示哪些結果。

    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. 若要先在本機電腦上部署 Web 應用程式,您必須在 BingAdsWebApp 專案屬性視窗中將 [已啟用 SSL ] 設定為 [True ]。 如果您尚未這麼做,則已註冊的應用程式重新導向 URL 必須包含 SSL URL 和埠,例如 https://localhost:44383/. 從功能表中,選取 [ 偵錯 > 開始但不 偵錯] 以在本機執行 Web 應用程式。

  5. 若要使用 Azure App 服務即時部署 Web 應用程式,請參閱 Azure 檔中的訂用帳戶和部署指示,例如,在 Azure 中建立 ASP.NET Framework Web 應用程式

設定沙箱

若要使用沙箱,請在專案根目錄Web.config檔的appSettings > 節點內 <,將BingAdsEnvironment金鑰設定為沙箱。

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

您也可以個別設定每個 ServiceClient 的環境,如下所示。

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

無論您是全域或個別設定 ServiceClient 環境,您也必須將 OAuth 環境設定為沙箱。

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

另請參閱

沙 箱
Bing 廣告 API 程式碼範例
Bing 廣告 API Web 服務位址