Azure Cloud Services (クラシック) と ASP.NET の使用を開始する
概要
重要
Cloud Services (クラシック) は、2024 年 9 月 1 日をもって、すべてのお客様に対して非推奨になりました。 既存の実行中のデプロイはすべて Microsoft によって停止およびシャットダウンされ、2024 年 10 月以降、データは永久に失われます。 新しいデプロイでは、新しい Azure Resource Manager ベースのデプロイ モデル、 Azure Cloud Services (延長サポート) を使用してください。
このチュートリアルでは、ASP.NET Model-View-Controller (MVC) フロントエンドを使用する多層 .NET アプリケーションを作成し、Azure クラウド サービスに配置する方法について説明します。 このアプリケーションでは、Azure SQL Database、Azure Blob service、および Azure Queue サービスを使用します。 Microsoft Developer Network (MSDN) コード ギャラリーから Visual Studio プロジェクトをダウンロードできます。
このチュートリアルでは、アプリケーションを作成してローカルで実行する方法、アプリケーションを Azure にデプロイしてクラウドで実行する方法、アプリケーションを最初から作成する方法について説明します。 アプリケーションを最初から作成する手順から始め、必要に応じて後でアプリケーションのテストとデプロイ手順に進んでください。
Contoso Ads アプリケーション
このアプリケーションは、広告の掲示板です。 ユーザーは、テキストを入力し、画像をアップロードして広告を作成します。 広告の一覧にはサムネイル画像が表示されます。広告を選択すると、フルサイズ画像と詳細が表示されます。
アプリケーションでは、 キューを中心とした作業パターン を使用して、CPU 負荷の高い縮小表示の作成をバックエンド プロセスにオフロードします。
代替アーキテクチャ:App Service と WebJobs
このチュートリアルでは、Azure クラウド サービスでフロントエンドとバックエンドの両方を実行する方法について説明します。 これに代わる方法として、フロントエンドを Azure Web Apps で実行し、バックエンド用に WebJobs 機能を使用する方法があります。 Web ジョブを使用するチュートリアルについては、「 Get Started with the Azure WebJobs SDK (Azure Web ジョブ SDK の概要)」を参照してください。 ご自身のシナリオに最適なサービスを選択する方法の詳細については、「Azure App Service、Cloud Services、および Virtual Machines の比較」を参照してください。
学習目標
- Azure SDK をインストールして、Azure 向け開発用にコンピューターを準備する方法
- ASP.NET MVC の Web ロールと worker ロールを使用して、Visual Studio クラウド サービス プロジェクトを作成する方法
- Azure ストレージ エミュレーターを使用してクラウド サービス プロジェクトをローカルでテストする方法
- Azure ストレージ アカウントを使用してクラウド プロジェクトを Azure クラウド サービスに発行し、テストする方法
- ファイルを Azure Blob service にアップロードして保存する方法
- Azure Queue サービスを使用して階層間の通信を行う方法
前提条件
このチュートリアルは、Web ロール、worker ロールなどの用語を含む Azure Cloud Services の基本概念を理解している方を対象にしています。 また、Visual Studio で ASP.NET MVC または Web フォーム プロジェクトを操作する方法を理解していることも前提としています。 サンプル アプリケーションでは MVC を使用しますが、チュートリアルのほとんどは Web フォームにも当てはまります。
Azure サブスクリプションがなくてもアプリをローカルで実行できますが、アプリケーションをクラウドに配置するために必要です。 アカウントを持っていない場合は、MSDN サブスクライバーの特典を有効にするか、無料試用版にサインアップしてください。
このチュートリアルの手順は、次のどの製品でも使用できます。
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017
- Visual Studio 2019
これらの製品をお持ちでない場合は、Azure SDK をインストールすると Visual Studio が自動的にインストールされます。
アプリケーションのアーキテクチャ
このアプリでは広告を SQL データベース内に格納します。Entity Framework Code First を使用してテーブルを作成し、データにアクセスします。 それぞれの広告に対し、フルサイズ画像用とサムネイル用の 2 つの URL がデータベースに格納されます。
ユーザーが画像をアップロードすると、Web ロールで実行されているフロントエンドによってその画像が Azure BLOBに格納され、広告情報がその BLOB を示す URL と共にデータベースに格納されます。 同時に、メッセージが Azure Queue に書き込まれます。 worker ロールで実行されているバックエンド プロセスは、定期的にキューをポーリングして新しいメッセージの有無を確認します。 新しいメッセージが出現すると、worker ロールはその画像の縮小表示を作成し、その広告の縮小表示 URL データベース フィールドを更新します。 次の図に、アプリケーションの各パーツのやり取りを示します。
開発環境を設定する
最初に、Visual Studio と Azure SDK を使用した開発環境を設定します。
Visual Studio 2019 には Azure SDK が含まれています。 Visual Studio 2019 を使用している場合、開発環境を設定するための追加のセットアップは必要ありません。
Visual Studio 2015 の場合、次のリンクをクリックして Azure SDK for Visual Studio 2015 をインストールします。
Visual Studio 2013 の場合、次のリンクをクリックして Azure SDK for Visual Studio 2013 をインストールします。
Visual Studio をまだインストールしていない場合は、以下の手順に従って Visual Studio 2019 と Azure SDK をインストールしてください。
Note
マシンに既にある SDK の依存関係の数に応じて、SDK のインストールには長時間 (数分から 30 分以上) かかる場合があります。
完成したソリューションをダウンロードして実行する
完成したソリューションをダウンロードして解凍します。
Visual Studio を起動します。
[ファイル] メニューの [プロジェクトを開く] を選択し、ソリューションをダウンロードした場所に移動して、ソリューション ファイルを開きます。
ソリューションをビルドするには、Ctrl キーと Shift キーを押しながら B キーを押します。
既定では、Visual Studio は、.zip ファイル内に含まれていなかった NuGet パッケージ コンテンツを自動的に復元します。 パッケージが復元されない場合は、 [ソリューションの NuGet パッケージの管理] ダイアログ ボックスの右上にある [復元] ボタンをクリックしてパッケージを手動でインストールします。
ソリューション エクスプローラーで、ContosoAdsCloudService がスタートアップ プロジェクトとして選択されていることを確認します。
Visual Studio 2015 以上を使用している場合は、ContosoAdsWeb プロジェクトのアプリケーションの Web.config ファイルと ContosoAdsCloudService プロジェクトの ServiceConfiguration.Local.cscfg ファイルで SQL Server 接続文字列を変更します。 いずれの場合も、"(localdb)\v11.0" を "(localdb)\MSSQLLocalDB" に変更します。
アプリケーションを実行するには、Ctrl + F5 キーを押します。
クラウド サービス プロジェクトをローカルで実行すると、Visual Studio によって Azure "Compute Emulator" と Azure "Storage Emulator" が自動的に起動されます。 Compute Emulator は、コンピューターのリソースを使用して、Web ロール環境と worker ロール環境をシミュレートします。 ストレージ エミュレーターは、 SQL Server Express LocalDB を使用して、Azure クラウド ストレージをシミュレートします。
クラウド サービス プロジェクトを初めて実行するときは、エミュレーターが起動されるまで 1 分程度かかります。 エミュレーターの起動が完了すると、既定のブラウザーが開き、アプリケーションのホーム ページが表示されます。
[Create an Ad] を選択します。
テスト データを入力し、アップロードする .jpg 画像を選択してから、[Create] を選択します。
アプリは [Index] ページに移動しますが、新しい広告のサムネイルは表示されません (その処理がまだ実行されていないため)。
しばらく待ってから [Index] ページを更新すると、縮小表示が表示されます。
広告の [Details] を選択すると、フルサイズの画像が表示されます。
これまで、クラウドへの接続なしで、アプリケーションを完全にローカル コンピューター上で実行してきました。 ストレージ エミュレーターは、キュー データと BLOB データを SQL Server Express LocalDB データベースに格納します。アプリケーションは、広告データを別の LocalDB データベースに格納します。 Web アプリが初めてアクセスしようとしたとき、広告データベースが Entity Framework Code First によって自動的に作成されました。
次のセクションでは、クラウド内で実行する際に、キュー、BLOB、アプリケーション データベースに Azure クラウド リソースを使用するようにソリューションを構成します。 必要であれば、ローカルでの実行を継続しながらクラウド ストレージとデータベース リソースを使用することもできます。 これは接続文字列を設定するだけで済みます。方法は後で説明します。
アプリケーションを Azure にデプロイする
アプリケーションをクラウド内で実行するには、次の手順を実行します。
- Azure クラウド サービスを作成します。
- Azure SQL Database にデータベースを作成します。
- Azure ストレージ アカウントを作成します。
- Azure で実行されたらユーザーのデータベースを使用するようにソリューションを構成します。
- Azure で実行されたときに Azure ストレージ アカウントを使用するためのソリューションを構成します。
- プロジェクトを Azure クラウド サービスにデプロイします。
Azure クラウド サービスの作成
Azure クラウド サービスは、アプリケーションが実行される環境です。
ブラウザーで、Azure Portal を開きます。
[リソースの作成] > [コンピューティング] > [クラウド サービス] を選択します。
ドメイン ネーム システム (DNS) 名の入力ボックス内に、クラウド サービスの URL プレフィックスを入力します。
この URL は一意である必要があります。 選択したプレフィックスが既に使用されている場合は、エラー メッセージが表示されます。
新しいリソース グループをサービスに指定します。 [新規作成] を選択し、[リソース グループ] 入力ボックス内に名前を入力します (「CS_contososadsRG」など)。
アプリケーションをデプロイするリージョンを選択します。
このフィールドは、クラウド サービスがホストされるデータセンターを指定します。 運用アプリケーションの場合は、顧客に最も近いリージョンを選択してください。 このチュートリアルでは、自分に最も近いリージョンを選択してください。
[作成] を選択します
次の画像では、クラウド サービスは CSvccontosoads.cloudapp.net という URL で作成されます。
Azure SQL Database にデータベースを作成する
アプリがクラウド内で実行されると、クラウドベースのデータベースが使用されます。
Azure portal 内で、[リソースの作成] > [データベース] > [SQL Database] の順に選択します。
[データベース名] ボックスに「 contosoads」と入力します。
[リソース グループ] 内で [既存のものを使用] を選択し、クラウド サービスに使用するリソース グループを選択します。
次の画像内にある、[サーバー] - [必要な設定の構成] と [新しいサーバーの作成] を選択します。
または、サブスクリプションに既にサーバーが設定されている場合は、ドロップダウン リストからそのサーバーを選択します。
[サーバー名] ボックスに「csvccontosodbserver」と入力します。
管理者のログイン名とパスワードを入力します。
[新しいサーバーの作成] を選択した場合、ここで既存の名前とパスワードを入力することはしません。 後でデータベースへのアクセス時に使用する、現在定義中の新しい名前とパスワードを入力します。 以前に作成したサーバーを選択した場合は、既に作成した管理ユーザー アカウントのパスワードをポータルで求められます。
[場所] で、クラウド サービスに選択したのと同じ場所を選択します。
クラウド サービスとデータベースが異なるデータセンター (異なる Azure リージョン) 内にある場合、待機時間が長くなり、データ センター外の帯域幅に対して料金が発生します。 データ センター内の帯域幅は無料です。
[Azure サービスにサーバーへのアクセスを許可する] チェック ボックスをオンにします。
[新しいサーバー] の [選択] を選択します。
[作成] を選択します。
Azure のストレージ アカウントの作成
Azure ストレージ アカウントは、キューおよび BLOB データをクラウドに格納するためのリソースを提供します。
現実のアプリケーションでは、通常、アプリケーション データとログ データ、テスト データと運用データに別個のアカウントを作成します。 このチュートリアルでは、アカウントを 1 つだけ使用します。
Azure portal 内で、[リソースの作成] > [ストレージ] > [ストレージ アカウント] - [BLOB、ファイル、テーブル、キュー] を選択します。
[名前] ボックスに、URL プレフィックスを入力します。
このプレフィックスとボックスの下に表示されるテキストが、ストレージ アカウントの一意の URL です。 入力したプレフィックスが既に他のユーザーに使用されている場合は、別のプレフィックスを選択します。
[デプロイ モデル] を [クラシック] に設定します。
[レプリケーション] ボックスの一覧で、 [ローカル冗長ストレージ (LRS)] を選択します。
geo レプリケーションをストレージ アカウントに対して有効にすると、格納されたコンテンツがセカンダリ データセンターにレプリケートされ、プライマリ ロケーションで重大な障害が発生した場合のフェールオーバーが有効になります。 Geo レプリケーションには追加費用が発生する場合があります。 また、テストおよび開発アカウントの場合は、一般的に Geo レプリケーションに対する課金は避けたいと考えるでしょう。 詳細については、「 ストレージ アカウントの作成、管理、削除」を参照してください。
[リソース グループ] 内で、[既存のものを使用] を選択し、クラウド サービスに使用するリソース グループを選択します。
[場所] ボックスの一覧で、クラウド サービスに選択したのと同じリージョンを選択します。
クラウド サービスとストレージ アカウントが異なるデータセンター (異なる Azure リージョン) 内にある場合、待機時間が長くなり、データ センター外の帯域幅に対して料金が発生します。 データ センター内の帯域幅は無料です。
Azure アフィニティ グループには、データ センター内のリソース間の距離を最短にする機能が備わっており、それにより遅延時間を短縮できます。 このチュートリアルでアフィニティ グループは使用しません。 詳細については、 Azure でアフィニティ グループを作成する方法に関するページを参照してください。
[作成] を選択します。
次の画像では、ストレージ アカウントは
csvccontosoads.core.windows.net
という URL で作成されます。
Azure で実行されたら Azure SQL Database のデータベースを使用するようにソリューションを構成する
Web プロジェクトと worker ロール プロジェクトにはそれぞれ独自のデータベース接続文字列があり、アプリが Azure で実行されたときはそれぞれが Azure SQL Database のデータベースを指し示す必要があります。
Web ロールには Web.config 変換を、worker にはクラウド サービス環境設定を使用します。
Note
このセクションと次のセクションでは、資格情報をプロジェクト ファイルに格納します。 機密データは、パブリックなソース コード リポジトリに格納しないでください。
ContosoAdsWeb プロジェクトで、アプリケーションの Web.config ファイルの Web.Release.config 変換ファイルを開き、
<connectionStrings>
要素が含まれているコメント ブロックを削除した後、次のコードをその場所に貼り付けます。<connectionStrings> <add name="ContosoAdsContext" connectionString="{connectionstring}" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> </connectionStrings>
ファイルは編集できるように開いたままにしておきます。
Azure Portal 内で、左側ペイン内の [SQL databases] を選択し、このチュートリアル用に作成したデータベースを選択してから、[接続文字列の表示] を選択します。
接続文字列と、パスワードのプレースホルダーがポータルに表示されます。
Web.Release.config 変換ファイルで
{connectionstring}
を削除し、Azure Portal からコピーした ADO.NET 接続文字列をその場所に貼り付けます。Web.Release.config 変換ファイルに貼り付けた接続文字列内の
{your_password_here}
を、新しい SQL データベース用に作成したパスワードで置き換えます。ファイルを保存します。
以降の worker ロール プロジェクトを構成するための手順で使用する接続文字列を選択してコピーします (引用符は除きます)。
ソリューション エクスプローラー内で、該当するクラウド サービス プロジェクト内の [Roles] の下にある [ContosoAdsWorker] を右クリックしてから、[プロパティ] を選択します。
[設定] タブを選択します。
[サービス構成] を [クラウド] に変更します。
ContosoAdsDbConnectionString
設定の [値] フィールドを選択し、このチュートリアルの前のセクションでコピーした接続文字列を貼り付けます。変更を保存します。
Azure で実行されたときに Azure ストレージ アカウントを使用するためのソリューションの設定
Web ロール プロジェクトと worker ロール プロジェクトの Azure ストレージ アカウント接続文字列は、クラウド サービス プロジェクトの環境設定に保存されます。 プロジェクトごとに、アプリケーションがローカルで実行された際と、クラウド内で実行された際に使用される個別の設定のセットがあります。 Web ロール プロジェクトと worker プロジェクトの両方のクラウド環境設定を更新します。
ソリューション エクスプローラー内で、[ContosoAdsCloudService] プロジェクト内の [Roles] の下にある [ContosoAdsWeb] を右クリックし、[プロパティ] を選択します。
[設定] タブを選択します。[サービス構成] ボックスの一覧の [クラウド] を選択します。
[StorageConnectionString] エントリを選択すると、行の右端に省略記号 [...] ボタンが表示されます。 省略記号ボタンを選択して、[ストレージ接続文字列の作成] ダイアログ ボックスを開きます。
[ストレージ接続文字列の作成] ダイアログ ボックス内で、[サブスクリプション] オプションを選択し、前に作成したストレージ アカウントを選択してから、[OK] を選択します。 まだサインインする必要がある場合は、エクスプローラーで Azure アカウントの資格情報を求められます。
変更を保存します。
StorageConnectionString
接続文字列の場合と同じ手順を使用して、Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString
接続文字列を設定します。この接続文字列は、ログに使用されます。
ContosoAdsWeb ロールの場合と同じ手順に従って、ContosoAdsWorker ロールの両方の接続文字列を設定します。 このとき、 [サービス構成] を [クラウド] に設定するのを忘れないでください。
Visual Studio UI を使用して構成したロールの環境設定は、ContosoAdsCloudService プロジェクト内の次のファイル内に格納されます。
- ServiceDefinition.csdef - 設定名を定義します。
- ServiceConfiguration.Cloud.cscfg - アプリがクラウドで実行されるときに値を提供します。
- ServiceConfiguration.Local.cscfg - アプリがローカルで実行されるときに値を提供します。
たとえば、ServiceDefinition.csdef には、次の定義が含まれます。
<ConfigurationSettings>
<Setting name="StorageConnectionString" />
<Setting name="ContosoAdsDbConnectionString" />
</ConfigurationSettings>
ServiceConfiguration.Cloud.cscfg ファイルには、Visual Studio でこれらの設定に入力した値が含まれます。
<Role name="ContosoAdsWorker">
<Instances count="1" />
<ConfigurationSettings>
<Setting name="StorageConnectionString" value="{yourconnectionstring}" />
<Setting name="ContosoAdsDbConnectionString" value="{yourconnectionstring}" />
<!-- other settings not shown -->
</ConfigurationSettings>
<!-- other settings not shown -->
</Role>
<Instances>
設定では、Azure で worker コードが実行される仮想マシンの数を指定します。 「 次のステップ 」セクションに、クラウド サービスのスケールアウトに関する情報へのリンクが含まれています。
Azure にプロジェクトをデプロイする
ソリューション エクスプローラーで、 [ContosoAdsCloudService] クラウド プロジェクトを右クリックし、 [発行] をクリックします。
Azure アプリケーションの発行ウィザードの [サインイン] 手順内で、[次へ] を選択します。
ウィザードの [設定] 手順内で、[次へ] を選択します。
[詳細設定] タブの既定の設定はこのチュートリアルではそのまま使用します。 [詳細設定] タブの詳細については、「 Microsoft Azure アプリケーションの発行ウィザード」を参照してください。
[概要] 手順内で、[発行] を選択します。
[Azure のアクティビティ ログ] ウィンドウが Visual Studio で開きます。
右矢印のアイコンを選択して配置の詳細を展開します。
デプロイが完了するまで 5 分程度かかる場合があります。
配置の状態が完了になったら、[Web アプリ URL] を選択してアプリケーションを起動します。
この段階で、アプリケーションをローカルで実行したときと同様に、広告を作成、表示、編集して、アプリをテストできます。
Note
テストが終了したら、クラウド サービスを削除または停止します。 クラウド サービスを使用していない場合でも仮想マシンのリソースが予約されるため、課金が発生します。 またクラウド サービスを実行したままにしておくと、その URL を見つけた他のユーザーが広告を作成したり表示したりする可能性があります。 Azure Portal で、クラウド サービスの [概要] タブに移動し、ページの上部にある [削除] ボタンをクリックします。 一時的に他のユーザーがこのサイトにアクセスできないようにするには、代わりに [停止] をクリックします。 この場合は、課金が継続されます。 同様の手順で、不要になった SQL データベースとストレージ アカウントを削除できます。
アプリケーションを最初から作成する
それでも完成したアプリケーションをダウンロードする必要がある場合は、今すぐにそうしてください。 ダウンロードしたプロジェクトから新しいプロジェクトにファイルをコピーします。
Contoso Ads アプリケーションを作成するには、次の手順を実行します。
- クラウド サービスの Visual Studio ソリューションを作成します。
- NuGet パッケージを更新して追加します。
- プロジェクト参照を設定します。
- 接続文字列を構成します。
- コード ファイルを追加します。
ソリューションを作成したら、クラウド サービス プロジェクト、Azure BLOB、およびキューに一意のコードを見ていきます。
クラウド サービス Visual Studio ソリューションの作成
Visual Studio で、 新しいプロジェクト from the [新しいプロジェクト] を選択します。
[新しいプロジェクト] ダイアログ ボックスの左側のウィンドウで、 [Visual C#] を展開し、 [クラウド] テンプレート、 [Azure クラウド サービス] テンプレートの順に選択します。
プロジェクトとソリューションに「ContosoAdsCloudService」という名前を付けて [OK] を選択します。
[新しい Azure クラウド サービス] ダイアログ ボックスで、Web ロールと worker ロールを追加します。 Web ロールに ContosoAdsWeb という名前を付け、worker ロールに ContosoAdsWorker という名前を付けます (右側のウィンドウの鉛筆アイコンを使用して、ロールの既定の名前を変更します)。
Web ロールの [新しい ASP.NET プロジェクト] ダイアログ ボックスが表示されたら [MVC] テンプレートを選択し、次に [認証の変更] を選択します。
[認証の変更] ダイアログ ボックス内で、[認証なし] を選択し、次に [OK] を選択します。
[新しい ASP.NET プロジェクト] ダイアログ内で [OK] を選択します。
ソリューション エクスプローラーで (プロジェクトのソリューション以外の) ソリューションを右クリックし、 [追加] > [新しいプロジェクト] の順に選択します。
[新しいプロジェクトの追加] ダイアログ ボックス内で、左側ペイン内の [Visual C#] の下にある [Windows] を選択し、[クラス ライブラリ] テンプレートを選択します。
そのプロジェクトに「ContosoAdsCommon」という名前を付けてから、[OK] を選択します。
Web ロール プロジェクトと worker ロール プロジェクトの両方から Entity Framework のコンテキストとデータ モデルを参照する必要があります。 代わりの方法として、Entity Framework に関連するクラスを Web ロール プロジェクトで定義し、worker ロール プロジェクトからそのプロジェクトを参照することもできます。 ただしその代替方法では、worker ロール プロジェクトに、必要としない Web アセンブリへの参照が含まれることになります。
NuGet パッケージの更新および追加
ソリューションの [NuGet パッケージの管理] ダイアログ ボックスを開きます。
ウィンドウの上部にある [更新プログラム] を選択します。
WindowsAzure.Storage パッケージを探して、一覧内にある場合はそれを選択し、更新する Web および worker プロジェクトを選択してから、[更新] を選択します。
ストレージ クライアント ライブラリは Visual Studio プロジェクト テンプレートよりも頻繁に更新されるため、新しく作成したプロジェクトのバージョンの更新が必要になることがあります。
ウィンドウの上部にある [参照] を選択します。
EntityFramework NuGet パッケージを見つけて、3 つのプロジェクトすべてにインストールします。
Microsoft.WindowsAzure.ConfigurationManager NuGet パッケージを見つけ、worker ロール プロジェクトにインストールします。
プロジェクト参照の設定
ContosoAdsWeb プロジェクトで、ContosoAdsCommon プロジェクトの参照を設定します。 [ContosoAdsWeb] プロジェクトを右クリックしてから、[参照] - [参照の追加] を選択します。 [参照マネージャー] ダイアログ ボックス内で、左側ペイン内の [ソリューション] – [プロジェクト] を選択し、[ContosoAdsCommon] を選択してから、[OK] を選択します。
ContosoAdsWorker プロジェクトで、ContosoAdsCommon プロジェクトの参照を設定します。
ContosoAdsCommon には、フロントエンドとバックエンドの両方を使用する Entity Framework データ モデルとコンテキスト クラスが含まれています。
ContosoAdsWorker プロジェクトで、
System.Drawing
プロジェクトの参照を設定します。このアセンブリは、画像を縮小表示に変換するためにバックエンドで使用されます。
接続文字列の構成
このセクションでは、Azure Storage と SQL 接続文字列をローカルでのテスト用に構成します。 チュートリアルの前半で紹介したデプロイ手順では、アプリケーションをクラウドで実行する場合の接続文字列の設定方法について説明しました。
ContosoAdsWeb プロジェクトで、アプリケーションの Web.config ファイルを開き、
connectionStrings
要素をconfigSections
要素の後に挿入します。<connectionStrings> <add name="ContosoAdsContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
Visual Studio 2015 以上を使用している場合は、"v11.0" を "MSSQLLocalDB" に置き換えます。
変更を保存。
[ContosoAdsCloudService] プロジェクト内で、[Roles] の下にある [ContosoAdsWeb] を右クリックしてから、[プロパティ] を選択します。
[Roles] の下にある [ContosoAdsWeb] のプロパティ ウィンドウ内で [設定] タブを選択してから、[設定の追加] を選択します。
[サービス構成] は [すべての構成] のままにしておきます。
StorageConnectionString という名前の設定を追加します。 [種類] を [接続文字列] に設定し、 [値] を UseDevelopmentStorage=true に設定します。
変更を保存します。
同じ手順を実行して、ストレージの接続文字列を ContosoAdsWorker ロール プロパティに追加します。
[Roles] の下にある [ContosoAdsWorker] のプロパティ ウィンドウ内にまだいる間に、別の接続文字列を追加します。
名前:ContosoAdsDbConnectionString
型: String
値:Web ロール プロジェクトに使用したのと同じ接続文字列を貼り付けます (次の例は Visual Studio 2013 用です。Visual Studio 2015 以上を使用していて、この例をコピーする場合は、忘れずにデータ ソースを変更してください)。
Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;
コード ファイルの追加
このセクションでは、ダウンロードしたソリューションから新しいソリューションにコード ファイルをコピーします。 以降のセクションでは、このコードの重要な部分について説明します。
プロジェクトまたはフォルダーにファイルを追加するには、プロジェクトまたはフォルダーを右クリックして、[追加] - [既存の項目] を選択します。 目的のファイルを選択し、[追加] を選択します。 既存のファイルを置き換えるかどうかを確認された場合は、[はい] を選択します。
ContosoAdsCommon プロジェクトで、Class1.cs ファイルを削除します。その場所に、ダウンロードしたプロジェクトから Ad.cs ファイルと ContosoAdscontext.cs ファイルを追加します。
ContosoAdsWeb プロジェクトで、ダウンロードしたプロジェクトから次のファイルを追加します。
- Global.asax.cs。
- Views\Shared フォルダー: _Layout.cshtml。
- Views\Home フォルダー内:Index.cshtml。
- Controllers フォルダー内:AdController.cs。
- Views\Ad フォルダー (最初にフォルダーを作成): 5 つの .cshtml ファイル。
ContosoAdsWorker プロジェクトで、ダウンロードしたプロジェクトから WorkerRole.cs を追加します。
チュートリアルの前の手順のとおり、アプリケーションをビルドして実行できるようになりました。アプリではローカル データベースとストレージ エミュレーターのリソースが使用されます。
以降のセクションでは、Azure 環境、BLOB、およびキューの操作に関連するコードについて説明します。 このチュートリアルでは、スキャフォールディングを使用した MVC コントローラーおよびビューの作成方法、SQL Server データベースで動作する Entity Framework コードの記述方法、ASP.NET 4.5 での非同期プログラミングの基礎については説明しません。 これらのトピックについては、次のリソースを参照してください。
ContosoAdsCommon - Ad.cs
Ad.cs ファイルは、広告カテゴリの enum と広告情報の POCO エンティティ クラスを定義します。
public enum Category
{
Cars,
[Display(Name="Real Estate")]
RealEstate,
[Display(Name = "Free Stuff")]
FreeStuff
}
public class Ad
{
public int AdId { get; set; }
[StringLength(100)]
public string Title { get; set; }
public int Price { get; set; }
[StringLength(1000)]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[StringLength(1000)]
[DisplayName("Full-size Image")]
public string ImageURL { get; set; }
[StringLength(1000)]
[DisplayName("Thumbnail")]
public string ThumbnailURL { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime PostedDate { get; set; }
public Category? Category { get; set; }
[StringLength(12)]
public string Phone { get; set; }
}
ContosoAdsCommon - ContosoAdsContext.cs
ContosoAdsContext クラスでは、Entity Framework が SQL データベース内に格納する DbSet コレクション内で、Ad クラスが使用されることを指定します。
public class ContosoAdsContext : DbContext
{
public ContosoAdsContext() : base("name=ContosoAdsContext")
{
}
public ContosoAdsContext(string connString)
: base(connString)
{
}
public System.Data.Entity.DbSet<Ad> Ads { get; set; }
}
このクラスには 2 つのコンストラクターがあります。 1 つ目のコンストラクターは Web プロジェクトによって使用され、Web.config ファイルに格納される接続文字列の名前を指定します。 2 つ目のコンストラクターにより、Web.config ファイルがないため worker ロール プロジェクトによって使用される実際の接続文字列を渡すことができます。 この接続文字列が格納されていた場所は、先ほど確認しました。 後で、コードで DbContext クラスがインスタンス化される際に接続文字列を取得する方法について説明します。
ContosoAdsWeb - Global.asax.cs
Application_Start
メソッドから呼び出されるコードにより、images BLOB コンテナーと images キューが存在しない場合はこれらが作成されます。 このコードにより、新しいストレージ アカウントを使用したり、新しいコンピューター上でストレージ エミュレーターを使用したりするたびに、必要な BLOB コンテナーとキューがコードで自動的に作成されることが保証されます。
次に、 .cscfg ファイルからのストレージ接続文字列を使用してストレージ アカウントへのアクセスが取得されます。
var storageAccount = CloudStorageAccount.Parse
(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
次に、 images BLOB コンテナーの参照が取得され、コンテナーがまだ存在していない場合はこれが作成され、新しいコンテナーのアクセス許可が設定されます。 既定では、新しいコンテナーは、ストレージ アカウント資格情報を持つクライアントのみに BLOB へのアクセスを許可します。 Web サイトで画像 BLOB を指し示す URL を使用して画像を表示できるようにするには、BLOB をパブリックに設定する必要があります。
var blobClient = storageAccount.CreateCloudBlobClient();
var imagesBlobContainer = blobClient.GetContainerReference("images");
if (imagesBlobContainer.CreateIfNotExists())
{
imagesBlobContainer.SetPermissions(
new BlobContainerPermissions
{
PublicAccess =BlobContainerPublicAccessType.Blob
});
}
似たようなコードを使用して、 images キューの参照を取得し、新しいキューを作成できます。 この場合、アクセス許可の変更は必要ありません。
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
var imagesQueue = queueClient.GetQueueReference("images");
imagesQueue.CreateIfNotExists();
ContosoAdsWeb - _Layout.cshtml
_Layout.cshtml ファイルは、アプリ名をヘッダーとフッターに設定し、"Ads" メニュー エントリを作成します。
ContosoAdsWeb - Views\Home\Index.cshtml
Views\Home\Index.cshtml ファイルは、ホーム ページにカテゴリ リンクを表示します。 リンクは、querystring 変数の Category
enum の整数値を Ads Index ページに渡します。
<li>@Html.ActionLink("Cars", "Index", "Ad", new { category = (int)Category.Cars }, null)</li>
<li>@Html.ActionLink("Real estate", "Index", "Ad", new { category = (int)Category.RealEstate }, null)</li>
<li>@Html.ActionLink("Free stuff", "Index", "Ad", new { category = (int)Category.FreeStuff }, null)</li>
<li>@Html.ActionLink("All", "Index", "Ad", null, null)</li>
ContosoAdsWeb - AdController.cs
AdController.cs ファイル内では、コンストラクターによって InitializeStorage
メソッドが呼び出され、BLOB とキューを操作するための API を提供する Azure Storage クライアント ライブラリ オブジェクトが作成されます。
次に、Global.asax.cs と同様に、images BLOB コンテナーへの参照が取得されます。 この処理中に、Web アプリに適した既定の 再試行ポリシー が設定されます。 既定の指数関数的バックオフ再試行ポリシーでは、一時的な障害に対する反復的再試行操作によって Web アプリが 1 分以上応答を停止する可能性があります。 ここでは、再試行ごとに 3 秒待機し、再試行の回数を 3 回までとする再試行ポリシーを指定しています。
var blobClient = storageAccount.CreateCloudBlobClient();
blobClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesBlobContainer = blobClient.GetContainerReference("images");
似たようなコードを使用して、 images キューの参照を取得できます。
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
queueClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesQueue = queueClient.GetQueueReference("images");
コントローラー コードのほとんどは、DbContext クラスを使用した Entity Framework データ モデルの操作に典型的なものです。 ただし、ファイルをアップロードして Blob Storage に保存する HttpPost Create
メソッドは例外です。 モデル バインダーは、このメソッドに HttpPostedFileBase オブジェクトを提供します。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(
[Bind(Include = "Title,Price,Description,Category,Phone")] Ad ad,
HttpPostedFileBase imageFile)
ユーザーがアップロードするファイルを選択すると、ファイルがアップロードされて BLOB に保存されます。さらに、Ad データベース レコードが更新され、その BLOB を示す URL が反映されます。
if (imageFile != null && imageFile.ContentLength != 0)
{
blob = await UploadAndSaveBlobAsync(imageFile);
ad.ImageURL = blob.Uri.ToString();
}
アップロード操作を実行するコードは UploadAndSaveBlobAsync
メソッドに含まれています。 このコードでは、BLOB の GUID 名が作成され、ファイルがアップロードおよび保存され、保存された BLOB への参照が返されます。
private async Task<CloudBlockBlob> UploadAndSaveBlobAsync(HttpPostedFileBase imageFile)
{
string blobName = Guid.NewGuid().ToString() + Path.GetExtension(imageFile.FileName);
CloudBlockBlob imageBlob = imagesBlobContainer.GetBlockBlobReference(blobName);
using (var fileStream = imageFile.InputStream)
{
await imageBlob.UploadFromStreamAsync(fileStream);
}
return imageBlob;
}
HttpPost Create
メソッドは、BLOB をアップロードしてデータベースを更新した後、画像を縮小表示に変換する準備が整ったことをバックエンド プロセスに通知するキュー メッセージを作成します。
string queueMessageString = ad.AdId.ToString();
var queueMessage = new CloudQueueMessage(queueMessageString);
await queue.AddMessageAsync(queueMessage);
HttpPost Edit
メソッドのコードも似ていますが、ユーザーが新しい画像ファイルを選択した場合に既に存在している BLOB を削除する必要がある点が異なります。
if (imageFile != null && imageFile.ContentLength != 0)
{
await DeleteAdBlobsAsync(ad);
imageBlob = await UploadAndSaveBlobAsync(imageFile);
ad.ImageURL = imageBlob.Uri.ToString();
}
次の例で示すのは、広告が削除されたときに BLOB を削除するコードです。
private async Task DeleteAdBlobsAsync(Ad ad)
{
if (!string.IsNullOrWhiteSpace(ad.ImageURL))
{
Uri blobUri = new Uri(ad.ImageURL);
await DeleteAdBlobAsync(blobUri);
}
if (!string.IsNullOrWhiteSpace(ad.ThumbnailURL))
{
Uri blobUri = new Uri(ad.ThumbnailURL);
await DeleteAdBlobAsync(blobUri);
}
}
private static async Task DeleteAdBlobAsync(Uri blobUri)
{
string blobName = blobUri.Segments[blobUri.Segments.Length - 1];
CloudBlockBlob blobToDelete = imagesBlobContainer.GetBlockBlobReference(blobName);
await blobToDelete.DeleteAsync();
}
ContosoAdsWeb - Views\Ad\Index.cshtml および Details.cshtml
Index.cshtml ファイルは、縮小表示を他の広告データと共に表示します。
<img src="@Html.Raw(item.ThumbnailURL)" />
Details.cshtml ファイルは、フルサイズの画像を表示します。
<img src="@Html.Raw(Model.ImageURL)" />
ContosoAdsWeb - Views\Ad\Create.cshtml および Edit.cshtml
Create.cshtml ファイルと Edit.cshtml ファイルは、フォームのエンコードを指定してコントローラーが HttpPostedFileBase
オブジェクトを取得できるようにします。
@using (Html.BeginForm("Create", "Ad", FormMethod.Post, new { enctype = "multipart/form-data" }))
<input>
要素は、ファイル選択ダイアログを表示するようにブラウザーに指示します。
<input type="file" name="imageFile" accept="image/*" class="form-control fileupload" />
ContosoAdsWorker - WorkerRole.cs - OnStart メソッド
Azure worker ロール環境は、worker ロールの起動時に WorkerRole
クラスの OnStart
メソッドを呼び出し、OnStart
メソッドの終了時に Run
メソッドを呼び出します。
OnStart
メソッドは、 .cscfg ファイルからデータベース接続文字列を取得して Entity Framework の DbContext クラスに渡します。 SQLClient プロバイダーは既定で使用されるため、プロバイダーを指定する必要はありません。
var dbConnString = CloudConfigurationManager.GetSetting("ContosoAdsDbConnectionString");
db = new ContosoAdsContext(dbConnString);
次に、ストレージ アカウントへの参照が取得され、BLOB コンテナーとキューが存在しない場合はこれらが作成されます。 この操作を行うためのコードは、Web ロールの Application_Start
メソッドで示したコードに似ています。
ContosoAdsWorker - WorkerRole.cs - Run メソッド
Run
メソッドは、OnStart
メソッドが初期化操作を終了するときに呼び出されます。 このメソッドは、新しいキュー メッセージを監視する無限ループを実行して、キュー メッセージが到着したときにそれを処理します。
public override void Run()
{
CloudQueueMessage msg = null;
while (true)
{
try
{
msg = this.imagesQueue.GetMessage();
if (msg != null)
{
ProcessQueueMessage(msg);
}
else
{
System.Threading.Thread.Sleep(1000);
}
}
catch (StorageException e)
{
if (msg != null && msg.DequeueCount > 5)
{
this.imagesQueue.DeleteMessage(msg);
}
System.Threading.Thread.Sleep(5000);
}
}
}
ループの各イテレーションの後でキュー メッセージが見つからなかった場合、プログラムは 1 秒間スリープ状態になります。 このスリープにより、worker が過剰な CPU 時間とストレージ トランザクション コストを発生させないようにします。 Microsoft Customer Advisory Team では、このスリープ機能を含めるのを忘れて、運用環境に配置し、休暇に出かけた開発者の話をしています。 戻ってきたときには、休暇を超える監視コストになりました。
ときには、キュー メッセージの内容が原因で処理エラーが生じることがあります。 この種のメッセージは、"有害なメッセージ" と呼ばれています。 単にエラーをログに記録し、ループを再開しただけの場合は、そのメッセージの処理を無限に試みるおそれがあります。 そのため、catch ブロックには、アプリが現在のメッセージを処理しようとした回数を確認する if ステートメントが含まれています。 カウントが 5 回を超える場合、そのメッセージはキューから削除されます。
ProcessQueueMessage
は、キュー メッセージが見つかったときに呼び出されます。
private void ProcessQueueMessage(CloudQueueMessage msg)
{
var adId = int.Parse(msg.AsString);
Ad ad = db.Ads.Find(adId);
if (ad == null)
{
throw new Exception(String.Format("AdId {0} not found, can't create thumbnail", adId.ToString()));
}
CloudBlockBlob inputBlob = this.imagesBlobContainer.GetBlockBlobReference(ad.ImageURL);
string thumbnailName = Path.GetFileNameWithoutExtension(inputBlob.Name) + "thumb.jpg";
CloudBlockBlob outputBlob = this.imagesBlobContainer.GetBlockBlobReference(thumbnailName);
using (Stream input = inputBlob.OpenRead())
using (Stream output = outputBlob.OpenWrite())
{
ConvertImageToThumbnailJPG(input, output);
outputBlob.Properties.ContentType = "image/jpeg";
}
ad.ThumbnailURL = outputBlob.Uri.ToString();
db.SaveChanges();
this.imagesQueue.DeleteMessage(msg);
}
このコードには、データベースを読み取って画像の URL を取得する操作、画像を縮小表示に変換する操作、縮小表示を BLOB に保存する操作、縮小表示 BLOB の URL を反映するようにデータベースを更新する操作、およびキュー メッセージを削除する操作が含まれています。
Note
ConvertImageToThumbnailJPG
メソッドのコードでは、簡略化のために System.Drawing 名前空間のクラスを使用しています。 ただし、この名前空間のクラスは Windows フォーム用に設計されています。 これらのクラスは、Windows または ASP.NET サービスでの使用に関してサポートされていません。 イメージの処理オプションの詳細については、イメージの動的生成とイメージのサイズ変更の詳細に関する各ページを参照してください。
トラブルシューティング
このチュートリアルの手順に従って作業しているときに発生する可能性のある一般的なエラーとその解決方法について説明します。
ServiceRuntime.RoleEnvironmentException
RoleEnvironment
オブジェクトは、アプリケーションを Azure で実行したときまたは Azure Compute Emulator を使用してローカルで実行したときに Azure によって提供されます。 ローカルで実行している際にこのエラーが発生する場合は、必ず ContosoAdsCloudService プロジェクトをスタートアップ プロジェクトとして設定してください。 この設定により、Azure Compute Emulator を使用してプロジェクトが実行されます。
アプリケーションが Azure RoleEnvironment を使用する目的の 1 つに、 .cscfg ファイルに格納されている接続文字列値を取得することがあります。したがって、この例外の別の原因として、接続文字列が見つからないことが考えられます。 ContosoAdsWeb プロジェクトのクラウド構成とローカル構成の両方に対して StorageConnectionString 設定が作成されていること、および ContosoAdsWorker プロジェクトの両方の構成に対して両方の接続文字列が作成されていることを確認してください。 ソリューション全体に対して StorageConnectionString の [すべて検索] を実行すると、6 つのファイル内に 9 件見つかります。
ポート xxx をオーバーライドできません。 新しいポートが http プロトコルで許容されている最小値 8080 を下回っています
Web プロジェクトで使用するポート番号を変更してください。 [ContosoAdsWeb] プロジェクトを右クリックし、[プロパティ] を選択します。 [Web] タブを選択してから、[プロジェクトの URL] 設定内のポート番号を変更します。
ほかに考えられるこの問題の解決方法については、次のセクションを参照してください。
ローカルで実行しているときに発生するその他のエラー
既定では、新しいクラウド サービス プロジェクトは、Azure Compute Emulator Express を使用して Azure 環境をシミュレートします。 Azure Compute Emulator はフル装備のコンピューティング エミュレーターの軽量バージョンであり、一部の条件下では、Express バージョンが機能しない場合に完全なエミュレーターが動作します。
フル装備のエミュレーターを使用するようにプロジェクトを変更するには、[ContosoAdsCloudService] プロジェクトを右クリックして、[プロパティ] を選択します。 [プロパティ] ウィンドウ内で、[Web] タブを選択してから、[Full Emulator を使用する] ラジオ ボタンを選択します。
フル装備のエミュレーターを使用してアプリケーションを実行するには、管理者特権で Visual Studio を開く必要があります。
次のステップ
Contoso Ads アプリケーションは、入門チュートリアル用に意図的にシンプルに作られています。 たとえば、依存関係挿入やリポジトリと作業単位パターンは実装されていません。 ログ記録用のインターフェイス、データ モデル変更管理の EF Code First 移行、一時的なネットワーク エラー管理の EF 接続の回復性なども使用されていません。
クラウド向けの開発については、「 Azure を使用した実際のクラウド アプリケーションの作成」をご覧ください。
詳細については、次のリソースを参照してください。