QUIZ – aplikacja ASP.NET MVC

Autorzy: Piotr Romański


C#, ASP.NET, ASP.NET MVC, MVC


Artykuł ten jest pierwszą częścią serii, która ukazywać się będzie na stronie koła informatycznego RESET. Będzie ona przedstawiać rozwiązanie problemu dotyczącego napisania prostego quizu internetowego „Co to za gra?”. W tym przypadku zastosowaną technologią będzie ASP.NET MVC.
Artykuł został napisany w ramach staży realizowanych w firmie LGBS Polska.

Wstęp {sekcja}
Nasze zadanie będzie polegać na utworzeniu prostej aplikacji ASP.NET MVC - quizu  "Co to za gra?". Zadaniem
użytkownika będzie natomiast  wybranie z listy odpowiedzi nazwy gry, z której pochodzi przedstawione zdjęcie.
Ilość odpowiedzi będzie losowa- z przedziału 3 - 5. Galerie zdjęć będą przechowywane w pliku XML. Po naciśnięciu
przycisku użytkownik otrzyma kolejne pytanie wraz z odpowiedzią do poprzedniego. Do stworzenia przedmiotowej
aplikacji wykorzystamy Visual Studio 2013 Express for Web.

Wstęp

Nasze zadanie będzie polegać na utworzeniu prostej aplikacji ASP.NET MVC - quizu  "Co to za gra?". Zadaniem użytkownika będzie natomiast wybranie z listy odpowiedzi nazwy gry, z której pochodzi przedstawione zdjęcie. Ilość odpowiedzi będzie losowa- z przedziału 3 - 5. Galerie zdjęć będą przechowywane w pliku XML. Po naciśnięciu przycisku użytkownik otrzyma kolejne pytanie wraz z odpowiedzią do poprzedniego. Do stworzenia przedmiotowej aplikacji wykorzystamy Visual Studio 2013 Express for Web.

aplikacja1

Tworzenie nowego projektu MVC

 

Tworzymy nowy projekt w Visual Studio. W nowo otwartym oknie wybieramy z listy szablonów Visual C#, następnie zaznaczamy projekt typu ASP.NET Web Application i nadajemy mu nazwę Quiz.

projekt1

W kolejnym kroku wybieramy szablon Empty oraz zaznaczamy pole MVC.

projekt2

W ten sposób utworzyliśmy pusty projekt ASP.NET MVC.

Dodawanie galerii zdjęć

Klikamy prawym przyciskiem myszy na nazwie naszego projektu w Solution Explorer, po czym wybieramy pozycję Add -> New folder. Nadajemy mu nazwę Images. Nasza struktura projektu powinna wyglądać następująco:

solucja1

Każdą nową galerię zdjęć z konkretnej gry będziemy tworzyć zaczynając od dodania katalogu z nazwą gry do folderu Images/Gallery.

Utworzymy teraz plik XML, w którym umieszczane będą dane o dostępnych galeriach. Klikamy prawym przyciskiem myszy na folderze App_Data, następnie wybieramy pozycję Add->XML File. W nowo otwartym oknie, wprowadzamy nazwę Galleries.  W głównym obszarze Visual Studio, zostanie wyświetlony nasz nowo utworzony plik XML. Definiujemy nasz główny znacznik, niech będzie to galleries. Zawierać się w nim będą wszystkie dostępne galerie.

Każda galeria będzie zawierała swój identyfikator, nazwę gry oraz listę obrazków.

Gotowy, przykładowy plik XML, może wyglądać tak jak poniżej.

 

<?xml version="1.0" encoding="utf-8" ?>
<games>
  <game id="1" name="Need for Speed Rivals">
    <image src="/Games/Need for speed rivals/1.jpg"/>
    <image src="/Games/Need for speed rivals/2.jpg"/>
    <image src="/Games/Need for speed rivals/3.jpg"/>
  </game>
  <game id="2" name="Call of Duty Ghosts">
    <image src="/Games/Call of duty ghosts/1.jpg"/>
    <image src="/Games/Call of duty ghosts/2.jpg"/>
  </game>
  <game id="3" name="Crysis">
    <image src="/Games/Crysis/1.jpg"/>
    <image src="/Games/Crysis/2.jpg"/>
  </game>
  <game id="4" name="S.T.A.L.K.E.R. Zew Prypeci">
    <image src="/Games/Stalker zew prypeci/1.jpg"/>
    <image src="/Games/Stalker zew prypeci/2.jpg"/>
  </game>
  <game id="5" name="Wiedzmin 2">
    <image src="/Games/Wiedzmin 2/1.jpg"/>
    <image src="/Games/Wiedzmin 2/2.jpg"/>
    <image src="/Games/Wiedzmin 2/3.jpg"/>
  </game>
