付録: Fix it サンプル アプリケーション (Azure を使用したクラウド アプリReal-Worldビルド)

作成者 : Rick AndersonTom Dykstra

Fix It プロジェクトをダウンロードする

Azure 電子書籍 を使用した Real World Cloud Apps の構築 は、Scott Guthrie が開発したプレゼンテーションに基づいています。 クラウド向けの Web アプリの開発を成功させるために役立つ 13 のパターンとプラクティスについて説明します。 電子書籍の詳細については、 最初の章を参照してください。

Azure を使用した Real World Cloud Apps の構築に関する電子書籍のこの付録には、ダウンロードできる Fix It サンプル アプリケーションに関する追加情報を提供する次のセクションが含まれています。

既知の問題

Fix It アプリは、この電子書籍に示されているパターンの一部を可能な限り簡単に示すために開発されました。 ただし、この電子書籍は実際のアプリの構築に関するものなので、Fix It コードに、リリースされたソフトウェアに対して行うのと同様のレビューとテスト プロセスを適用しました。 多くの問題が見つかり、実際のアプリケーションと同様に、それらの一部を修正し、その一部を後のリリースに延期しました。

次の一覧には、運用アプリケーションで対処する必要がある問題が含まれていますが、何かの理由で、Fix It サンプル アプリケーションの最初のリリースでは対処しないことを決定しました。

セキュリティ

  • 存在しない所有者にタスクを割り当てることができないことを確認します。
  • 自分が作成または割り当てたタスクのみを表示および変更できることを確認します。
  • サインイン ページと認証 Cookie には HTTPS を使用します。
  • 認証 Cookie の制限時間を指定します。

入力の検証

一般に、運用アプリは Fix It アプリよりも多くの入力検証を行います。 たとえば、アップロードに使用できるイメージ サイズ/イメージ ファイル サイズを制限する必要があります。

管理者の機能

管理者は、既存のタスクの所有権を変更できる必要があります。 たとえば、タスクの作成者が会社を離れ、管理者アクセスが有効になっていない限り、タスクを維持する権限を持つユーザーがいなくなる場合があります。

キュー メッセージの処理

Fix It アプリでのキュー メッセージ処理は、キュー中心の作業パターンを最小限のコードで示すために単純に設計されました。 この単純なコードは、実際の運用アプリケーションには適していません。

  • このコードでは、各キュー メッセージが最大で 1 回処理されるとは限りません。 キューからメッセージを取得すると、タイムアウト期間があり、その間、メッセージは他のキュー リスナーには表示されません。 メッセージが削除される前にタイムアウトが切れると、メッセージが再び表示されます。 したがって、ワーカー ロール インスタンスがメッセージの処理に長い時間を費やすと、理論的には同じメッセージが 2 回処理され、データベース内のタスクが重複する可能性があります。 この問題の詳細については、「 Azure Storage キューの使用」を参照してください。
  • メッセージの取得をバッチ処理することで、キュー ポーリング ロジックの方がコスト効率が高くなります。 CloudQueue.GetMessageAsync を呼び出すたびに、トランザクション コストが発生します。 代わりに、CloudQueue.GetMessagesAsync (複数形の 's' に注意してください) を呼び出して、1 つのトランザクションで複数のメッセージを取得できます。 Azure Storage キューのトランザクション コストは非常に低いので、ほとんどのシナリオではコストへの影響は大きくはありません。
  • キュー メッセージ処理コードの緊密なループによって CPU アフィニティが発生し、マルチコア VM を効率的に利用しません。 より優れた設計では、タスクの並列処理を使用して、複数の非同期タスクを並列で実行します。
  • キュー メッセージ処理には基本的な例外処理しかありません。 たとえば、コードは 有害メッセージを処理しません。 (メッセージ処理で例外が発生した場合は、エラーをログに記録してメッセージを削除する必要があります。または、ワーカー ロールがもう一度処理を試み、ループは無期限に続行されます)。

SQL クエリは無制限です

Current Fix It コードでは、インデックス ページのクエリが返す行の数に制限はありません。 大量のタスクがデータベースに入力されると、受信した結果のリストのサイズによってパフォーマンスの問題が発生する可能性があります。 解決策は、ページングを実装することです。 例については、「 ASP.NET MVC アプリケーションの Entity Framework を使用した並べ替え、フィルター処理、ページング」を参照してください。

