Créer et utiliser un service d’application

Important

Les listes de code de cette rubrique sont C# uniquement. Pour obtenir un exemple d’application App Service en C++/WinRT et C#, consultez l’exemple d’application App Service.

Les services d’application sont des applications UWP qui fournissent des services à d’autres applications UWP. Ils sont analogues aux services web, sur un appareil. Un service d’application s’exécute sous forme de tâche en arrière-plan dans l’application hôte et peut fournir son service à d’autres applications. Par exemple, un service d’application peut fournir un service de scanneur de code-barres que d’autres applications peuvent utiliser. Ou peut-être qu’une suite d’applications Enterprise dispose d’un service commun de vérification orthographique accessible aux autres applications de la suite. Les services d’application vous permettent de créer des services sans interface utilisateur que les applications peuvent appeler sur le même appareil et à partir de Windows 10, version 1607, sur des appareils distants.

À compter de Windows 10, version 1607, vous pouvez créer des services d’application qui s’exécutent dans le même processus que l’application hôte. Cet article se concentre sur la création et la consommation d’un service d’application qui s’exécute dans un processus en arrière-plan distinct. Pour plus d’informations sur l’exécution d’un service d’application, consultez Convertir un service d’application pour qu’il s’exécute dans le même processus que le fournisseur.

Créer un projet de fournisseur app service

Dans ce guide pratique, nous allons créer tout dans une solution pour simplifier.

  1. Dans Visual Studio 2015 ou version ultérieure, créez un projet d’application UWP et nommez-le AppServiceProvider.

    1. Sélectionnez Nouveau > projet de fichier>...
    2. Dans la boîte de dialogue Créer un projet , sélectionnez Application vide (Windows universel) C#. Il s’agit de l’application qui rend le service d’application disponible pour d’autres applications UWP.
    3. Cliquez sur Suivant, puis nommez le projet AppServiceProvider, choisissez un emplacement pour celui-ci, puis cliquez sur Créer.
  2. Lorsque vous êtes invité à sélectionner une version cible et minimale pour le projet, sélectionnez au moins 10.0.14393. Si vous souhaitez utiliser le nouvel attribut SupportsMultipleInstances, vous devez utiliser Visual Studio 2017 ou Visual Studio 2019 et cibler 10.0.15063 (Mise à jour Windows 10 Créateurs) ou version ultérieure.

Ajouter une extension app service à Package.appxmanifest

Dans le projet AppServiceProvider , ouvrez le fichier Package.appxmanifest dans un éditeur de texte :

  1. Cliquez avec le bouton droit sur celui-ci dans le Explorateur de solutions.
  2. Sélectionnez Ouvrir avec.
  3. Sélectionnez l’éditeur XML (texte).

Ajoutez l’extension suivante AppService à l’intérieur de l’élément <Application> . Cet exemple publie le com.microsoft.inventory service et identifie cette application en tant que fournisseur de services d’application. Le service réel sera implémenté en tant que tâche en arrière-plan. Le projet App Service expose le service à d’autres applications. Nous vous recommandons d’utiliser un style de nom de domaine inverse pour le nom du service.

Notez que le xmlns:uap4 préfixe d’espace de noms et l’attribut uap4:SupportsMultipleInstances sont valides uniquement si vous ciblez le SDK Windows version 10.0.15063 ou ultérieure. Vous pouvez les supprimer en toute sécurité si vous ciblez des versions antérieures du Kit de développement logiciel (SDK).

Remarque

Pour obtenir un exemple d’application App Service en C++/WinRT et C#, consultez l’exemple d’application 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>

L’attribut Category identifie cette application en tant que fournisseur de services d’application.

L’attribut EntryPoint identifie la classe qualifiée d’espace de noms qui implémente le service, que nous allons implémenter ensuite.

L’attribut SupportsMultipleInstances indique que chaque fois que le service d’application est appelé, il doit s’exécuter dans un nouveau processus. Cela n’est pas obligatoire, mais est disponible si vous avez besoin de cette fonctionnalité et ciblez le SDK 10.0.15063 (Mise à jour Windows 10 Créateurs) ou version ultérieure. Elle doit également être précédée par l’espace uap4 de noms.