</games>

 

Tworzenie modelu

W kolejnym kroku musimy stworzyć model reprezentujący pojedynczą galerię gier. Klikamy prawym przyciskiem myszy na folderze Models, wybieramy Add->Class i nadajemy nazwę Gallery. W nowo utworzonej klasie definiujemy trzy właściwości, tj. Id typu int, Name typu string oraz Images typu IList<string>.

 

public class Gallery
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IList<string> Images { get; set; }

    public Gallery()
    {
        Images = new List<string>();
    }
}

 

 

Tworzenie modelu widoku

Każde pytanie quizu składa się z jednego obrazka oraz losowej liczby odpowiedzi. Stwórzmy zatem klasę, której obiekty będą pełniły rolę "opakowania danych" przekazywanych przez kontroler do widoku. Dodamy teraz do projektu folder o nazwie ViewModels, a następnie utworzymy w nim klasę QuestionViewModel.

 

public class QuestionViewModel
{
    public string ImagePath { get; set; }
    public List<Answer> Answers { get; set; }
    public string Result { get; set; }
    public bool IsCorrect { get; set; }

    public class Answer
    {
        public int AnswerId { get; set; }
        public string Name { get; set; }
    }

    public QuestionViewModel()
    {
        Answers = new List<Answer>();
    }
}

 

Tworzenie usługi

Dane o galeriach przechowywane są w pliku XML, zatem trzeba je w jakiś sposób dostarczyć do kontrolera. Posłuży nam do tego obiekt typu GalleryService. Do projektu dodajemy nowy folder Services, a następnie tworzymy w nim klasę GalleryService. Nasz projekt powinien wyglądać teraz tak jak na rysunku poniżej.

solucja2

Do klasy usług skopiujemy zawartość poniższego listingu kodu.

 

public class GalleryService
{
    private IList<Gallery> _galleryList;
    private const string _xmlPath = "~/App_Data/Galleries.xml";

    public GalleryService()
    {
        _galleryList = new List<Gallery>();
        LoadData();
    }

    private void LoadData()
    {
        XElement root = XElement.Load(HttpContext.Current.Server.MapPath(_xmlPath));

        _galleryList = root.Elements("gallery").Select(p => new Gallery()
        {
            Id = int.Parse(p.Attribute("id").Value),
            Name = p.Attribute("name").Value,
            Images = p.Elements("image").Select(i => string.Format("/Images{0}", i.Attribute("src").Value)).ToList()
        }).ToList();
    }

    public QuestionViewModel GetQuestion()
    {
        var question = new QuestionViewModel();
        var random = new Random(Guid.NewGuid().GetHashCode());
        // wybranie losowego pytania
        var gallery = _galleryList[random.Next(0, _galleryList.Count - 1)];
        // wybranie losowego obrazka z galerii
        question.ImagePath = gallery.Images.ElementAtOrDefault(random.Next(0, gallery.Images.Count - 1));
        // dodanie poprawnej odpowiedzi do listy odpowiedzi
        question.Answers.Add(new QuestionViewModel.Answer
        {
            AnswerId = gallery.Id,
            Name = gallery.Name
        });
        // liczba brakujących odpowiedzi do pytania
        var answerToTake = random.Next(3, 6) - 1;
        var indexOfCorrectAnswer = _galleryList.IndexOf(gallery);
        // losowe wybranie niepoprawnych odpowiedzi
        var randomFailAnswers = Enumerable.Range(0, _galleryList.Count)
            .Where(n => n != indexOfCorrectAnswer)
            .OrderBy(n => Guid.NewGuid())
            .Take(answerToTake)
            .OrderBy(n => n)
            .Select(n => new QuestionViewModel.Answer
            {
                AnswerId = _galleryList[n].Id,
                Name = _galleryList[n].Name
            }).ToList();
        // dodanie niepoprawnych odpowiedzi do pytania
        question.Answers.AddRange(randomFailAnswers);
        // losowe posortowanie odpowiedzi
        question.Answers = question.Answers.OrderBy(n => Guid.NewGuid()).ToList();
        // zapis id galerii w sesji - posłuży to do sprawdzenia poprawności odpowiedzi, gdy użytkownik
        // prześle odpowiedź
        HttpContext.Current.Session["GalleryId"] = gallery.Id;

        return question;
    }

