アプリ サービスの作成と利用

重要

このトピックのコード リストは C# のみです。 C++/WinRTおよび C# の App Service サンプル アプリについては、App Service サンプル アプリに関するページを参照してください

アプリ サービスは、他の UWP アプリにサービスを提供する UWP アプリです。 これは、デバイス上にある Web サービスのようなものです。 アプリ サービスは、バック グラウンド タスクとしてホスト アプリで実行され、そのサービスを他のアプリに提供することができます。 たとえば、アプリ サービスによって、他のアプリで使用できるバー コード スキャナー サービスが提供される場合があります。 また、アプリのエンタープライズ スイートに共通のスペル チェック アプリ サービスを備えておき、そのサービスを同じスイート内の他のアプリから利用可能にする場合もあるでしょう。 アプリ サービスでは、同じデバイス上のアプリから呼び出せる UI を持たないサービスを作成できます。また、Windows 10 バージョン 1607 以降では、リモート デバイスからも呼び出せます。

Windows 10 バージョン 1607 以降では、ホスト アプリと同じプロセスで実行されるアプリ サービスを作成できます。 この記事では、別のバックグラウンド プロセスで実行されるアプリ サービスの作成と利用に重点を置いて説明します。 プロバイダーと同じプロセスでアプリ サービスを実行する詳細については、「ホスト アプリと同じプロセスで実行するようにアプリ サービスを変換する」をご覧ください。

新しいアプリ サービス プロバイダー プロジェクトの作成

このトピックでは、わかりやすくするためにすべてを 1 つのソリューションで作成します。

  1. 2015 Visual Studio以降では、新しい UWP アプリ プロジェクトを作成し、AppServiceProvider という名前を付きます

    1. [File New > Project...] を選択します。
    2. [新しいプロジェクトの作成] ダイアログボックスで、空のアプリ (ユニバーサル Windows) C# を選択します。 これは、他の UWP アプリがアプリ サービスを利用できるアプリとなります。
    3. [ 次へ] をクリックし、プロジェクトに AppServiceProviderという名前を付け、その場所を選択して、[作成] を クリックします
  2. プロジェクトの [ターゲット] と[最小]バージョンの選択を求めるメッセージが表示された場合は、少なくとも10.0.14393 を選択します。 新しいSupportsMultipleInstances属性を使用する場合は、Visual Studio 2017 または Visual Studio 2019 を使用し、10.0.15063 (Windows 10 Creators Update) 以上をターゲットとする必要があります。

App Service 拡張機能を Package.appxmanifest に追加する

AppServiceProvider プロジェクトで、テキスト エディターで Package.appxmanifestファイルを開きます。

  1. 次のファイルで右クリックソリューション エクスプローラー。
  2. [Open With]を選択します
  3. [XML (テキスト) エディター] を選択します。

要素内に次 AppService の拡張機能を追加 <Application> します。 この例では、com.microsoft.inventory サービスをアドバタイズし、このアプリをアプリ サービス プロバイダーとして識別します。 実際のサービスは、バックグラウンド タスクとして実装されます。 アプリ サービスのプロジェクトは、サービスを他のアプリに公開します。 サービス名には逆のドメイン名スタイルを使うことをお勧めします。

xmlns:uap4 名前空間のプレフィックスと uap4:SupportsMultipleInstances 属性は、Windows SDK バージョン 10.0.15063 以降をターゲットとしている場合のみ有効です。 以前のバージョンの SDK をターゲットとしている場合には、それらは安全に削除できます。

Note

C++/WinRTおよび C# の App Service サンプル アプリについては、App Service サンプル アプリに関するページを参照してください

<Package
    ...
    xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
    xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
    ...
    <Applications>
        <Application Id="AppServiceProvider.App"
          Executable="$targetnametoken$.exe"
          EntryPoint="AppServiceProvider.App">
          ...
          <Extensions>
            <uap:Extension Category="windows.appService" EntryPoint="MyAppService.Inventory">
              <uap3:AppService Name="com.microsoft.inventory" uap4:SupportsMultipleInstances="true"/>
            </uap:Extension>
          </Extensions>
          ...
        </Application>
    </Applications>

属性 Category は、このアプリケーションをアプリ サービス プロバイダーとして識別します。

属性 EntryPoint は、次に実装するサービスを実装する名前空間修飾クラスを識別します。

属性 SupportsMultipleInstances は、App Service が呼び出されるたび、新しいプロセスで実行する必要がある場合に示します。 これは必要ありませんが、その機能が必要で、10.0.15063 SDK (Windows 10 Creators Update) 以上を対象とする場合は使用できます。 また、先頭に uap4 名前空間を付ける必要があります。

アプリ サービスの作成

  1. アプリ サービスは、バックグラウンド タスクとして実装できます。 これにより、フォアグラウンド アプリケーションは、別のアプリケーションのアプリ サービスを呼び出すことができます。 バックグラウンド タスクとしてアプリ サービスを作成するには>という名前の新しい Windows ランタイム コンポーネント プロジェクトをソリューション ([ファイル追加] [新しいProject ) に追加します。> [新しいコンポーネントの追加Project]ダイアログ ボックスで、[ インストール済み Visual C# Windows ランタイム コンポーネント (ユニバーサル Windows) を選択します

  2. AppServiceProviderプロジェクトで、新しいMyAppServiceプロジェクトへのプロジェクト間参照を追加します (ソリューション エクスプローラー で、AppServiceProviderプロジェクトの参照プロジェクトの追加ソリューションを右クリックし、MyAppServiceOKを選択します)。 参照を追加しない場合でも、アプリ サービスは実行時に接続されないため、この手順は重要です。

  3. MyAppService プロジェクトで、Class1.csの一番上に次の using ステートメントを追加します。

    using Windows.ApplicationModel.AppService;
    using Windows.ApplicationModel.Background;
    using Windows.Foundation.Collections;
    
  4. Class1.cs名前を Inventory.csに変更し、Class1のスタブ コードを Inventory という名前の新しいバックグラウンド タスク クラスに置き換えます

    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };
    
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();
    
            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;
    
            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }
    
        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // This function is called when the app service receives a request.
        }
    
        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
    

    このクラスは、アプリ サービスが作業を実行する場所です。

    バックグラウンド タスクが作成されると、実行が呼び出されます。 バックグラウンド タスクは Run が完了すると終了するため、バックグラウンド タスクが要求に引き続き対応できるように、コードは保留されます。 バックグラウンド タスクとして実装されたアプリ サービスは、呼び出しを受け取った後、約 30 秒間に再度呼び出されない限り、または保留されない限り、約 30 秒間有効になっています。アプリ サービスが同じプロセスで呼び出し元として実装されると、アプリ サービスの有効期間は呼び出し元の有効期間に関連付けられます。

    アプリ サービスの有効期間は、呼び出し元に依存します。

    • 呼び出し元がフォアグラウンドにある場合、App Service の有効期間は呼び出し元と同じです。
    • 呼び出し元がバックグラウンドにある場合、アプリ サービスの実行は 30 秒になります。 保留されると、1 回 5 秒追加されます。

    OnTaskCanceled は 、タスクが取り消された場合に呼び出されます。 タスクは、クライアント アプリが AppServiceConnectionを破棄した場合、クライアント アプリが中断された場合、OS がシャットダウンまたはスリープ状態の場合、またはタスクを実行するために OS のリソースが不足している場合に取り消されます。

アプリ サービスのコードを記述する

OnRequestReceived は、App Service のコードが行く場所です。 MyAppServiceInventory.csのスタブOnRequestReceivedを、この例のコードに置き換えます。 このコードは、インベントリの項目のインデックスを取得し、コマンド文字列と共にサービスに渡して、指定したインベントリ項目の名前と価格を取得します。 独自のプロジェクトには、エラー処理コードを追加します。

