Les jeux-questionnaires offrent une expérience engageante et éducative où vous pouvez apprendre de nouveaux faits et élargir vos connaissances sur divers sujets. De nos jours, les applications mobiles et Web Trivia quiz sont les domaines de prédilection les plus courants pour une telle activité. Que diriez-vous de jouer à un jeu-questionnaire sur WhatsApp ? Dans ce guide didacticiel, vous apprendrez à créer une application de quiz à l'aide de Twilio pour WhatsApp, ASP.NET Core et ( ). Le but de ce didacticiel est de créer une application de jeu-questionnaire qui permet aux utilisateurs de jouer et de répondre à des questions à choix multiples à l'aide de WhatsApp. Vous tirerez parti pour stocker et récupérer la progression de l'utilisateur, suivre le score et maintenir l'état du jeu. L'API Trivia sous licence CC BY-NC 4.0 sessions dans ASP.NET Core Pour récupérer ces questions, vous utiliserez l'API Trivia, une API REST, qui permet aux développeurs de créer facilement des applications de quiz en proposant des questions à choix multiples. Pour en savoir plus sur l'API Trivia, veuillez consulter la__ __. documentation de l'API Trivia Conditions préalables Pour réaliser ce tutoriel, vous aurez besoin de : Un système d'exploitation prenant en charge .NET (Windows/macOS/Linux) Kit de développement logiciel .NET 7 Un éditeur de code ou IDE (recommandé : , avec le , ou ) Visual Studio Code de Visual Studio Plugin C# Pilote JetBrains CLI ngrok Un compte Twilio gratuit ou payant (si vous n'en avez pas, vous pouvez ) essayez Twilio gratuitement Expérience avec C# et ASP.NET Core . Le code source de ce tutoriel est disponible sur GitHub Configurer un nouveau projet ASP.NET Core Pour commencer, en utilisant votre terminal shell dans un répertoire de travail préféré, exécutez les commandes suivantes pour créer un nouveau projet d'API Web : dotnet new webapi -n TwilioWhatsAppTriviaApp --no-openapi La deuxième commande de l'extrait ci-dessus créera un nouveau projet d'API Web avec le nom spécifié et sans prise en charge d'OpenAPI (Swagger). Si vous souhaitez utiliser Swagger dans le projet, omettez simplement dans la commande ci-dessus. --no-openapi Accédez au répertoire du projet en exécutant cette commande : cd TwilioWhatsAppTriviaApp Installez le Forfait NuGet : Bibliothèque Twilio Helper pour ASP.NET Core dotnet add package Twilio.AspNet.Core Cette bibliothèque simplifie l'utilisation des webhooks et des API Twilio dans une application ASP.NET Core. Ouvrez le projet en utilisant votre IDE préféré. Dans le dossier , supprimez le fichier de contrôleur de modèle standard, , et supprimez également dans le répertoire du projet. Controllers WeatherForecastController.cs WeatherForcast.cs Créez et exécutez votre projet pour vous assurer que tout ce que vous avez fait jusqu'à présent fonctionne bien à l'aide des commandes suivantes : dotnet build dotnet run Après avoir exécuté le projet avec succès, notez toutes les URL localhost qui apparaissent dans la console de débogage. Vous pouvez utiliser n'importe laquelle de ces URL pour configurer un serveur Web local accessible au public à l'aide de ngrok. Mettre en œuvre des sessions Les sessions sont l'une des nombreuses façons de stocker les données d'un utilisateur dans une application ASP.NET Core. Ceci est essentiel lorsque vous souhaitez conserver les données utilisateur entre les requêtes car par défaut, le protocole HTTP est sans état, ce qui signifie que les données ne sont pas conservées. Ajoutez le fournisseur de session en mémoire en modifiant , comme indiqué dans le code suivant : Program.cs var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run(); enregistre le service de cache de mémoire distribuée. Ce service fournit un cache en mémoire qui peut être utilisé pour stocker et récupérer des données sur plusieurs requêtes ou sessions. AddDistributedMemoryCache() enregistre les services de session, permettant à l'application de maintenir l'état de session. Le paramètre vous permet de configurer diverses options liées à la session. est utilisé pour définir la durée d'inactivité après laquelle une session sera considérée comme inactive. Dans ce cas, elle est fixée à 40 secondes. garantit que l'état de la session reste fonctionnel et même dans les scénarios où le rejet des cookies est activé. AddSession() options IdleTimeout Cookie.IsEssential La prise en charge des sessions est activée en ajoutant le middleware au pipeline d'application, c'est-à-dire que votre application accède à un objet de session qui peut être utilisé pour stocker et récupérer des données. UseSession Créer les modèles Créez un nouveau dossier, dans le répertoire de votre projet. Ajoutez deux fichiers de classe de modèle, et avec les propriétés indiquées dans les exemples de code suivants : Models, TriviaApiResponse.cs Question.cs using Newtonsoft.Json; namespace TwilioWhatsAppTriviaApp.Models; public class TriviaApiResponse { [JsonProperty("category")] public string Category { get; set; } [JsonProperty("correctAnswer")] public string CorrectAnswer { get; set; } [JsonProperty("incorrectAnswers")] public List<string> IncorrectAnswers { get; set; } [JsonProperty("question")] public string Question { get; set; } [JsonProperty("type")] public string? Type { get; set; } [JsonProperty("difficulty")] public string Difficulty { get; set; } } namespace TwilioWhatsAppTriviaApp.Models; public class Question { public string QuestionText { get; set; } public List<(string option, bool isCorrect)> Options { get; set; } } Le modèle inclut des propriétés qui représentent les champs de la réponse de l'API Trivia. L'attribut garantit que chaque propriété est correctement renseignée avec les données JSON correspondantes. TriviaApiResponse JsonProperty Pour une manière simplifiée de gérer les questions triviales, la classe vient à la rescousse. Cette classe encapsule les informations nécessaires pour une question triviale, y compris le texte de la question et une liste d'options. Chaque option est représentée par un tuple contenant le texte de l'option et une valeur booléenne indiquant si c'est la bonne option. Question Ajouter la classe de service Trivia Créez un dossier dans le répertoire de votre projet et ajoutez un nouveau fichier de classe nommé . Modifiez son contenu, comme indiqué dans le code suivant : Services TriviaService.cs using Newtonsoft.Json; using TwilioWhatsAppTriviaApp.Models; namespace TwilioWhatsAppTriviaApp.Services; public class TriviaService { private const string TheTriviaApiUrl = @"https://the-trivia-api.com/api/questions?limit=3"; private HttpClient httpClient; public TriviaService(HttpClient httpClient) { this.httpClient = httpClient; } public async Task<IEnumerable<TriviaApiResponse>> GetTrivia() { var response = await httpClient.GetAsync(TheTriviaApiUrl); var triviaJson = await response.Content.ReadAsStringAsync(); var trivia = JsonConvert.DeserializeObject<IEnumerable<TriviaApiResponse>>(triviaJson); return trivia; } public List<Question> ConvertTriviaToQuestions(IEnumerable<TriviaApiResponse> questions) { List<Question> newQuestions = new(); foreach (var question in questions) { var options = new List<(string option, bool isCorrect)>() { (question.CorrectAnswer, true), (question.IncorrectAnswers[0], false), (question.IncorrectAnswers[1], false), (question.IncorrectAnswers[2], false) }; // Shuffle the options randomly Random random = new(); options = options.OrderBy(_ => random.Next()).ToList(); newQuestions.Add(new Question { QuestionText = question.Question, Options = options }); } return newQuestions; } } La classe contient deux méthodes : et . La méthode envoie la requête HTTP GET à l'API Trivia avec un paramètre de requête, , qui spécifie que seules 3 questions doivent être renvoyées. Sans le paramètre limit, l'API renvoie 10 questions par défaut. TriviaService GetTrivia ConvertTriviaToQuestions GetTrivia limit=3 La méthode convertit la réponse de l'API de manière organisée. La méthode mélange également toutes les options de questions de manière aléatoire, de sorte qu'une seule option ne soit pas la réponse à toutes les questions. ConvertTriviaToQuestions Pour enregistrer et le client HTTP dans le conteneur Dependency Injection (DI) de votre application, modifiez comme indiqué dans le code suivant : TriviaService Program.cs using TwilioWhatsAppTriviaApp.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); builder.Services.AddHttpClient(); builder.Services.AddScoped<TriviaService>(); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run(); Créer le contrôleur Trivia Ajoutez une classe de contrôleur API vide dans un fichier nommé au dossier et modifiez son contenu comme indiqué dans le code suivant : TriviaController.cs Controllers using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Twilio.AspNet.Core; using Twilio.TwiML; using Twilio.TwiML.Messaging; using TwilioWhatsAppTriviaApp.Models; using TwilioWhatsAppTriviaApp.Services; namespace WhatsappTrivia.Controllers; [Route("[controller]")] [ApiController] public class TriviaController : TwilioController { private const string SessionKeyIsGameOn = "IsGameOn"; private const string SessionKeyScore = "Score"; private const string SessionKeyCurrentQuestionIndex = "CurrentQuestionIndex"; private const string SessionKeyTotalQuestions = "TotalQuestions"; private const string SessionKeyQuestions = "Questions"; private static readonly string[] StartCommands = { "START", "S" }; private static readonly string[] OptionValues = { "A", "B", "C", "D" }; private readonly TriviaService triviaService; public TriviaController(TriviaService triviaService) { this.triviaService = triviaService; } [HttpPost] public async Task<IActionResult> Index() { var response = new MessagingResponse(); var form = await Request.ReadFormAsync(); var body = form["Body"].ToString().ToUpper().Trim(); await HttpContext.Session.LoadAsync(); var isGameOn = Convert.ToBoolean(HttpContext.Session.GetString(SessionKeyIsGameOn)); int currentQuestionIndex = HttpContext.Session.GetInt32(SessionKeyCurrentQuestionIndex) ?? 0; int totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; if (StartCommands.Contains(body) && !isGameOn) { await StartGame(); HttpContext.Session.SetString(SessionKeyIsGameOn, "true"); response.Message(PresentQuestionWithOptions(currentQuestionIndex)); return TwiML(response); } if (OptionValues.Contains(body) && isGameOn) { var result = ProcessUserAnswer(body, currentQuestionIndex); response.Message(result); currentQuestionIndex++; if (currentQuestionIndex <= totalQuestions - 1) { HttpContext.Session.SetInt32(SessionKeyCurrentQuestionIndex, currentQuestionIndex); response.Append(new Message(PresentQuestionWithOptions(currentQuestionIndex))); } else { response.Append(new Message(EndTrivia())); } return TwiML(response); } response.Message(!isGameOn ? "*Hello! Send 'Start' or 'S' to play game*" : "*Invalid Input! Send a correct option 'A', 'B', 'C' or 'D'*"); return TwiML(response); } private async Task StartGame() { if (HttpContext.Session.GetString(SessionKeyQuestions) != null) { HttpContext.Session.Remove(SessionKeyQuestions); } var trivia = await this.triviaService.GetTrivia(); var questions = this.triviaService.ConvertTriviaToQuestions(trivia); AddNewQuestionsToSession(questions); HttpContext.Session.SetInt32(SessionKeyTotalQuestions, questions.Count); } private string ProcessUserAnswer(string userAnswer, int questionIndex) { bool optionIsCorrect = false; int score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var question = RetrieveQuestionFromSession(questionIndex); switch (userAnswer) { case "A": optionIsCorrect = question.Options[0].isCorrect; break; case "B": optionIsCorrect = question.Options[1].isCorrect; break; case "C": optionIsCorrect = question.Options[2].isCorrect; break; case "D": optionIsCorrect = question.Options[3].isCorrect; break; } if (optionIsCorrect) { score++; HttpContext.Session.SetInt32(SessionKeyScore, score); } return optionIsCorrect ? "_Correct ✅_" : $"_Incorrect ❌ Correct answer is {question.Options.Find(o => o.isCorrect).option.TrimEnd()}_"; } private string PresentQuestionWithOptions(int questionIndex) { var question = RetrieveQuestionFromSession(questionIndex); return $""" {questionIndex + 1}. {question.QuestionText} {OptionValues[0]}. {question.Options[0].option} {OptionValues[1]}. {question.Options[1].option} {OptionValues[2]}. {question.Options[2].option} {OptionValues[3]}. {question.Options[3].option} """; } private void AddNewQuestionsToSession(List<Question> questions) => HttpContext.Session.SetString(SessionKeyQuestions, JsonConvert.SerializeObject(questions)); private Question RetrieveQuestionFromSession(int questionIndex) { var questionsFromSession = HttpContext.Session.GetString(SessionKeyQuestions); return JsonConvert.DeserializeObject<List<Question>>(questionsFromSession)[questionIndex]; } private string EndTrivia() { var score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; var userResult = $""" Thanks for playing! 😊 You answered {score} out of {totalQuestions} questions correctly. To play again, send 'Start' or 'S' """; HttpContext.Session.Clear(); return userResult; } } Cette classe de contrôleur est responsable du traitement des messages entrants, de la gestion de l'état de la session et de la génération des réponses. Il hérite de la classe fournie par la bibliothèque Twilio.AspNet.Core, qui vous donne accès à la méthode . Vous pouvez utiliser cette méthode pour répondre avec . La classe utilise les méthodes pour interagir avec la session. Les entrées valides sont des éléments des tableaux en lecture seule et . Le corps du message entrant est comparé à ces éléments pour garantir que l'utilisateur a envoyé une entrée appropriée. Dans le cas contraire, un message sera envoyé à l'utilisateur l'invitant à effectuer la bonne entrée en fonction de l'état actuel du jeu. D'autres champs avec le préfixe « SessionKey » sont utilisés pour définir des chaînes constantes privées pour les clés de session dans le programme. TwilioController TwiML TwiML, qui est le langage de balisage Twilio TriviaController HttpContext.Session StartCommands OptionValues La méthode est la méthode d'action principale qui gère les requêtes HTTP POST entrantes de WhatsApp via la route . Il charge les données de session à l'aide de et récupère les données concernant l'état du jeu de la session à l'aide des méthodes et . Index /Trivia HttpContext.Session.LoadAsync() HttpContext.Session.GetString() HttpContext.Session.GetInt32() L'utilisation de traits de soulignement (_) et d'astérisques (*) au début et à la fin de certaines chaînes permet d'obtenir respectivement un formatage de texte en italique et en gras dans les messages WhatsApp rendus. Chaque méthode d'assistance du effectue une tâche spécifique qui prend en charge les fonctionnalités principales de la classe. TriviaController La méthode initialise le jeu en récupérant les questions triviales, en les convertissant dans un format adapté au jeu et en les stockant dans la session. StartGame La méthode traite la réponse de l'utilisateur à une question et détermine si elle est correcte ou non. ProcessUserAnswer La méthode est responsable du formatage et de la présentation d’une question avec ses options. PresentQuestionWithOptions La méthode stocke une liste de questions dans la session. Il convertit les questions au format JSON et enregistre la chaîne JSON dans la session. AddNewQuestionsToSession La méthode récupère une question de la session à l’aide de l’index des questions. RetrieveQuestionFromSession La méthode génère un message pour terminer le jeu-questionnaire. Cette méthode supprime également les données de session liées au jeu. Basé sur la configuration du service de session dans , cela se produit automatiquement lorsque la session est inactive pendant 40 secondes. EndTrivia Program.cs Testez l'application Pour tester l'application, vous devez configurer Twilio Sandbox pour WhatsApp, rendre le point de terminaison de votre application accessible au public et ajouter l'URL du point de terminaison dans la configuration Sandbox en tant que webhook. Configurer Twilio Sandbox pour WhatsApp Allez au , accédez à . Console Twilio Message > Essayez-le > Envoyer un message WhatsApp Suivez les instructions sur la page pour vous connecter au bac à sable, en envoyant un message WhatsApp depuis votre appareil au numéro Twilio fourni afin de créer une connexion réussie avec le bac à sable WhatsApp. De même, les autres personnes souhaitant tester votre application avec leurs numéros respectifs devront suivre la même procédure. Exposez votre webhook en utilisant ngrok pour les tests Maintenant, ouvrez un terminal shell et exécutez la commande suivante pour démarrer ngrok et exposer votre application ASP.NET Core locale en remplaçant par l'URL complète de votre hôte local que vous avez copié initialement : <localhost-url> ngrok http <localhost-url> ngrok générera une URL publique qui transmettra les requêtes à votre application ASP.NET locale. Recherchez l'URL de transfert intitulée dans la fenêtre du terminal ngrok et copiez-la. Forwarding Revenez à la page Twilio Try WhatsApp, cliquez sur et modifiez l'URL endpoint url avec l'URL générée par ngrok plus la route et assurez-vous que la méthode est définie sur POST. Cliquez ensuite sur Enregistrer pour enregistrer la nouvelle configuration du bac à sable. Sandbox Settings When a message comes in de transfert /Trivia Démo du projet Exécutez votre projet ASP.NET Core à l'aide de la commande suivante : dotnet run Maintenant, testez votre application en envoyant un message lors de la conversation initiale avec le numéro Twilio Sandbox. Conclusion En tirant parti de la puissance de la plate-forme Twilio et de WhatsApp, vous avez créé une expérience de jeu-questionnaire immersive dont les utilisateurs peuvent profiter. Vous avez également appris à enregistrer et récupérer les données des sessions. Il existe plusieurs façons d’améliorer ce projet. Vous pouvez encore améliorer ce projet en ajoutant une minuterie, en gérant les exceptions, en permettant aux utilisateurs de choisir la difficulté et en appliquant la difficulté choisie comme paramètre de requête via l'URL de l'API Trivia (par exemple ). De plus, vous pouvez explorer la possibilité de créer une solution permettant aux utilisateurs de répondre à des sondages via WhatsApp. https://the-trivia-api.com/api/questions?difficulty=hard