    public CorrectAnswer CheckAnswer(int answerId, int galleryId)
    {
        var name = _galleryList.First(g => g.Id == galleryId).Name;
        var isCorrect = answerId == galleryId ? true : false;
        var answer = new CorrectAnswer
        {
            NameOfCorrectAnswer = name,
            IsCorrect = isCorrect
        };
        return answer;
    }

    public class CorrectAnswer
    {
        public string NameOfCorrectAnswer { get; set; }
        public bool IsCorrect { get; set; }
    }
}

 

 

Kontroler

Kontroler pełni kluczową rolę we wzorcu architektonicznym MVC. Zapewnia on wsparcie dla widoku, tzn. dostarcza do niego dane, odpowiada na jego żądania oraz przetwarzana dane w nim wprowadzone. Dodawanie nowego kontrolera możliwe jest poprzez użycie prawego przycisku myszy na folderze Controllers, a następnie wybranie pozycji Add -> Controller. W nowo otwartym oknie wybieramy MVC 5 Controller - Empty zatwierdzając przyciskiem Add. Następnie wprowadzamy nazwę HomeController. Nasz nowy kontroler będzie zawierał dwie akcje Index, pierwsza będzie odpowiadać na żądania typu Get, druga natomiast na żądania typu Post.
public class HomeController : Controller
{
    private GalleryService _galleryService = new GalleryService();

    [HttpGet]
    public ActionResult Index()
    {
        var question = _galleryService.GetQuestion();
        return View(question);
    }

    [HttpPost]
    public ActionResult Index(int answerId = -1)
    {
        if (Session["GalleryId"] != null && Session["GalleryId"] is int)
        {
            var galleryId = (int)Session["GalleryId"];
            var answer = _galleryService.CheckAnswer(answerId, galleryId);
            var question = _galleryService.GetQuestion();
            question.Result = answer.NameOfCorrectAnswer;
            question.IsCorrect = answer.IsCorrect;
            return View(question);
        }
        else
            return View(_galleryService.GetQuestion());
    }
}
Pierwsza metoda pobiera z obiektu galleryService losowe pytanie, następnie przekazywane jest ono do widoku. Druga metoda, odpowiada na żądania typu post. Przyjmuje ona jeden parametr, tj. answerId, który domyślnie ma przypisaną wartość -1. . Metoda ta pobiera rezultat sprawdzania poprawności odpowiedzi użytkownika oraz pobiera kolejne, losowe pytanie przekazując je następnie do widoku.

Widok

Pozostało nam jeszcze zdefiniować widok, który będzie odpowiednio prezentował dane dostarczone przez kontroler. W tym celu klikamy prawym przyciskiem myszy na rezultacie zwracanym w metodzie Index kontrolera Home.
projekt3
Następnie z menu kontekstowego wybieramy pozycję Add View. W nowo otwartym oknie odznaczamy pozycję Use a layout page:

projekt4

Do utworzonego pliku wklejamy zawartość poniższego listingu.
@model Quiz.ViewModels.QuestionViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Co to za gra?</title>
</head>
<body>
    @if (Model.Result != null)
    {
        <h2>Poprawna odpowiedź to: @Model.Result</h2>
        if (Model.IsCorrect)
        {
            <h3>Brawo! Udzieliłeś poprawnej odpowiedzi</h3>
        }
        else
        {
            <h3>Niestety! Nie udzieliłeś poprawnej odpowiedzi</h3>
        }
    }
    <h2>Co to za gra?</h2>
    <img src="@Url.Content(Model.ImagePath)" width="500" height="280" />
    @using (Html.BeginForm("Index", "Home"))
    {
        foreach (var answer in Model.Answers)
        {
            <input type="radio" name="answerId" value="@answer.AnswerId" />
            <label>@answer.Name</label>
            <br />
        }
        <input type="submit" value="Sprawdź!" />
    }