Fix It アプリでは、FixItTask エンティティ クラスを使用して、コントローラーとビューの間で情報を渡します。 ベスト プラクティスは、ビュー モデルを使用することです。 ドメイン モデル (FixItTask エンティティ クラスなど) は、データの永続化に必要なものを中心に設計されていますが、ビュー モデルはデータ表示用に設計できます。

Fix It アプリは、アップロードされた画像をパブリックとして格納します。つまり、URL を見つけたすべてのユーザーが画像にアクセスできます。 イメージはパブリックではなくセキュリティで保護できます。

キュー用の PowerShell オートメーション スクリプトがない

サンプルの PowerShell 自動化スクリプトは、完全にAzure App Service Web Appsで実行される Fix It の基本バージョンに対してのみ記述されました。 キューの処理に必要な Web アプリとクラウド サービス環境を設定してデプロイするためのスクリプトは提供されていません。

ユーザー入力での HTML コードの特別な処理

ASP.NET は、悪意のあるユーザーがユーザー入力テキスト ボックスにスクリプトを入力してクロスサイト スクリプティング攻撃を試みる可能性がある多くの方法を自動的に防止します。 また、タスクのタイトルとメモを表示するために使用される MVC DisplayFor ヘルパーは、ブラウザーに送信される値を HTML エンコードします。 ただし、運用アプリでは、追加の対策を講じたいと考える場合があります。 詳細については、「 ASP.NET での要求の検証」を参照してください。

ベスト プラクティス

次に、コード レビューと Fix It アプリの元のバージョンのテストで検出された後に修正されたいくつかの問題を示します。 一部の原因は、元のコード作成者が特定のベスト プラクティスを認識していないこと、コードが迅速に記述され、リリースされたソフトウェアを意図していなかったためです。 このレビューとテストから学んだことがあり、Web アプリを開発している他のユーザーに役立つ可能性がある場合に備えて、ここで問題を一覧表示します。

データベース リポジトリを破棄する

クラスは FixItTaskRepository Entity Framework DbContext インスタンスを破棄する必要があります。 これを行ったのは、 クラスで をFixItTaskRepository実装IDisposableすることです。

public class FixItTaskRepository : IFixItTaskRepository, IDisposable
{
    private MyFixItContext db = new MyFixItContext();

    // other code not shown

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Free managed resources.
            if (db != null)
            {
                db.Dispose();
                db = null;
            }
        }
    }
}

AutoFac ではインスタンスが自動的に破棄 FixItTaskRepository されるため、明示的に破棄する必要はありません。

もう 1 つのオプションは、 からFixItTaskRepositoryメンバー変数をDbContext削除し、代わりにステートメント内の各リポジトリ メソッド内にローカルDbContext変数をusing作成することです。 次に例を示します。

// Alternate way to dispose the DbContext
using (var db = new MyFixItContext())
{
    fixItTask = await db.FixItTasks.FindAsync(id);
}

DI にシングルトンを登録する

クラスとLoggerクラスのPhotoServiceインスタンスは 1 つだけ必要であるため、DependenciesConfig.cs依存関係の挿入のために、これらのクラスを単一インスタンスとして登録する必要があります。

builder.RegisterType<Logger>().As<ILogger>().SingleInstance();
builder.RegisterType<FixItTaskRepository>().As<IFixItTaskRepository>();
builder.RegisterType<PhotoService>().As<IPhotoService>().SingleInstance();

セキュリティ: ユーザーにエラーの詳細を表示しない

元の Fix It アプリには一般的なエラー ページがありませんでした。また、すべての例外を UI にバブル アップさせるだけなので、データベース接続エラーなどの一部の例外により、完全なスタック トレースがブラウザーに表示される可能性があります。 詳細なエラー情報は、悪意のあるユーザーによる攻撃を助ける場合があります。 解決策は、例外の詳細をログに記録し、エラーの詳細を含まないユーザーにエラー ページを表示することです。 Fix It アプリは既にログ記録されており、エラー ページを表示するために、Web.config ファイルに追加しました <customErrors mode=On>

<system.web>
  <customErrors mode="On"/>
  <authentication mode="None" />
  <compilation debug="true" targetFramework="4.5" />
  <httpRuntime targetFramework="4.5" />
</system.web>

既定では、エラーの Views\Shared\Error.cshtml が表示されます。 Error.cshtml をカスタマイズすることも、独自のエラー ページ ビューを作成して属性をdefaultRedirect追加することもできます。 特定のエラーに対して異なるエラー ページを指定することもできます。

セキュリティ: タスクの作成者による編集のみを許可します

[ダッシュボード インデックス] ページには、ログオンしているユーザーによって作成されたタスクのみが表示されますが、悪意のあるユーザーが別のユーザーのタスクの ID を持つ URL を作成する可能性があります。 その場合に 404 を返すコードを DashboardController.cs に追加しました。

public async Task<ActionResult> Edit(int id)
{
    FixItTask fixittask = await fixItRepository.FindTaskByIdAsync(id);
    if (fixittask == null)
    {
        return HttpNotFound();
    }

    // Verify logged in user owns this FixIt task.
    if (User.Identity.Name != fixittask.Owner)
    {
       return HttpNotFound();
    }

    return View(fixittask);
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(int id, [Bind(Include = "CreatedBy,Owner,Title,Notes,PhotoUrl,IsDone")]FormCollection form)
{
    FixItTask fixittask = await fixItRepository.FindTaskByIdAsync(id);

    // Verify logged in user owns this FixIt task.
    if (User.Identity.Name != fixittask.Owner)
    {
       return HttpNotFound();
    }

    if (TryUpdateModel(fixittask, form))
    {
        await fixItRepository.UpdateAsync(fixittask);
        return RedirectToAction("Index");
    }

    return View(fixittask);
}

例外を飲み込まない

元の Fix It アプリは、SQL クエリの結果として発生した例外をログに記録した後に null を返しました。

catch (Exception e)
{
    log.Error(e, "Error in FixItTaskRepository.FindTasksByOwnerAsync(userName={0})", userName);
    return null;
}

これにより、クエリが成功したが行が返されなかったかのようにユーザーに見えるようになります。 解決策は、キャッチしてログを記録した後に例外を再スローすることです。

catch (Exception e)
{
    log.Error(e, "Error in FixItTaskRepository.FindTasksByCreatorAsync(creater={0})", creator);
    throw;
}

worker ロールのすべての例外をキャッチする

ワーカー ロールで未処理の例外が発生すると、VM がリサイクルされるため、try-catch ブロックで行うすべての処理をラップし、すべての例外を処理する必要があります。

エンティティ クラスの文字列プロパティの長さを指定する

単純なコードを表示するために、Fix It アプリの元のバージョンでは FixItTask エンティティのフィールドの長さが指定されておらず、その結果、データベースで varchar(max) として定義されていました。 その結果、UI はほぼすべての量の入力を受け入れます。 長さを指定すると、Web ページのユーザー入力とデータベース内の列サイズの両方に適用される制限が設定されます。

public class FixItTask
{
    public int FixItTaskId  { get; set; }
    [StringLength(80)]
    public string CreatedBy { get; set; }
    [Required]
    [StringLength(80)]
    public string Owner { get; set; }
    [Required]
    [StringLength(80)]
    public string Title { get; set; }
    [StringLength(1000)]
    public string Notes { get; set; }
    [StringLength(200)]
    public string PhotoUrl { get; set; }
    public bool IsDone      { get; set; }  
}

プライベート メンバーに変更が予想されない場合は、読み取り専用としてマークする

たとえば、 クラスでは のDashboardControllerFixItTaskRepositoryインスタンスが作成され、変更されるとは限らないため、読み取り時に定義しました。

public class DashboardController : Controller
    {
        private readonly IFixItTaskRepository fixItRepository = null;

リストを使用します。リストの代わりに Any() を指定します。Count() > 0

リスト内の 1 つ以上の項目が指定した条件に適合するかどうかに注意する必要がある場合は、 条件 に適合する項目が見つかるとすぐに返されるため、Any メソッドを使用します。一方 Count 、メソッドは常にすべての項目を反復処理する必要があります。 ダッシュボード Index.cshtml ファイルには、最初に次のコードが含まれています。

@if (Model.Count() == 0) {
    <br />
    <div>You don't have anything currently assigned to you!!!</div>
}

これを次に変更しました。

@if (!Model.Any()) {
    <br />
    <div>You don't have anything currently assigned to you!!!</div>
}

MVC ヘルパーを使用して MVC ビューで URL を生成する

ホーム ページの [ 修正プログラムの作成 ] ボタンの場合、Fix It アプリはアンカー要素をハードコーディングしました。

<a href="/Tasks/Create" class="btn btn-primary btn-large">Create a New FixIt &raquo;</a>

このような表示/アクション リンクの場合は、 Url.Action HTML ヘルパーを使用することをお勧めします。次に例を示します。

@Url.Action("Create","Tasks")

ワーカー ロールで Thread.Sleep の代わりに Task.Delay を使用する

新しいプロジェクト テンプレートはワーカー ロールのサンプル コードを記述 Thread.Sleep しますが、スレッドがスリープ状態になると、スレッド プールで不要なスレッドが追加で生成される可能性があります。 これを回避するには、代わりに Task.Delay を 使用します。

while (true)
{
    try
    {
        await queueManager.ProcessMessagesAsync();
    }
    catch (Exception ex)
    {
        logger.Error(ex, "Exception in worker role Run loop.");
    }
    await Task.Delay(1000);
}

async void を避ける

非同期メソッドが値を返す必要がない場合は、 ではなくvoid型をTask返します。

この例は、 クラスの FixItQueueManager 例です。

// Correct
public async Task SendMessageAsync(FixItTask fixIt) { ... }

// Incorrect
public async void SendMessageAsync(FixItTask fixIt) { ... }

は、最上位のイベント ハンドラーにのみ使用 async void する必要があります。 メソッドを として async void定義した場合、呼び出し元はメソッドを 待機 することも、メソッドがスローする例外をキャッチすることもできません。 詳細については、「 非同期プログラミングのベスト プラクティス」を参照してください。

キャンセル トークンを使用して worker ロール ループから切り離す

通常、ワーカー ロールの Run メソッドには無限ループが含まれます。 worker ロールが停止すると、 RoleEntryPoint.OnStop メソッドが呼び出されます。 Run メソッド内で実行されている作業を取り消し、正常に終了するには、このメソッドを使用する必要があります。 そうしないと、操作の途中でプロセスが終了する可能性があります。

自動 MIME スニッフィング手順のオプトアウト

場合によっては、インターネット エクスプローラーは、Web サーバーで指定された種類とは異なる MIME の種類を報告します。 たとえば、インターネット エクスプローラーが HTTP 応答ヘッダー Content-Type: text/plain で配信されたファイル内の HTML コンテンツを見つけた場合、インターネット エクスプローラーはコンテンツを HTML としてレンダリングする必要があると判断します。 残念ながら、この "MIME スニッフィング" は、信頼されていないコンテンツをホストしているサーバーのセキュリティ上の問題につながる可能性もあります。 この問題に対処するために、インターネット エクスプローラー 8 では MIME タイプの決定コードに多くの変更が加えられており、アプリケーション開発者は MIME スニッフィングをオプトアウトできます。 次のコードが Web.config ファイルに追加されました。

<system.webServer>
     <httpProtocol>
        <customHeaders>
           <add name="X-Content-Type-Options" value="nosniff"/>
        </customHeaders>
     </httpProtocol>
     <modules>
      <remove name="FormsAuthenticationModule" />
    </modules>
  </system.webServer>

バンドルと縮小を有効にする

Visual Studio で新しい Web プロジェクトを作成する場合、JavaScript ファイルのバンドルと縮小は既定では有効になっていません。 BundleConfig.cs にコード行を追加しました。

// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                "~/Scripts/jquery-{version}.js"));
 
   // Code removed for brevity/
 
   BundleTable.EnableOptimizations = true;
}

認証 Cookie の有効期限のタイムアウトを設定する

既定では、認証 Cookie の有効期限は 2 週間です。 より短い時間の方が安全です。 この設定は 、StartupAuth.cs で変更できます。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    ExpireTimeSpan = System.TimeSpan.FromMinutes(20)
});

