ASP.NET MVC #3 – Widoki

Poprzednio dowiedziałeś się jak dodać własny kontroler w aplikacji. Dzisiaj porozmawiamy trochę o widokach i layoutach. Postanowiłem podzielić temat na dwa podtematy ponieważ materiał jest obszerniejszy. W tej części powiem jak zbudowany jest widok i co to są layouty. W kolejnej, uzupełniającej, dowiesz się jak poskładać nieźle wyglądającą stronę z użyciem biblioteki Bootstrap, wtedy też nasza aplikacja zacznie nabierać kształtu.

W poprzedniej części skupiliśmy się na temacie kontrolerów. Jednak żeby przetestować to co wtedy tworzyliśmy trzeba było dodać pierwsze widoki. Nasz widok nie był szczególnie interesujący ponieważ zawierał tylko jeden tekst. Czas to zmienić.

Fundamenty wizualne

Jednak zanim zaczniemy wypełniać poszczególne widoki treścią zacznijmy od tego w jaki sposób właściwie całość działa. Mam nadzieję, że zauważyłeś po dodaniu swojego pierwszego widoku w aplikacji, że mimo iż nie zawierał on praktycznie nic to jednak po uruchomieniu widoczny był nie tylko wpisany przez nas tekst ale też cała otoczka w postaci m.in. menu górnego. Jak to możliwe? Odpowiedzią są layouty.

Co to ten layout?

Layouty w ASP.NET MVC są to pewnego rodzaju kontenery na treść. Jednocześnie są to po prostu specyficzne widoki wykorzystywane przez inne widoki. Definiują one wygląd strony niejako naokoło treści. Zakładam, że znasz HTMLa. Pamiętasz zapewne, że w jego strukturze poza częścią <body>, w której pojawia się treść jest też chociażby sekcja <head> z metadanymi. W layoutach zazwyczaj ląduje właśnie ten <head> i cała reszta elementów, które się nie zmieniają w ramach jednego widoku. Po prostu layout jest to część kodu HTML, która jest wspólna dla wielu widoków. Dobrym elementem, który można zapakować do layoutu jest menu aplikacji. Nie zmienia się ono na przestrzeni kolejnych podstron, ewentualnie jest różne dopiero na poziomie np. zalogowanego i niezalogowanego użytkownika.

W szablonie aplikacji ASP.NET MVC, który użyliśmy w naszym projekcie istnieje jeden layout. Znajduje się on w pliku _Layout.cshtml i znajdziesz go w folderze Views/Shared/. Jego zawartość wygląda tak:

Na pierwszy rzut oka wygląda przerażająco. Znając HTMLa po chwili zobaczysz tutaj jego podstawową strukturę. Jednak oprócz tego widać tutaj dziwne fragmenty zaczynające się od znaku @. O nich powiemy sobie za chwilę omawiając same widoki.

W tym momencie ważne dla Ciebie będą dwa elementy:

  • struktura menu, którą mogłeś rozpoznać po nazwach klas. Jest to menu z frameworka Bootstrap. Uruchamiając aplikację widzisz je na samej górze. Od razu widzisz tutaj ideę layoutów. To menu jest zdefiniowane tylko w tym miejscu, a mimo to widzisz je na każdej podstronie aplikacji
  • Linijka z kodem  @RenderBody() . To w tym miejscu doklejana jest treść konkretnych widoków. Jeśli wyświetlisz źródło chociażby naszej prostej podstrony dodanej w poprzedniej części to zobaczysz, że cała zawartość, którą tam napisaliśmy znalazła się właśnie wewnątrz znacznika <div> z klasami  container body-content , w którym to znajduje się nasza metoda  @RenderBody()

Przejdźmy teraz do samych pojedynczych widoków.

Widoku pokaż się!

Najprościej rzecz ujmując widoki to fragment HTMLa z dołożonymi wstawkami w języku C#. Przez to, że pojawia się właśnie ten C# widoki przed wyświetleniem muszą być skompilowane. Za cały proces przetwarzania widoków do stanu nadającego się do wyświetlenia odpowiada silnik Razor. Dodatkowym problemem związanym z koniecznością kompilowania widoków jest fakt, że nie możesz ich od tak otworzyć w przeglądarce otwierając odpowiedni plik z katalogu. Tzn. możesz to zrobić, ale efekt będzie daleki od oczekiwanego.

Skoro widoki w ASP.NET MVC to HTML z wstawkami w C# nic nie stoi na przeszkodzie żeby tego C# nie używać jeśli nie ma takiej potrzeby. Wtedy piszesz zwykły kod HTML, który powinieneś już znać. Jedyna różnica będzie taka, że całość będzie zazwyczaj rozdzielona na co najmniej dwa pliki – layout i konkretny widok.

Gdzie ten C# się ukrył?

Omówimy teraz podstawy wstawiania kompilowanego kodu do struktury HTML. Na potrzeby tej części kursu wymyślmy sobie proste zadanie, które zrealizujemy na naszej stronie /Task/Index (niech się do czegoś przyda póki nie mamy jeszcze konkretnych funkcjonalności ;) ). Niech zadaniem będzie wyświetlenie 5 razy napisu przechowywanego w zmiennej. Dodatkowo przy trzecim razie niech napis będzie opakowany w znacznik div.

Zaczynamy od istniejącego widoku

