チュートリアル: C でのBing Ads API Web アプリケーション#
この例の C# Web アプリケーションは、指定した資格情報を使用してユーザーの同意を求め、認証されたユーザーがアクセスできるアカウントを取得します。
最初にアプリケーションを登録し、クライアント ID (登録済みアプリケーション ID)、クライアント シークレット (登録済みパスワード)、リダイレクト URI を書き留めておく必要があります。 アプリケーションの登録と承認コード付与フローの詳細については、「 OAuth による認証」を参照してください。
運用 開発者トークンも必要です。 以下で説明するように、サンプルを段階的に作成するか、 GitHub からより多くの例をダウンロードできます。
ヒント
この例では、「 Azure で ASP.NET Framework Web アプリを作成する」の手順を参照します。 Azure への Web アプリのデプロイの詳細については、Azure のドキュメントを参照してください。
コードチュートリアル
Visual Studio Community 2017 開発環境を開きます。 Visual Studio を既にインストールしている場合は、[ツール][ツール>と機能の取得] をクリックして、Visual Studio に ASP.NET と Web 開発と Azure 開発のワークロードを追加します。
[ファイル] [新しいプロジェクト] を選択して、新しい>プロジェクトを作成します。> [ 新しいプロジェクト ] ウィンドウで、ドロップダウンで [.NET Framework 4.7.1 ] を選択し、[ Visual C# > Web > ASP.NET Web Application (.NET Framework)] を選択します。 プロジェクトに BingAdsWebApp という名前を付け、[OK] をクリック します。
任意の種類の ASP.NET Web アプリを Azure にデプロイできます。 このクイック スタートでは、 MVC テンプレートを選択し、認証が [認証なし] に設定されていることを確認し、[OK] をクリック します。
BingAdsWebApp 用の NuGet を使用して SDK をインストールします。 依存関係の詳細については、「 SDK のインストール」を参照してください。 [ツール] ->[NuGet パッケージ マネージャー] -[パッケージ マネージャー コンソール] の順>にクリックします。 プロンプトで、次のコマンドを入力して、パッケージを一度に 1 つずつインストールします。
Install-Package Microsoft.BingAds.SDK
Install-Package System.ServiceModel.Primitives -Version 4.4.1
Install-Package System.ServiceModel.Http -Version 4.4.1
Install-Package System.Configuration.ConfigurationManager -Version 4.4.1
Web.config ファイルを開き、その内容を次のコード ブロックに置き換えます。 BingAdsEnvironment を編集してサンドボックスから運用に移行し、必要に応じて運用開発者トークンを設定します。 ClientId、ClientSecret、RedirectUri は、アプリケーションの登録時にプロビジョニングされた対応するアプリケーション ID、アプリケーション シークレット、リダイレクト URL の値で編集する必要があります。
注:
ライブに移行する前に localhost にデプロイする場合は、ローカル SSL URL とポート (例: ) も登録してください。 https://localhost:44383/. その場合は、BingAdsWebApp プロジェクトのプロパティ ウィンドウで SSL Enabled を 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=\"Web\" /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>
設定ファイルを作成します。 BingAdsWebApp のプロジェクト ビューで、[ プロパティ ] を右クリックし、[ 開く] をクリックします。 [ 設定] をクリックし、テキストをクリックします 。プロジェクトには既定の設定ファイルが含まれていません。ここをクリックして作成します。 Web.config からの新しい値が自動的に追加されます。
BingAdsWebApp プロジェクトの Views ->Home フォルダー内で Index.cshtml ファイルを開き、その内容を次のコード ブロックに置き換えます。 これにより、以下にさらに記述されるサービス呼び出しの結果を表示する Web ページ ビューが定義されます。
@{ ViewBag.Title = "Index"; } <h2>Index</h2> <h4>Accounts</h4> <p>@Html.Raw(@ViewBag.Accounts)</p> <p><b style="color: red">@ViewBag.Errors</b></p>
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 } }
Web アプリをローカル コンピューターにデプロイするには、まず BingAdsWebApp プロジェクトのプロパティ ウィンドウで SSL Enabled を True に設定する必要があります。 まだ登録していない場合は、登録されているアプリケーション リダイレクト URL に SSL URL とポート (例: ) を含める必要があります。 https://localhost:44383/. メニューから[ デバッグなしでデバッグ > を開始する ] を選択して、Web アプリをローカルで実行します。
Azure App Serviceを使用して Web アプリをライブにデプロイするには、Azure ドキュメント内のサブスクリプションとデプロイの手順 (例: Azure で ASP.NET Framework Web アプリを作成する) を参照してください。
サンドボックスの構成
サンドボックスを使用するには、プロジェクト ルートのWeb.configファイルの appSettings ノード内で< BingAdsEnvironment> キーを Sandbox に設定します。
<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);