ローカル コンピューターで Visual Studio からアプリを実行する方法

Fix It アプリを実行するには、次の 2 つの方法があります。

  • 新しいタスクを SQL データベースに直接書き込む基本アプリケーションを実行します。
  • キューとバックエンド サービスを使用してアプリケーションを実行し、タスクを作成します。 キュー パターンについては、「 キュー中心の作業パターン」の章で説明されています。

基本アプリケーションを実行する

  1. Visual Studio 2017 をインストールします。
  2. Azure SDK for .NET for Visual Studio をインストールします
  3. MSDN コード ギャラリーから.zip ファイルをダウンロードします。
  4. エクスプローラーで、.zip ファイルを右クリックし、[プロパティ] をクリックし、プロパティ ウィンドウで [ブロックの解除] をクリックします。
  5. ファイルを解凍します。
  6. .sln ファイルをダブルクリックして Visual Studio を起動します。
  7. [ツール] メニューの [NuGet パッケージ マネージャー]、[パッケージ マネージャー コンソール] の順にクリックします。
  8. パッケージ マネージャー コンソール (PMC) で、[復元] をクリックします。
  9. Visual Studio を終了します。
  10. Azure Storage Emulator を起動します。
  11. Visual Studio を再起動し、前の手順で閉じたソリューション ファイルを開きます。
  12. FixIt プロジェクトがスタートアップ プロジェクトとして設定されていることを確認し、Ctrl キーを押しながら F5 キーを押してプロジェクトを実行します。