Już w tym momencie mamy fragment C#. Widzisz ten blok kodu zaczynający się od znaku @? Właśnie tym znakiem dajemy do zrozumienia, że najbliższy blok kodu wymaga kompilacji. W powyższym przypadku mamy do czynienia z blokiem, w którym może się znaleźć wiele instrukcji. Jednak możliwe jest też użycie @ dla pojedynczych wywołań funkcji. Wtedy wystarczy zapis

ViewBag obecny w naszym widoku jest pewnego rodzaju workiem na dane. Jest dynamicznym typem i możemy tam wrzucić czy to z poziomu kontrolera czy widoku dowolne wartości. Jednak przypadki jego wykorzystania powinny być ograniczone do naprawdę dużego minimum dlatego nie będę się nad nim rozwodził dłużej. Nie będziemy z niego korzystali.

A miały być HTMLe…

Zabierzmy się za nasze zadanie.

Po pierwsze potrzebujemy tekstu przechowywanego w zmiennej. Do tego celu wykorzystamy istniejący już blok kodu. Dopisz pod ViewBagiem kolejną linijkę gdzie do zmiennej o nazwie text przypiszesz jakąś wartość:

Pamiętaj, że jest to C# dlatego w bloku kodu poszczególne instrukcje muszą się kończyć średnikiem. Możesz teraz uruchomić aplikację, żeby przekonać się, że na razie nic nowego nie zostanie wyświetlone i jednocześnie całość „wstanie”. Ponieważ będziemy pracować na widoku to nie ma konieczności wyłączania aplikacji przed wprowadzaniem zmian. Od tej pory wystarczy, że zapiszesz plik i odświeżysz stronę – zmiany zostaną wcielone w życie.

Kolejny element rozwiązania to pętla for, która wykona się 5 razy. Załóżmy, że nasz tekst będzie się wyświetlał poniżej istniejącego nagłówka.

Ponieważ for wyznacza blok kodu dlatego wystarczy użyć @ przed nim. Jak zapiszesz zmiany i odświeżysz stronę to nadal nie zobaczysz żadnych nowości ;)

Pora żeby w końcu coś się pokazało na ekranie. Wyświetlmy więc nasz tekst 5 razy.

Po odświeżeniu strony pojawi się on na ekranie.

Dlaczego mimo, że użycie zmiennej text znajduje się w bloku kodu użyłem znaku @? Jest to konieczne jeśli chcemy coś wyświetlić. Inaczej kompilator potraktowałby tą linię jako jakąś operację i dostałbyś błąd, że nie jest to żadna instrukcja, wywołanie metody itd.

Został nam ostatni klocek rozwiązania – warunek, który pozwoli dodać znacznik <div> przy trzecim przejściu pętli.

Jak widzisz if nie musi być już poprzedzony znakiem @ ponieważ nie jest próbą wyświetlenia czegoś. Dodatkowo zwróć uwagę, że wstawienie kodu HTML w bloku C# nie wymagało żadnej dodatkowej gimnastyki. Haczyk tutaj jest taki, że jeśli byś w tym divie chciał znowu wstawić np. instrukcję warunkową to musiałbyś ją poprzedzić znakiem @. Jest tak dlatego, że kod HTML rozpoczyna kolejny nie-sisharpowy blok. Dlatego jeśli przez naszym ifem pojawił by się jakiś fragment HTMLa to sam if musiałby się rozpoczynać od @.

Po odświeżeniu strony powinieneś zobaczyć poniższy widok:

A po zbadaniu źródła strony widać, że znacznik div faktycznie tam został raz dodany:

Wróćmy do początku

Teraz mając tą wiedzę możesz ponownie spojrzeć na kod layoutu pokazany na początku. Zapis  @RenderBody()  o którym wspominałem jest po prostu wywołaniem dostępnej we frameworku metody stworzonej na poziomie .NETa.

W poprzedniej części powiedziałem Ci jak ASP.NET MVC szuka widoków na podstawie nazw kontrolerów i akcji. Nie musiałeś pisać nazwy widoku, wystarczyło, że umieściłeś go w odpowiednim miejscu.

Czasami jednak przychodzi potrzeba użycia widoku o innej nazwie. Przykładowo chcesz wykorzystać ten sam formularz dla tworzenia nowego i edytowania istniejącego wpisu (tak naprawdę przykład słaby bo taka możliwość jest fajna tylko na początku :P ). W takim wypadku możesz powiedzieć frameworkowi, żeby przy zwracaniu widoku strony użył nie tego, który wynika z nazw w kontrolerze, ale tego podanego przez Ciebie.

Aby to zrobić wystarczy, że do metody View() przekażesz nazwę widoku. Jest tylko jeden dodatkowy motyw, który trzeba zapamiętać. Jeśli podajesz widok z katalogu /Views/Shared/ wystarczy podać nazwę pliku. Jeśli zaś podajesz widok z innego kontrolera musisz podać całą ścieżkę, łączenie z rozszerzeniem pliku.

Tak więc chcąc zwrócić widok Error.cshtml, który znajduje się w katalogu Shared wystarczy napisać:

Jednak już dla widoku Contact.cshtml znajdującego się w folderze innego kontrolera zapis będzie wyglądał tak:

Znak tyldy na początku stringa oznacza główny katalog aplikacji.

Podsumujmy

Ta część była pierwszą częścią dotyczącą widoków. Potraktuj to jako wprowadzenie w temat. Konkretnym projektem zajmiemy się już niebawem. Nie chciałem żeby ten wpis był długości małej książki :P

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *