Quizspiele bieten ein fesselndes und lehrreiches Erlebnis, bei dem Sie neue Fakten erfahren und Ihr Wissen über verschiedene Themen hinweg erweitern können. Heutzutage sind Trivia-Quiz-Mobil- und Webanwendungen die häufigsten Anlaufstellen für eine solche Aktivität. Wie wäre es mit einem Quizspiel auf WhatsApp? In diesem Tutorial-Leitfaden erfahren Sie, wie Sie mit Twilio für WhatsApp, ASP.NET Core und eine Trivia-Quizanwendung erstellen ( ). Das Ziel dieses Tutorials besteht darin, eine Quizspielanwendung zu erstellen, mit der Benutzer Multiple-Choice-Fragen mit WhatsApp spielen und beantworten können. Sie werden Nutzen daraus ziehen um den Benutzerfortschritt zu speichern und abzurufen, den Punktestand zu verfolgen und den Spielstatus aufrechtzuerhalten. Die Trivia-API lizenziert unter CC BY-NC 4.0 Sitzungen in ASP.NET Core Um diese Fragen abzurufen, verwenden Sie die Trivia API, eine REST-API, die es Entwicklern erleichtert, Quiz-Apps zu erstellen, indem sie Multiple-Choice-Trivia-Fragen bereitstellt. Um mehr über die Trivia-API zu erfahren, besuchen Sie bitte die__ . Trivia-API-Dokumentation__ Voraussetzungen Um dieses Tutorial abzuschließen, benötigen Sie: Ein Betriebssystem, das .NET unterstützt (Windows/macOS/Linux) .NET 7 SDK Ein Code-Editor oder eine IDE (empfohlen: , mit dem , oder ) Visual Studio Visual Studio-Code C#-Plugin JetBrains-Fahrer ngrok-CLI Ein kostenloses oder kostenpflichtiges Twilio-Konto (falls Sie noch keins haben, können Sie dies tun ) Testen Sie Twilio kostenlos Erfahrung mit C# und ASP.NET Core . Den Quellcode für dieses Tutorial finden Sie auf GitHub Richten Sie ein neues ASP.NET Core-Projekt ein Führen Sie zunächst über Ihr Shell-Terminal in einem bevorzugten Arbeitsverzeichnis die folgenden Befehle aus, um ein neues Web-API-Projekt zu erstellen: dotnet new webapi -n TwilioWhatsAppTriviaApp --no-openapi Der zweite Befehl im obigen Snippet erstellt ein neues Web-API-Projekt mit dem angegebenen Namen und ohne OpenAPI-Unterstützung (Swagger). Wenn Sie Swagger im Projekt verwenden möchten, lassen Sie im obigen Befehl einfach weg. --no-openapi Wechseln Sie in das Projektverzeichnis, indem Sie diesen Befehl ausführen: cd TwilioWhatsAppTriviaApp Installiere das NuGet-Paket: Twilio-Hilfsbibliothek für ASP.NET Core dotnet add package Twilio.AspNet.Core Diese Bibliothek vereinfacht die Arbeit mit Twilio-Webhooks und APIs in einer ASP.NET Core-Anwendung. Öffnen Sie das Projekt mit Ihrer bevorzugten IDE. Entfernen Sie im Ordner die Boilerplate-Controller-Vorlagendatei “ und entfernen Sie auch „ im Projektverzeichnis. „Controllers“ „WeatherForecastController.cs WeatherForcast.cs“ Erstellen Sie Ihr Projekt und führen Sie es aus, um sicherzustellen, dass alles, was Sie bisher getan haben, ordnungsgemäß funktioniert, indem Sie die folgenden Befehle verwenden: dotnet build dotnet run Notieren Sie sich nach erfolgreicher Ausführung des Projekts alle Localhost-URLs, die in der Debugging-Konsole angezeigt werden. Sie können jede dieser URLs verwenden, um mit ngrok einen öffentlich zugänglichen lokalen Webserver einzurichten. Implementieren Sie Sitzungen Sitzungen sind eine von mehreren Möglichkeiten, die Daten eines Benutzers in einer ASP.NET Core-Anwendung zu speichern. Dies ist wichtig, wenn Sie Benutzerdaten zwischen Anfragen beibehalten möchten, da das HTTP-Protokoll standardmäßig zustandslos ist – das bedeutet, dass Daten nicht erhalten bleiben. Fügen Sie den In-Memory-Sitzungsanbieter hinzu, indem Sie ändern, wie im folgenden Code gezeigt: 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(); registriert den verteilten Speicher-Cache-Dienst. Dieser Dienst stellt einen In-Memory-Cache bereit, der zum Speichern und Abrufen von Daten über mehrere Anfragen oder Sitzungen hinweg verwendet werden kann. AddDistributedMemoryCache() registriert die Sitzungsdienste und ermöglicht der Anwendung, den Sitzungsstatus beizubehalten. Mit dem können Sie verschiedene sitzungsbezogene Optionen konfigurieren. wird verwendet, um die Dauer der Inaktivität festzulegen, nach der eine Sitzung als inaktiv betrachtet wird. In diesem Fall ist sie auf 40 Sekunden eingestellt. stellt sicher, dass der Sitzungsstatus auch in Szenarien, in denen die Cookie-Ablehnung aktiviert ist, funktionsfähig bleibt. AddSession() options IdleTimeout Cookie.IsEssential Die Sitzungsunterstützung wird durch das Hinzufügen der Middleware zur Anwendungspipeline aktiviert, d. h. Ihre Anwendung erhält Zugriff auf ein Sitzungsobjekt, das zum Speichern und Abrufen von Daten verwendet werden kann. UseSession Erstellen Sie die Modelle Erstellen Sie einen neuen Ordner, in Ihrem Projektverzeichnis. Fügen Sie zwei Modellklassendateien hinzu, und , mit Eigenschaften, wie in den folgenden Codebeispielen gezeigt: 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; } } Das Modell enthält Eigenschaften, die die Felder der Trivia-API-Antwort darstellen. Das Attribut stellt sicher, dass jede Eigenschaft korrekt mit den entsprechenden JSON-Daten gefüllt wird. TriviaApiResponse JsonProperty Für eine optimierte Bearbeitung trivialer Fragen kommt die Klasse zum Einsatz. Diese Klasse kapselt die notwendigen Informationen für eine Trivia-Frage, einschließlich des Fragetextes und einer Liste von Optionen. Jede Option wird durch ein Tupel dargestellt, das den Optionstext und einen booleschen Wert enthält, der angibt, ob es sich um die richtige Option handelt. Question Fügen Sie die Trivia-Serviceklasse hinzu Erstellen Sie einen Ordner in Ihrem Projektverzeichnis und fügen Sie eine neue Klassendatei mit dem Namen hinzu. Ändern Sie den Inhalt, wie im folgenden Code gezeigt: 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; } } Die Klasse enthält zwei Methoden: und . Die Methode sendet die HTTP-GET-Anfrage mit dem Abfrageparameter an die Trivia-API, der angibt, dass nur drei Fragen zurückgegeben werden sollen. Ohne den limit-Parameter gibt die API standardmäßig 10 Fragen zurück. TriviaService GetTrivia ConvertTriviaToQuestions GetTrivia limit=3 Die Methode wandelt die Antwort von der API in eine organisierte Form um. Die Methode mischt außerdem alle Frageoptionen nach dem Zufallsprinzip, sodass eine einzelne Option nicht die Antwort auf alle Fragen ist. ConvertTriviaToQuestions Um und den HTTP-Client im Dependency Injection (DI)-Container Ihrer Anwendung zu registrieren, ändern Sie wie im folgenden Code gezeigt: 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(); Erstellen Sie den Trivia-Controller Fügen Sie eine leere API-Controller-Klasse in einer Datei namens zum Ordner hinzu und ändern Sie deren Inhalt wie im folgenden Code gezeigt: 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; } } Diese Controller-Klasse ist für die Verarbeitung eingehender Nachrichten, die Verwaltung des Sitzungsstatus und die Generierung von Antworten verantwortlich. Es erbt von der Klasse, die von der Twilio.AspNet.Core-Bibliothek bereitgestellt wird und Ihnen Zugriff auf die Methode ermöglicht. Mit dieser Methode können Sie antworten . Die Klasse verwendet Methoden, um mit der Sitzung zu interagieren. Die gültigen Eingaben sind Elemente in den schreibgeschützten Arrays und . Der Text der eingehenden Nachricht wird mit diesen Elementen verglichen, um sicherzustellen, dass der Benutzer eine korrekte Eingabe gesendet hat. Andernfalls wird eine Nachricht an den Benutzer gesendet, die ihn auffordert, basierend auf dem aktuellen Status des Spiels die richtige Eingabe vorzunehmen. Andere Felder mit dem Präfix „SessionKey“ werden verwendet, um private Konstantenzeichenfolgen für Sitzungsschlüssel im Programm zu definieren. TwilioController TwiML TwiML, die Twilio Markup Language TriviaController HttpContext.Session StartCommands OptionValues Die Methode ist die Hauptaktionsmethode, die eingehende HTTP-POST-Anfragen von WhatsApp über die Route verarbeitet. Es lädt die Sitzungsdaten mit und ruft mit den Methoden und Daten zum Spielstatus aus der Sitzung ab. Index /Trivia- HttpContext.Session.LoadAsync() HttpContext.Session.GetString() HttpContext.Session.GetInt32() Durch die Verwendung von Unterstrichen (_) und Sternchen (*) am Anfang und Ende bestimmter Zeichenfolgen wird eine kursive bzw. fette Textformatierung in gerenderten WhatsApp-Nachrichten erreicht. Jede Hilfsmethode im führt eine bestimmte Aufgabe aus, die die Hauptfunktionalität der Klasse unterstützt. TriviaController Methode initialisiert das Spiel, indem sie Quizfragen abruft, sie in ein für das Spiel geeignetes Format konvertiert und sie in der Sitzung speichert. StartGame Methode verarbeitet die Antwort des Benutzers auf eine Frage und bestimmt, ob sie richtig ist oder nicht. ProcessUserAnswer Die Methode ist für die Formatierung und Darstellung einer Frage zusammen mit ihren Optionen verantwortlich. PresentQuestionWithOptions Methode speichert eine Liste von Fragen in der Sitzung. Es konvertiert die Fragen in das JSON-Format und speichert die JSON-Zeichenfolge in der Sitzung. AddNewQuestionsToSession Methode ruft mithilfe des Fragenindex eine Frage aus der Sitzung ab. RetrieveQuestionFromSession Methode generiert eine Nachricht zum Beenden des Quizspiels. Diese Methode entfernt auch Sitzungsdaten im Zusammenhang mit dem Spiel. Basierend auf der Konfiguration des Sitzungsdiensts in geschieht dies automatisch, wenn die Sitzung 40 Sekunden lang inaktiv ist. EndTrivia Program.cs Testen Sie die Anwendung Um die Anwendung zu testen, müssen Sie Twilio Sandbox für WhatsApp einrichten, Ihren Anwendungsendpunkt öffentlich zugänglich machen und die Endpunkt-URL in der Sandbox-Konfiguration als Webhook hinzufügen. Richten Sie Twilio Sandbox für WhatsApp ein Gehe zum , navigieren Sie zu . Twilio-Konsole Nachricht > Ausprobieren > WhatsApp-Nachricht senden Befolgen Sie die Anweisungen auf der Seite, um eine Verbindung zur Sandbox herzustellen, indem Sie eine WhatsApp-Nachricht von Ihrem Gerät an die angegebene Twilio-Nummer senden, um eine erfolgreiche Verbindung mit der WhatsApp-Sandbox herzustellen. Ebenso müssen andere Personen, die Ihre App mit ihren jeweiligen Nummern testen möchten, das gleiche Verfahren befolgen. Machen Sie Ihren Webhook mit ngrok zum Testen verfügbar Öffnen Sie nun ein Shell-Terminal und führen Sie den folgenden Befehl aus, um ngrok zu starten und Ihre lokale ASP.NET Core-App verfügbar zu machen, indem Sie durch die vollständige URL Ihres ursprünglich kopierten Localhosts ersetzen: <localhost-url> ngrok http <localhost-url> ngrok generiert eine öffentliche URL, die Anfragen an Ihre lokale ASP.NET-App weiterleitet. Suchen Sie im ngrok-Terminalfenster nach der Weiterleitungs-URL mit der Bezeichnung und kopieren Sie sie. „Forwarding“ Gehen Sie zurück zur Twilio Try WhatsApp-Seite, klicken Sie auf und ändern Sie die Endpunkt-URL durch die von ngrok generierte -URL sowie die Route “ und stellen Sie sicher, dass die Methode auf „POST“ eingestellt ist. Klicken Sie dann auf Speichern, um die neue Sandbox-Konfiguration zu speichern. Sandbox-Einstellungen „Wenn eine Nachricht eingeht“ Weiterleitungs „/Trivia Projektdemo Führen Sie Ihr ASP.NET Core-Projekt mit dem folgenden Befehl aus: dotnet run Testen Sie nun Ihre Anwendung, indem Sie im ersten Gespräch eine Nachricht mit der Twilio Sandbox-Nummer senden. Abschluss Durch die Nutzung der Leistungsfähigkeit der Twilio-Plattform und WhatsApp haben Sie ein fesselndes Quizspielerlebnis geschaffen, das die Benutzer genießen können. Sie haben außerdem gelernt, wie Sie Daten aus Sitzungen speichern und abrufen. Es gibt mehrere Möglichkeiten, dieses Projekt zu verbessern. Sie können dieses Projekt weiter verbessern, indem Sie einen Timer hinzufügen, Ausnahmen behandeln, Benutzern die Auswahl des Schwierigkeitsgrads ermöglichen und den gewählten Schwierigkeitsgrad als Abfrageparameter über die Trivia-API-URL anwenden (z. B ). Darüber hinaus können Sie die Möglichkeit prüfen, eine Lösung zu entwickeln, die es Benutzern ermöglicht, Umfragen über WhatsApp auszufüllen. https://the-trivia-api.com/api/questions?difficulty=hard