キュー処理を使用してアプリケーションを実行する

  1. 「基本アプリケーションを実行する」の指示に従って、ブラウザーを閉じて Visual Studio を閉じます。

  2. 管理者特権で Visual Studio を起動します。 (Azure Compute Emulator を使用します。これには管理者特権が必要です)。

  3. MyFixIt プロジェクト (Web プロジェクト) のアプリケーション Web.config ファイルで、 のappSettings/UseQueues値を "true" に変更します。

    <appSettings>
        <!-- Other settings not shown -->
        <add key="UseQueues" value="true"/>
    </appSettings>
    
  4. Azure Storage Emulator がまだ実行されていない場合は、もう一度起動します。

  5. FixIt Web プロジェクトと MyFixItCloudService プロジェクトを同時に実行します。

    Visual Studio を使用:

    1. F5 キーを押して FixIt プロジェクトを実行します。
    2. ソリューション エクスプローラーで MyFixItCloudService プロジェクトを右クリックし、[デバッグ>] [新しいインスタンスの開始] の順にクリックします。

    Visual Studio 2013 Express for Web の使用:

    1. ソリューション エクスプローラーで、FixIt ソリューションを右クリックし、 [プロパティ] を選択します

    2. [複数のスタートアップ プロジェクト] を選択します

    3. [ アクション ] ドロップダウン リストの [MyFixIt] と [MyFixItCloudService] で、[開始] を選択 します

    4. [OK] をクリックします。

    5. F5 キーを押して両方のプロジェクトを実行します。

      MyFixItCloudService プロジェクトを実行すると、Visual Studio によって Azure Compute Emulator が起動されます。 ファイアウォールの構成によっては、エミュレーターをファイアウォール経由で許可する必要がある場合があります。

Windows PowerShell スクリプトを使用してベース アプリをAzure App Service Web Appsにデプロイする方法

[すべて自動化] パターンを示すために、Fix It アプリには、Azure で環境を設定し、新しい環境にプロジェクトをデプロイするスクリプトが用意されています。 次の手順では、スクリプトの使用方法について説明します。

キューを使用せずに Azure で実行する場合、キューを使用してローカルで実行するように変更を行った場合は、次の手順に進む前に UseQueues appSetting の値を false に戻してください。