private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
    // Get a deferral because we use an awaitable API below to respond to the message
    // and we don't want this call to get canceled while we are waiting.
    var messageDeferral = args.GetDeferral();

    ValueSet message = args.Request.Message;
    ValueSet returnData = new ValueSet();

    string command = message["Command"] as string;
    int? inventoryIndex = message["ID"] as int?;

    if (inventoryIndex.HasValue &&
        inventoryIndex.Value >= 0 &&
        inventoryIndex.Value < inventoryItems.GetLength(0))
    {
        switch (command)
        {
            case "Price":
            {
                returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            case "Item":
            {
                returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            default:
            {
                returnData.Add("Status", "Fail: unknown command");
                break;
            }
        }
    }
    else
    {
        returnData.Add("Status", "Fail: Index out of range");
    }

    try
    {
        // Return the data to the caller.
        await args.Request.SendResponseAsync(returnData);
    }
    catch (Exception e)
    {
        // Your exception handling code here.
    }
    finally
    {
        // Complete the deferral so that the platform knows that we're done responding to the app service call.
        // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
        messageDeferral.Complete();
    }
}

この例ではSendResponseAsyncを待ち受けできるメソッド呼び出しを行うので、OnRequestReceivedは非同期です。

サービスがOnRequestReceivedハンドラーで非同期メソッドを使用できるよう、遅延が発生します。 これにより、メッセージの処理が 完了するまで、OnRequestReceived の呼び出しが完了しなくなっていることを確認します。 SendResponseAsync が結果を呼び出し元に送ります。 SendResponseAsync は、呼び出しの完了時に通知しません。 OnRequestReceived が完了したことを SendMessageAsync に通知するのは、保留の完了時です。 SendResponseAsyncの呼び出しは try/finally ブロックにラップされます。SendResponseAsyncが例外をスローした場合でも遅延を完了する必要があります。

App Services では 、ValueSet オブジェクトを 使用して情報を交換します。 渡すことができるデータのサイズは、システム リソースによってのみ制限されます。 ValueSet で使うことができる定義済みのキーはありません。 アプリ サービスのプロトコルの定義に使うキーの値を決定する必要があります。 呼び出し元は、そのプロトコルを念頭に置いて記述する必要があります。 この例では、アプリ サービスがインベントリ項目またはその価格の名前を提供するかどうかを示す値を持つ、Command という名前のキーを選びました。 インベントリ名のインデックスは、ID キーに保存されています。 戻り値は Result キーに保存されます。

AppServiceClosedStatus 列挙体が呼び出し元に返され、アプリ サービスの呼び出した成功したか失敗したかを示します。 アプリ サービスへの呼び出しが失敗する例として、OS がサービスのエンドポイントを中止した、リソースが超過したなどがあります。 ValueSet を通じて、さらにエラー情報を取得することができます。 この例では、Status という名前のキーを使って、より詳細なエラー情報を呼び出し元に返します。

SendResponseAsync の呼び出しからは、ValueSet が呼び出し元に返されます。

サービス アプリを展開して、パッケージ ファミリ名を取得する

クライアントから呼び出す前に、アプリ サービス プロバイダーをデプロイする必要があります。 デプロイするには、 [ソリューションのビルド] [ソリューション の配置]を選択Visual Studio。

また、アプリ サービス プロバイダーを呼び出すには、パッケージ ファミリ名も必要です。 これは、デザイナー ビューで AppServiceProvider プロジェクトの Package.appxmanifest ファイルを開いて取得できます (ソリューション エクスプローラー で ダブルクリックします)。 [パッケージ化] タブを選択し、[パッケージ ファミリ名] の横の値をコピーし、現在は [パッケージ] メモ帳貼り付けます。

アプリ サービスを呼び出すクライアントを作成する

  1. [ファイル] [追加] > [新しいプロジェクト]で、新しい空の Windows ユニバーサル アプリ プロジェクトをソリューションに追加します。 [新しいアプリの追加Project]ダイアログ ボックスで、[インストール済み Visual C# 空のアプリ (ユニバーサル Windows)を選択し、ClientApp という名前を付きます

  2. ClientApp プロジェクトで、次のusingステートメントをMainPage.xaml.cs の上部に追加します

    using Windows.ApplicationModel.AppService;
    
  3. textBox というテキスト ボックスと ボタンをMainPage.xaml に追加します

  4. と呼ばれるボタンのボタン クリック ハンドラーを button_Clickし、ボタン ハンドラーのシグネチャに キーワード async を追加します。

  5. ボタンのクリック ハンドラーのスタブを、次のコードで置き換えます。 必ず、inventoryService フィールドの宣言を含めます。

    private AppServiceConnection inventoryService;
    
    private async void button_Click(object sender, RoutedEventArgs e)
    {
       // Add the connection.
       if (this.inventoryService == null)
       {
           this.inventoryService = new AppServiceConnection();
    
           // Here, we use the app service name defined in the app service 
           // provider's Package.appxmanifest file in the <Extension> section.
           this.inventoryService.AppServiceName = "com.microsoft.inventory";
    
           // Use Windows.ApplicationModel.Package.Current.Id.FamilyName 
           // within the app service provider to get this value.
           this.inventoryService.PackageFamilyName = "Replace with the package family name";
    
           var status = await this.inventoryService.OpenAsync();
    
           if (status != AppServiceConnectionStatus.Success)
           {
               textBox.Text= "Failed to connect";
               this.inventoryService = null;
               return;
           }
       }
    
       // Call the service.
       int idx = int.Parse(textBox.Text);
       var message = new ValueSet();
       message.Add("Command", "Item");
       message.Add("ID", idx);
       AppServiceResponse response = await this.inventoryService.SendMessageAsync(message);
       string result = "";
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data  that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result = response.Message["Result"] as string;
           }
       }
    
       message.Clear();
       message.Add("Command", "Price");
       message.Add("ID", idx);
       response = await this.inventoryService.SendMessageAsync(message);
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result += " : Price = " + response.Message["Result"] as string;
           }
       }
    
       textBox.Text = result;
    }
    

    this.inventoryService.PackageFamilyName = "Replace with the package family name"; のパッケージ ファミリ名を、「サービス アプリを展開して、パッケージ ファミリ名を取得する」で得た this.inventoryService.PackageFamilyName = "Replace with the package family name"; プロジェクトのパッケージ ファミリ名に置き換えます。

    Note

    変数に格納するのではなく、必ず文字列リテラルを貼り付けます。 変数を使用した場合は機能しません。

    最初に、コードによってアプリ サービスとの接続が確立されます。 接続は、this.inventoryService を破棄するまで開いたままになります。 App Service 名は AppServiceNameAppService プロジェクトの Name ファイルに追加した要素の属性と一致する必要があります。 この例では <uap3:AppService Name="com.microsoft.inventory"/> です。

    という 名前の ValueSet が作成され、アプリ サービスに送信するコマンドを指定します。 この例のアプリ サービスでは、2 つのアクションのどちらを実行するかをコマンドが示すことを想定しています。 クライアント アプリのテキスト ボックスからインデックスを取得し、 コマンドを使用してサービスを呼び出して、項目の説明 Item を取得します。 その後、Price コマンドで呼び出しを行い、項目の価格を取得します。 ボタンのテキストは結果に設定されています。

    オペレーティング システムがアプリ サービスに呼び出しを接続できたかどうかを示すのは AppServiceResponseStatus のみです。このため、アプリ サービスが要求を満たすことができたことを確認するために、アプリ サービスから受け取る ValueSet キーをチェックします。

  6. ClientApp プロジェクトをスタートアップ プロジェクトに設定し (ソリューション エクスプローラー [スタートアップ プロジェクトに設定] で右クリックしProject を実行します。 数値 1 をテキスト ボックスに入力し、ボタンをクリックします。 サービスから "Chair : Price = 88.99" が返されます。

    Chair : price = 88.99 を表示するサンプル アプリ

App Service の呼び出しが失敗した場合は 、ClientApp プロジェクトで次を確認します。

  1. インベントリ サービス接続に割り当てられているパッケージ ファミリ名が 、AppServiceProvider アプリのパッケージ ファミリ名と一致する必要があります。 を使用して、button_Click 参照してください
  2. button_Click、インベントリ サービス接続に割り当てられているアプリ サービス名が 、AppServiceProviderPackage.appxmanifest ファイル内の App Service 名と一致する必要があります。 this.inventoryService.AppServiceName = "com.microsoft.inventory"; をご覧ください。
  3. AppServiceProvider アプリがデプロイされている必要があります。 ( 次のソリューション エクスプローラーソリューションを右クリックし、 [ソリューションの配置] を選択します

アプリ サービスのデバッグ

  1. サービスを呼び出す前にアプリ サービス プロバイダーのアプリが配置される必要があるため、ソリューションがデバッグする前に展開されるようにします。 (Visual Studio で、[ビルド] [ソリューションの配置] の順にクリックします)。
  2. 次の ソリューション エクスプローラーAppServiceProvider プロジェクトを右クリックし、 [プロパティ] を 選択します[デバッグ] タブで、[開始動作][起動しないが、開始時にマイ コードをデバッグする] に変更します。 (C++ を使ってアプリ サービス プロバイダーを実装した場合、[デバッグ] タブから [アプリケーションの起動][いいえ] に変更します)。
  3. MyAppService プロジェクトのInventory.csファイルで、OnRequestReceived にブレークポイントを設定します
  4. AppServiceProvider プロジェクトをスタートアップ プロジェクトに設定し、F5 キーを押します
  5. クライアントから ClientAppを起動スタート メニュー (クライアント アプリからVisual Studio)。
  6. 数値 1 をテキスト ボックスに入力し、ボタンを押します。 デバッガーは、アプリ サービス内のブレークポイントでアプリ サービスの呼び出しを停止します。

クライアントのデバッグ

  1. 前の手順に従って、アプリ サービスを呼び出すクライアントをデバッグします。
  2. クライアントアプリから ClientAppを起動スタート メニュー。
  3. デバッガーをプロセス (ClientApp.exe プロセスではなく) に ApplicationFrameHost.exe します。 (Visual Studio で、[デバッグ] [プロセスにアタッチ] の順に選びます)。
  4. ClientApp プロジェクトで、 にブレークポイントを設定button_Click。
  5. ClientApp のテキスト ボックスに数字 1 を入力してボタンをクリックすると、クライアントと App Service の両方のブレークポイントにヒットします。

一般的なアプリ サービスのトラブルシューティング

App Service に接続 しようとして AppUnavailable 状態が発生した場合は、次を確認します。

  • アプリ サービス プロバイダー プロジェクトとアプリ サービス プロジェクトが展開されていることを確認します。 クライアントを実行する前に、両方が展開されている必要があります。展開されていない場合、クライアントには接続先がありません。 Visual Studio から [ビルド][ソリューションの配置] で展開できます。
  • 次の ソリューション エクスプローラーアプリ サービス プロバイダー プロジェクトに、App Service を実装するプロジェクトへのプロジェクト間参照が含まれる必要があります。
  • 「App Service 拡張機能を Package.appxmanifest に追加する」で指定したように、エントリとその子要素が、App Service プロバイダー プロジェクトに属する <Extensions><Extensions>ファイルに追加されています。
  • App Service プロバイダーを呼び出すクライアントの AppServiceConnection.AppServiceName 文字列が、アプリ サービス プロバイダー プロジェクトの Package.appxmanifest ファイルで指定された と一致する必要があります。
  • AppServiceConnection.PackageFamilyName が、「App Service拡張機能をPackage.appxmanifestに追加する」で指定した App Service プロバイダー コンポーネントのパッケージ ファミリ名と一致するようにします
  • この例のようなアウトプロセス アプリ サービスの場合は、アプリ サービス プロバイダー プロジェクトの EntryPoint<uap:Extension ...>EntryPoint ファイルの 要素で指定された が、App Service プロジェクトで <uap:Extension ...> を実装するパブリック クラスの名前空間とクラス名と一致する必要があります。

デバッグのトラブルシューティング

アプリ サービス プロバイダーまたはアプリ サービス プロジェクトのブレークポイントでデバッガーが停止しない場合は、以下を確認します。

  • アプリ サービス プロバイダー プロジェクトとアプリ サービス プロジェクトが展開されていることを確認します。 クライアントを実行する前に、両方が展開されている必要があります。 Visual Studio から [ビルド][ソリューションの配置] で展開できます。
  • デバッグするプロジェクトがスタートアップ プロジェクトとして設定され 、F5 キーが押された場合、そのプロジェクトのデバッグ プロパティがプロジェクトを実行しない設定に設定されている必要があります。 プロジェクトを右クリックし、[プロパティ][デバッグ] (または C++ では [デバッグ]) の順にクリックします。 C# では、[開始動作][起動しないが、開始時にマイ コードをデバッグする] に設定します。 C++ では、[アプリケーションの起動][いいえ] に設定します。

注釈

この例では、バックグラウンド タスクとして実行されるアプリ サービスを作成して、それを別のアプリから呼び出す概要を示しています。 重要な点は次のとおりです。

  • アプリ サービスをホストするバックグラウンド タスクを作成します。
  • 拡張機能を windows.appService アプリ サービス プロバイダーの windows.appService します。
  • クライアント アプリから接続できるよう、アプリ サービス プロバイダーのパッケージ ファミリ名を取得します。
  • App Service プロバイダー プロジェクトから App Service プロジェクトにプロジェクト間参照を追加します。
  • [Windows] を使用します。サービスを呼び出す ApplicationModel.AppService.AppServiceConnection。

MyAppService の完全なコード

using System;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;

namespace MyAppService
{
    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();

            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;

            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }

        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // Get a deferral because we use an awaitable API below to respond to the message
            // and we don't want this call to get canceled while we are waiting.
            var messageDeferral = args.GetDeferral();

            ValueSet message = args.Request.Message;
            ValueSet returnData = new ValueSet();

            string command = message["Command"] as string;
            int? inventoryIndex = message["ID"] as int?;

            if (inventoryIndex.HasValue &&
                 inventoryIndex.Value >= 0 &&
                 inventoryIndex.Value < inventoryItems.GetLength(0))
            {
                switch (command)
                {
                    case "Price":
                        {
                            returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    case "Item":
                        {
                            returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    default:
                        {
                            returnData.Add("Status", "Fail: unknown command");
                            break;
                        }
                }
            }
            else
            {
                returnData.Add("Status", "Fail: Index out of range");
            }

            // Return the data to the caller.
            await args.Request.SendResponseAsync(returnData);

            // Complete the deferral so that the platform knows that we're done responding to the app service call.
            // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
            messageDeferral.Complete();
        }


        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
}