Créer le service App Service

  1. Un service d’application peut être implémenté en tant que tâche en arrière-plan. Cela permet à une application de premier plan d’appeler un service d’application dans une autre application. Pour créer un service d’application en tant que tâche en arrière-plan, ajoutez un nouveau projet de composant Windows Runtime à la solution (Ajouter > > un nouveau projet) nommé MyAppService. Dans la boîte de dialogue Ajouter un nouveau projet , choisissez Composant > Windows Runtime Visual C# > installé (Windows universel).

  2. Dans le projet AppServiceProvider, ajoutez une référence de projet à projet au nouveau projet MyAppService (dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet AppServiceProvider Ajouter>>une solution de projets>> de référence, sélectionnez MyAppService>OK). Cette étape est essentielle, car si vous n’ajoutez pas la référence, le service d’application ne se connecte pas au moment de l’exécution.

  3. Dans le projet MyAppService, ajoutez les instructions using suivantes en haut de Class1.cs :

    using Windows.ApplicationModel.AppService;
    using Windows.ApplicationModel.Background;
    using Windows.Foundation.Collections;
    
  4. Renommez Class1.cs en Inventory.cs, puis remplacez le code stub pour Class1 par une nouvelle classe de tâche en arrière-plan nommée 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();
            }
        }
    }
    

    Cette classe est l’endroit où le service d’application fera son travail.

    L’exécution est appelée lorsque la tâche en arrière-plan est créée. Étant donné que les tâches en arrière-plan sont arrêtées une fois l’exécution terminée, le code supprime un report afin que la tâche en arrière-plan reste à jour pour traiter les demandes. Un service d’application implémenté en tant que tâche en arrière-plan reste actif pendant environ 30 secondes après qu’il reçoit un appel, sauf s’il est appelé à nouveau dans cette fenêtre de temps ou qu’un report est supprimé. Si le service d’application est implémenté dans le même processus que l’appelant, la durée de vie du service d’application est liée à la durée de vie de l’appelant.

    La durée de vie du service d’application dépend de l’appelant :

    • Si l’appelant est au premier plan, la durée de vie d’App Service est identique à celle de l’appelant.
    • Si l’appelant est en arrière-plan, le service d’application obtient 30 secondes pour s’exécuter. La suppression d’un report fournit une durée supplémentaire de 5 secondes.

    OnTaskCanceled est appelé lorsque la tâche est annulée. La tâche est annulée lorsque l’application cliente supprime AppServiceConnection, l’application cliente est suspendue, le système d’exploitation est arrêté ou en veille, ou le système d’exploitation manque de ressources pour exécuter la tâche.

Écrire le code du service d’application

OnRequestReceived est l’emplacement où se trouve le code du service d’application. Remplacez le stub OnRequestReceived dans le Inventory.cs myAppService par le code de cet exemple. Ce code obtient un index pour un élément d’inventaire et le transmet, ainsi qu’une chaîne de commande, au service pour récupérer le nom et le prix de l’élément d’inventaire spécifié. Pour vos propres projets, ajoutez du code de gestion des erreurs.

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();
    }
}

Notez que OnRequestReceived est asynchrone , car nous effectuons un appel de méthode awaitable à SendResponseAsync dans cet exemple.

Un report est effectué afin que le service puisse utiliser des méthodes asynchrones dans le gestionnaire OnRequestReceived . Il garantit que l’appel à OnRequestReceived n’est pas terminé tant qu’il n’a pas terminé de traiter le message. SendResponseAsync envoie le résultat à l’appelant. SendResponseAsync ne signale pas l’achèvement de l’appel. Il s’agit de l’achèvement du report qui signale à SendMessageAsync que OnRequestReceived a terminé. L’appel à SendResponseAsync est encapsulé dans un bloc try/finally, car vous devez terminer le report même si SendResponseAsync lève une exception.

Les services d’application utilisent des objets ValueSet pour échanger des informations. La taille des données que vous pouvez transmettre n’est limitée que par les ressources système. Il n’existe aucune clé prédéfinie à utiliser dans votre ValueSet. Vous devez déterminer les valeurs clés que vous utiliserez pour définir le protocole de votre service d’application. L’appelant doit être écrit à l’esprit avec ce protocole. Dans cet exemple, nous avons choisi une clé nommée Command qui a une valeur qui indique si le service d’application doit fournir le nom de l’élément d’inventaire ou son prix. L’index du nom d’inventaire est stocké sous la ID clé. La valeur de retour est stockée sous la Result clé.

Une énumération AppServiceClosedStatus est retournée à l’appelant pour indiquer si l’appel au service d’application a réussi ou échoué. Par exemple, l’appel au service d’application peut échouer si le système d’exploitation abandonne le point de terminaison de service, car ses ressources ont été dépassées. Vous pouvez retourner des informations d’erreur supplémentaires via ValueSet. Dans cet exemple, nous utilisons une clé nommée Status pour renvoyer des informations d’erreur plus détaillées à l’appelant.

L’appel à SendResponseAsync retourne ValueSet à l’appelant.

Déployer l’application de service et obtenir le nom de la famille de packages

Le fournisseur app service doit être déployé avant de pouvoir l’appeler à partir d’un client. Vous pouvez le déployer en sélectionnant Build > Deploy Solution dans Visual Studio.

Vous aurez également besoin du nom de famille de packages du fournisseur App Service pour l’appeler. Vous pouvez l’obtenir en ouvrant le fichier Package.appxmanifest du projet AppServiceProvider dans l’affichage concepteur (double-cliquez dessus dans le Explorateur de solutions). Sélectionnez l’onglet Empaquetage, copiez la valeur en regard du nom de la famille du package et collez-la quelque part comme le Bloc-notes pour l’instant.

Écrire un client pour appeler le service d’application

  1. Ajoutez un nouveau projet d’application windows universelle vide à la solution avec Fichier > Ajouter > un nouveau projet. Dans la boîte de dialogue Ajouter un nouveau projet, choisissez Application > vide Visual C# > installée (Windows universel) et nommez-la ClientApp.

  2. Dans le projet ClientApp, ajoutez l’instruction using suivante en haut de MainPage.xaml.cs :

    using Windows.ApplicationModel.AppService;
    
  3. Ajoutez une zone de texte appelée zone de texte et un bouton à MainPage.xaml.

  4. Ajoutez un gestionnaire de clics de bouton pour le bouton appelé button_Click, puis ajoutez le mot clé asynchrone à la signature du gestionnaire de boutons.

  5. Remplacez le stub de votre gestionnaire de clics de bouton par le code suivant. Veillez à inclure la déclaration de inventoryService champ.

    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;
    }
    

    Remplacez le nom de la famille de packages dans la ligne this.inventoryService.PackageFamilyName = "Replace with the package family name"; par le nom de famille de packages du projet AppServiceProvider que vous avez obtenu ci-dessus dans Déployer l’application de service et obtenir le nom de la famille de packages.

    Remarque

    Veillez à coller dans le littéral de chaîne, plutôt que de le placer dans une variable. Cela ne fonctionnera pas si vous utilisez une variable.

    Le code établit d’abord une connexion avec le service d’application. La connexion reste ouverte jusqu’à ce que vous disposiez this.inventoryService. Le nom du service d’application doit correspondre à l’attribut de l’élément AppService que vous avez ajouté au fichier Package.appxmanifest du projet AppServiceProvider.Name Dans cet exemple, il s’agit de <uap3:AppService Name="com.microsoft.inventory"/>.

    Un jeu de valeurs nommé message est créé pour spécifier la commande que nous voulons envoyer au service d’application. L’exemple d’app service s’attend à ce qu’une commande indique les deux actions à entreprendre. Nous obtenons l’index à partir de la zone de texte de l’application cliente, puis appelons le service avec la Item commande pour obtenir la description de l’élément. Ensuite, nous effectuons l’appel avec la Price commande pour obtenir le prix de l’article. Le texte du bouton est défini sur le résultat.

    Étant donné que AppServiceResponseStatus indique uniquement si le système d’exploitation a pu connecter l’appel au service d’application, nous vérifions la Status clé du ValueSet que nous recevons du service d’application pour vous assurer qu’il a pu répondre à la demande.

  6. Définissez le projet ClientApp comme projet de démarrage (cliquez dessus avec le bouton droit dans le Explorateur de solutions> Set en tant que projet de démarrage) et exécutez la solution. Entrez le numéro 1 dans la zone de texte, puis cliquez sur le bouton. Vous devez obtenir « Chair : Prix = 88,99 » de retour du service.

    exemple d’application affichant le prix de la chaise=88,99

Si l’appel app service échoue, vérifiez ce qui suit dans le projet ClientApp :

  1. Vérifiez que le nom de la famille de packages affecté à la connexion du service d’inventaire correspond au nom de famille de package de l’application AppServiceProvider . Voir la ligne dans button_Click avec this.inventoryService.PackageFamilyName = "...";.
  2. Dans button_Click, vérifiez que le nom du service d’application affecté à la connexion du service d’inventaire correspond au nom du service d’application dans le fichier Package.appxmanifest d’AppServiceProvider. Voir : this.inventoryService.AppServiceName = "com.microsoft.inventory";.
  3. Vérifiez que l’application AppServiceProvider a été déployée. (Dans le Explorateur de solutions, cliquez avec le bouton droit sur la solution et choisissez Déployer la solution).

Déboguer le service d’application

  1. Vérifiez que la solution est déployée avant le débogage, car l’application du fournisseur app service doit être déployée avant que le service puisse être appelé. (Dans Visual Studio, Générer une > solution de déploiement).
  2. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet AppServiceProvider et choisissez Propriétés. Sous l’onglet Débogage, remplacez l’action Démarrer par Ne pas lancer, mais déboguez mon code au démarrage. (Notez que si vous utilisiez C++ pour implémenter votre fournisseur App Service, à partir de la Onglet Débogage , vous devez remplacer l’application Lancement par Non.
  3. Dans le projet MyAppService , dans le fichier Inventory.cs , définissez un point d’arrêt dans OnRequestReceived.
  4. Définissez le projet AppServiceProvider comme projet de démarrage et appuyez sur F5.
  5. Démarrez ClientApp à partir de l’menu Démarrer (pas à partir de Visual Studio).
  6. Entrez le numéro 1 dans la zone de texte et appuyez sur le bouton. Le débogueur s’arrête dans l’appel app service sur le point d’arrêt de votre service d’application.

Déboguer le client

  1. Suivez les instructions de l’étape précédente pour déboguer le client qui appelle le service d’application.
  2. Lancez ClientApp à partir du menu Démarrer.
  3. Attachez le débogueur au processus ClientApp.exe (et non au processus ApplicationFrameHost.exe ). (Dans Visual Studio, choisissez Déboguer > l’attachement au processus....)
  4. Dans le projet ClientApp , définissez un point d’arrêt dans button_Click.
  5. Les points d’arrêt du client et du service d’application sont désormais atteints lorsque vous entrez le numéro 1 dans la zone de texte de ClientApp , puis cliquez sur le bouton.

Résolution des problèmes généraux du service d’application

Si vous rencontrez un état AppUnavailable après avoir essayé de vous connecter à un service d’application, vérifiez ce qui suit :

  • Vérifiez que le projet du fournisseur d’application et le projet App Service sont déployés. Les deux doivent être déployés avant d’exécuter le client, car sinon le client n’a rien à connecter. Vous pouvez déployer à partir de Visual Studio à l’aide de Build>Deploy Solution.
  • Dans le Explorateur de solutions, assurez-vous que votre projet de fournisseur d’applications dispose d’une référence de projet à projet au projet qui implémente le service d’application.
  • Vérifiez que l’entrée <Extensions> et ses éléments enfants ont été ajoutés au fichier Package.appxmanifest appartenant au projet du fournisseur d’applications, comme spécifié ci-dessus dans Ajouter une extension app service à Package.appxmanifest.
  • Vérifiez que la chaîne AppServiceConnection.AppServiceName dans votre client qui appelle le fournisseur de services d’application correspond à celle <uap3:AppService Name="..." /> spécifiée dans le fichier Package.appxmanifest du projet package.appxmanifest du projet de fournisseur d’applications.
  • Vérifiez que appServiceConnection.PackageFamilyName correspond au nom de famille de package du composant du fournisseur d’applications, comme spécifié ci-dessus, dans Ajouter une extension app service à Package.appxmanifest
  • Pour les services d’application obsolètes tels que celui de cet exemple, vérifiez que l’élément EntryPoint spécifié dans l’élément <uap:Extension ...> du fichier Package.appxmanifest de votre projet de fournisseur d’application correspond à l’espace de noms et au nom de classe de la classe publique qui implémente IBackgroundTask dans votre projet App Service.

Résoudre les problèmes de débogage

Si le débogueur ne s’arrête pas aux points d’arrêt dans votre fournisseur app service ou vos projets App Service, vérifiez ce qui suit :

  • Vérifiez que le projet du fournisseur d’application et le projet App Service sont déployés. Les deux doivent être déployés avant d’exécuter le client. Vous pouvez les déployer à partir de Visual Studio à l’aide de Build>Deploy Solution.
  • Vérifiez que le projet que vous souhaitez déboguer est défini comme projet de démarrage et que les propriétés de débogage de ce projet ne sont pas définies pour ne pas exécuter le projet lorsque F5 est enfoncé. Cliquez avec le bouton droit sur le projet, cliquez sur Propriétés, puis Déboguez (ou Débogage en C++). En C#, modifiez l’action Démarrer pour Ne pas lancer, mais déboguez mon code au démarrage. En C++, définissez Lancer l’application sur Non.

Notes

Cet exemple fournit une introduction à la création d’un service d’application qui s’exécute en tant que tâche en arrière-plan et l’appelant à partir d’une autre application. Les éléments clés à noter sont les suivants :

  • Créez une tâche en arrière-plan pour héberger le service d’application.
  • Ajoutez l’extension windows.appService au fichier Package.appxmanifest du fournisseur d’app service.
  • Obtenez le nom de famille de packages du fournisseur app service afin que nous puissions nous y connecter à partir de l’application cliente.
  • Ajoutez une référence de projet à projet du projet fournisseur d’application au projet App Service.
  • Utilisez Windows.ApplicationModel.AppService.AppServiceConnection pour appeler le service.

Code complet pour 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();
            }
        }
    }
}