これらの手順では、Fix It ソリューションを既にローカルでダウンロードして実行しており、Azure アカウントを持っているか、管理する権限がある Azure サブスクリプションがあることを前提としています。

  1. Azure PowerShell コンソールをインストールします。 手順については、「 Azure PowerShell のインストールおよび構成方法」を参照してください。

    このカスタマイズされたコンソールは、Azure サブスクリプションで動作するように構成されています。 Azure モジュールは Program Files ディレクトリにインストールされ、Azure PowerShell コンソールを使用するたびに自動的にインポートされます。

    ISE のWindows PowerShellなど、別のホスト プログラムで作業する場合は、必ず Import-Module コマンドレットを使用して Azure モジュールをインポートするか、Azure モジュールのコマンドを使用してモジュールの自動インポートをトリガーしてください。

  2. [管理者として実行] オプションを使用してAzure PowerShellを開始します。

  3. Set-ExecutionPolicy コマンドレットを実行して、Azure PowerShell実行ポリシーを にRemoteSigned設定します。 ポリシーの変更を完了するには、 Y ([はい] に) と入力します。

    PS C:\> Set-ExecutionPolicy RemoteSigned
    

    この設定を使用すると、デジタル署名されていないローカル スクリプトを実行できます。 (実行ポリシーを に Unrestricted設定することもできます。これにより、後でブロックを解除する必要がなくなりますが、セキュリティ上の理由から推奨されません)。

  4. コマンドレットを Add-AzureAccount 実行して、アカウントの資格情報を使用して PowerShell を設定します。

    PS C:\> Add-AzureAccount
    

    これらの資格情報は一定期間後に期限切れになり、コマンドレットを再実行する Add-AzureAccount 必要があります。 この電子書籍が書かれているので、資格情報の有効期限が切れるまでの時間制限は 12 時間です。

  5. 複数のサブスクリプションがある場合は、Select-AzureSubscription コマンドレットを使用して、テスト環境を作成するサブスクリプションを指定します。

  6. コマンドレットと Import-AzurePublishSettingsFile コマンドレットを使用して、同じ Azure サブスクリプションの管理証明書をGet-AzurePublishSettingsFileインポートします。 これらのコマンドレットの 1 つ目は証明書ファイルをダウンロードし、2 番目のコマンドレットでは、そのファイルをインポートするためにそのファイルの場所を指定します。 > [!重要]

    ダウンロードしたファイルは安全な場所に保管するか、Azure サービスの管理に使用できる証明書が含まれているため、ファイルの使用が完了したら削除します。

    PS C:\Users\username\Documents\Visual Studio 2013\Projects\MyFixIt\Automation> Get-AzurePublishSettingsFile
    PS C:\Users\username\Documents\Visual Studio 2013\Projects\MyFixIt\Automation> Import-AzurePublishSettingsFile "C:\Users
    \username\Downloads\Azure MSDN - Visual Studio Ultimate-12-14-2013-credentials.publishsettings"
    

    証明書は、SQL Database サーバーにファイアウォール規則を設定するために、開発用コンピューターの IP アドレスを検出する REST API 呼び出しに使用されます。

  7. Set-Location コマンドレット (エイリアスは cdchdir、および sl) を実行して、スクリプトを含むディレクトリに移動します。 (これらは、Fix It ソリューション フォルダーの Automation フォルダーにあります)。いずれかのディレクトリ名にスペースが含まれている場合は、パスを引用符で囲みます。 たとえば、ディレクトリに移動するには c:\Sample Apps\FixIt\Automation 、次のコマンドを入力します。

    PS C:\> cd "c:\Sample Apps\MyFixIt\Automation"
    
  8. Windows PowerShellでこれらのスクリプトを実行できるようにするには、Unblock-File コマンドレットを使用します。 (スクリプトはインターネットからダウンロードされたためブロックされます)。

    警告

    セキュリティ - スクリプトまたは実行可能ファイルで実行 Unblock-File する前に、メモ帳でファイルを開き、コマンドを調べて、悪意のあるコードが含まれていないことを確認します。

    たとえば、次のコマンドは、現在の Unblock-File ディレクトリ内のすべてのスクリプトで コマンドレットを実行します。

    PS C:\Sample Apps\FixIt\Automation> Unblock-File -Path .\*.ps1
    
  9. ベース (キュー処理なし) 用の Web アプリを作成するには、環境作成スクリプトを実行します。

    必須 Name パラメーターは、データベースの名前を指定し、スクリプトによって作成されるストレージ アカウントにも使用されます。 名前は、azurewebsites.net ドメイン内でグローバルに一意である必要があります。 Fixit や Test など、一意ではない名前を指定した場合 (または例のように fixitdemo の場合でも) New-AzureWebsite 、コマンドレットは競合を報告する内部エラーで失敗します。 スクリプトは、Web アプリ、ストレージ アカウント、データベースの名前要件に準拠するために、名前を小文字に変換します。

    必須SqlDatabasePasswordパラメーターは、SQL Database用に作成される管理者アカウントのパスワードを指定します。 パスワード (&<> ;)に特殊な XML 文字を含めないでください。 これは、スクリプトの記述方法の制限であり、Azure の制限ではありません。

    たとえば、"fixitdemo" という名前の Web アプリを作成し、SQL Server管理者パスワード "Passw0rd1" を使用する場合は、次のコマンドを入力できます。

    PS C:\Sample Apps\FixIt\Automation> .\New-AzureWebsiteEnv.ps1 -Name 
    fixitdemo <required params here>
    

    名前は azurewebsites.net ドメインで一意である必要があり、パスワードはパスワードの複雑さの要件SQL Database満たしている必要があります。 (例 Passw0rd1 は要件を満たしています)。

    コマンドは "." で始まる点に注意してください。 スクリプトの悪意のある実行を防ぐために、Windows PowerShellスクリプトの実行時にスクリプト ファイルへの完全修飾パスを指定する必要があります。 ドットを使用して現在のディレクトリ (".") を示すか、次のような完全修飾パスを指定できます。

    PS C:\Temp\FixIt\Automation> C:\Temp\FixIt\Automation\New-AzureWebsiteEnv.ps1 -Name fixitdemo -SqlDatabasePassword Pas$w0rd
    

    スクリプトの詳細については、 コマンドレットを使用します Get-Help

    PS C:\Sample Apps\FixIt\Automation> Get-Help -Full .\New-AzureWebsiteEnv.ps1
    

    Get-Help コマンドレットの 、FullParameters、および Examples パラメーターを使用Detailedして、返されるヘルプをフィルター処理できます。

    スクリプトが失敗するか、"New-AzureWebsite : Call Set-AzureSubscription and Select-AzureSubscription first" などのエラーが生成された場合、Azure PowerShellの構成が完了していない可能性があります。

    スクリプトが完了したら、Azure 管理ポータルを使用して、作成されたリソースを確認できます (「 すべてを自動化 する」の章を参照)。

  10. FixIt プロジェクトを新しい Azure 環境にデプロイするには、 AzureWebsite.ps1 スクリプトを使用します。 次に例を示します。

    PS C:\Sample Apps\FixIt\Automation> .\Publish-AzureWebsite.ps1 ..\MyFixIt\MyFixIt.csproj -Launch
    

    デプロイが完了すると、ブラウザーが開き、Azure で Fix It が実行されます。