</body>
</html>
Nasz widok zawiera definicję modelu widoku (pierwsza linia kodu), który zostanie do niego przekazany z metody akcji. Możemy zauważyć, iż zastosowany silnik Razor umożliwia połączenie kodu C# z kodem HTML, poprzez użycie znaku @ przed kodem języka C#. Przykładowy fragment kodu:
@using (Html.BeginForm("Index", "Home"))
{
    foreach (var answer in Model.Answers)
    {
        <input type="radio" name="answerId" value="@answer.AnswerId" />
        <label>@answer.Name</label>
        <br />
    }
    <input type="submit" value="Sprawdź!" />
}
Kod ten tworzy formularz, który zostanie przekazany metodą post do akcji Index kontrolera Home. Zawierać on będzie listę odpowiedzi oraz przycisk służący do przesyłania formularza.
Po wykonaniu wszystkich opisanych w artykule kroków, struktura projektu przedstawia się następująco:
solucja3
W ten sposób utworzyliśmy prostą aplikację w technologii ASP.NET MVC. Wykorzystanie wspomnianej technologii umożliwia proste tworzenie oraz rozbudowywanie aplikacji webowych. W łatwy sposób możemy rozdzielić logikę biznesową oraz logikę prezentacji. Zachęcamy do szerszego poznania przedstawionej w artykule technologii.
Liczba ocen: 20 | Średnia ocen: 4.31

Czytaj także

 

Skomentuj

Twój komentarz
Dodaj

Komentarze

Nasz Fanpage

Popularne treści

  • .NET  
  • 3D  
  • 8  
  • ActiveDirectory  
  • AJAX  
  • amazon web services  
  • Android  
  • Android Market  
  • AngularJS  
  • Animacja  
  • API  
  • aplikacje  
  • Aplikacje wielojęzyczne  
  • asembler  
  • ASHX  
  • ASP.NET  
  • ASP.NET MVC  
  • assembler  
  • Automated Installation Kit  
  • Azure  
  • bezpieczeństwo  
  • bing  
  • Blender  
  • C#  
  • certyfikat  
  • chmura  
  • cloud computing  
  • cmd  
  • Cmdlet  
  • Cmdlet’ów  
  • core  
  • CSS  
  • Cycles  
  • developer  
  • Entity Framework  
  • Expression Blend  
  • fitl  
  • google  
  • google app engine  
  • googlemaps  
  • GPU  
  • Grafika  
  • GroupPolicy  
  • hamachi  
  • hyperv  
  • hyper-v  
  • IaaS  
  • ImageX  
  • instalacja aplikacji  
  • interface  
  • interfejs  
  • Iron Speed  
  • java  
  • JavaScript  
  • jQuery  
  • Kinect  
  • Knockout  
  • kolokacja  
  • konsola  
  • LINQ  
  • LINQ to SQL  
  • Linux  
  • MakeCert  
  • maps  
  • microsoft  
  • mobile  
  • moduły  
  • MVC  
  • mySQL  
  • OpenSource  
  • openstreet  
  • openvpn  
  • PaaS  
  • partycja  
  • PHP  
  • pliki apk  
  • pon  
  • powershell  
  • preview  
  • programowanie  
  • przeglądarka  
  • przetwarzanie w chmurze  
  • przewodnik  
  • Qt  
  • RAD  
  • Rendering  
  • SaaS  
  • script  
  • SDK  
  • server  
  • serwer  
  • Skalowanie  
  • SQL  
  • Systemy operacyjne  
  • światłowody  
  • Światłowód  
  • Template  
  • ubuntu  
  • virtual  
  • Visual Studio  
  • vpn  
  • WAIK  
  • WCF  
  • WebAdministration  
  • WebApi  
  • Windows  
  • windows azure  
  • Windows PE  
  • Windows Phone  
  • WinFroms  
  • wirtualizacja  
  • WPF  
  • XAML  
  • zdalny  
  • zdjęcia  
Komu polecasz tą stronę? (email)
Poleca (twoje imie/pseudonim)
Treść (opcjonalnie) Do Twojej treści zostanie dodany link polecanej strony
POLECAM