Windows PowerShell スクリプトのトラブルシューティング

これらのスクリプトの実行時に発生する最も一般的なエラーは、アクセス許可に関連しています。 と Import-AzurePublishSettingsFileAdd-AzureAccount成功し、同じ Azure サブスクリプションに使用したことを確認します。 成功した場合 Add-AzureAccount でも、もう一度実行する必要がある場合があります。 によって追加された Add-AzureAccount アクセス許可は、12 時間以内に期限切れになります。

オブジェクト参照がオブジェクト インスタンスに設定されていません。

スクリプトから "オブジェクト参照がオブジェクトのインスタンスに設定されていません" などのエラーが返される場合は、処理するオブジェクト Windows PowerShellが見つからない (これは null 参照例外です) ことを意味します。これは、コマンドレットをAdd-AzureAccount実行して、スクリプトをもう一度試します。

New-AzureSqlDatabaseServer : Object reference not set to an instance of an object.
At C:\ps-test\azure-powershell-samples-master\WebSite\create-azure-sql.ps1:80 char:19
+ $databaseServer = New-AzureSqlDatabaseServer -AdministratorLogin $UserName -Admi ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [New-AzureSqlDatabaseServer], NullReferenceException
    + FullyQualifiedErrorId : 
Microsoft.WindowsAzure.Commands.SqlDatabase.Server.Cmdlet.NewAzureSqlDatabaseServer

InternalError: サーバーで内部エラーが発生しました。

コマンドレットは New-AzureWebsite 、名前が azurewebsites.net ドメインで一意でない場合に内部エラーを返します。 エラーを解決するには、 の Name パラメーターにある名前に別の値 New-AzureWebsiteEnv.ps1使用します。

New-AzureWebsite : InternalError: The server encountered an internal error. 
Please retry the request.
At line:1 char:1
+ New-AzureWebsite -Name fixitdemo
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          
: CloseError: (:) [New-AzureWebsite], Exception
+ FullyQualifiedErrorId : 
Microsoft.WindowsAzure.Commands.Websites.NewAzureWebsiteCommand

スクリプトを再起動する

"スクリプトが完了しました" というメッセージが表示される前に失敗したために New-AzureWebsiteEnv.ps1 スクリプトを再起動する必要がある場合は、スクリプトが停止する前に作成したリソースを削除することをお勧めしています。 たとえば、スクリプトによって ContosoFixItDemo Web アプリが既に作成されていて、同じ名前でスクリプトを再度実行した場合、名前が使用されているため、スクリプトは失敗します。

スクリプトが停止する前に作成したリソースを確認するには、次のコマンドレットを使用します。

  • Get-AzureWebsite
  • Get-AzureSqlDatabaseServer
  • Get-AzureSqlDatabase: このコマンドレットを実行するには、データベース サーバー名を に Get-AzureSqlDatabaseパイプします。 Get-AzureSqlDatabaseServer | Get-AzureSqlDatabase.

これらのリソースを削除するには、次のコマンドを使用します。 データベース サーバーを削除すると、サーバーに関連付けられているデータベースが自動的に削除されることに注意してください。

  • Get-AzureWebsite -Name <WebsiteName> | Remove-AzureWebsite
  • Get-AzureSqlDatabase -Name <DatabaseName> -ServerName <DatabaseServerName> | Remove-SqlAzureDatabase
  • Get-AzureSqlDatabaseServer | Remove-AzureSqlDatabaseServer

キュー処理を使用してアプリを Azure App Service Web Apps と Azure Cloud Service にデプロイする方法

キューを有効にするには、MyFixIt\Web.config ファイルで次の変更を行います。 で appSettings、 の UseQueues 値を "true" に変更します。

<appSettings>
    <!-- Other settings not shown -->
    <add key="UseQueues" value="true"/>
</appSettings>

次に、前述のように、mvc アプリケーションを Azure App Service の Web アプリデプロイします。

次に、新しい Azure クラウド サービスを作成します。 Fix It アプリに含まれているスクリプトでは、クラウド サービスは作成またはデプロイされないため、これにはAzure portalを使用する必要があります。 ポータルで、[ 新しい -- コンピューティングクラウド サービス -- のクイック作成] をクリックし、URL とデータ センターの場所を入力します。 Web アプリをデプロイしたのと同じデータ センターを使用します。

Azure Cloud Service Portal と、新しい Azure クラウド サービス プロジェクトを作成するための利用可能な選択項目を含む複数のタブを示す図

クラウド サービスをデプロイする前に、一部の構成ファイルを更新する必要があります。

MyFixIt.WorkerRole\app.configの でconnectionStrings、接続文字列の値をappdb、SQL Databaseの実際の接続文字列に置き換えます。 接続文字列はポータルから取得できます。 ポータルで、ADO .Net、ODBC、PHP、JDBC の接続文字列SQL Database SQLDatabases - appdb - ビューをクリックします。 ADO.NET 接続文字列をコピーし、値を app.config ファイルに貼り付けます。 "{your_password_here}" をデータベース パスワードに置き換えます。 (スクリプトを使用して MVC アプリをデプロイした場合、スクリプト パラメーターにデータベース パスワードを SqlDatabasePassword 指定したとします)。

結果は次のようになります。

<add name="appdb" connectionString="Server=tcp:####.database.windows.net,1433;Database=appdb;User ID=####;Password=####;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;" providerName="System.Data.SqlClient" />

同じMyFixIt.WorkerRole\app.config ファイルの の下で appSettings、Azure ストレージ アカウントの 2 つのプレースホルダー値を置き換えます。

<appSettings>
  <add key="StorageAccountName" value="{StorageAccountName}" />
  <add key="StorageAccountAccessKey" value="{StorageAccountAccessKey}" />
</appSettings>

ポータルからアクセス キーを取得できます。 「ストレージ アカウントを管理する方法」を参照してください。

MyFixItCloudService\ServiceConfiguration.Cloud.cscfg で、Azure ストレージ アカウントの同じ 2 つのプレースホルダー値を置き換えます。

<ConfigurationSettings>
    <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" 
             value="DefaultEndpointsProtocol=https;AccountName={StorageAccountName};AccountKey={StorageAccountAccessKey}" />
  </ConfigurationSettings>

これで、クラウド サービスをデプロイする準備ができました。 [ソリューションの探索] で、MyFixItCloudService プロジェクトを右クリックし、[発行] を選択 します。 詳細については、「アプリケーションを Azure にデプロイする」を参照してください。 これは、このチュートリアルのパート 2 に含まれています。