3 ASP.NET MVC Podstawy 1
1. Cel zajęć Celem zajęć jest zapoznanie się z podstawami ASP.NET MVC 2.0 Framework. 2. Zadanie Proszę zbudować prostą aplikację WWW przy zastosowaniu framework a ASP.NET MVC 2.0 W tym celu należy wykonać odpowiednie kroki: I. Stworzenie projektu a) Tworzymy nowy projekt b) Jako typ projektu wybieramy ASP.NET MVC 2 Web Application z grupy Web c) W kolejnym oknie, w którym decydujemy czy chcemy stworzyć również projekt do testowania aplikacji wybieramy opcję No, do not create a unit test project. 2
II. Stworzenie bazy danych a) Do katalogu App_data dodajemy nową bazę (SQL Server Database), którą nazywamy np. Kontakty. b) Dodajemy do bazy danych tabele, zgodnie z diagramem poniżej: Adresy Column Na... Data Type Allow Nulls ID Ulica varchar(100) NrDomu NrMieszkania KodPocztowy varchar(6) Miejscowosc varchar(100) TypAdresu varchar(100) IDOsoby FK_Adresy_Osoba Osoba Column Name Data Type Allow Nulls ID FK_Telefony_Osoba Imie varchar(100) Telefony Column Name Data Type Allow Nulls DrugieImie Nazwisko varchar(100) varchar(100) ID NrTelefonu TypNumeru varchar(50) IDOsoby III. Stworzenie modelu a) Do katalogu Model dodajemy mapowanie LinqToSql. b) Następnie w tym samym katalogu proszę stworzyć klasę oraz erfejs zgodnie z kodem przedstawionym poniżej: public class OsobaModel public ID get; set; public string Imie get; set; public string DrugieImie get; set; public string Nazwisko get; set; public erface IOsobaUslugi List<OsobaModel> ZwrocOsoby(); OsobaModel ZwrocOsobyWgID( ID); void DodajOsobe(OsobaModel osoba); void EdytujOsobe(OsobaModel osoba); void UsunOsobe(OsobaModel osoba); 3
c) Proszę następnie o zdefiniowanie klasy np. OsobaUslugi, która implementuje powyższy erfejs. d) Kolejnym krokiem, jest stworzenie podobnych klas dla tabeli Telefon. Jedna z klas powinna implementować poniższy erfejs: public erface ITelefonUslugi List< <TelefonModel> PobierzTelefonyDlaOsoby( IDOsoby); TelefonModel PobierzTelefonWgID( ID); void DodajNumer(TelefonModel telefon); void EdytujNumer(TelefonModel telefon); void UsunNumer(TelefonModel telefon); IV. Stworzenie kontrolerów a) Otwieramy okno Solution Explorer. b) Klikamy prawym przyciskiem myszy na katalogu Controllers i wybieramy opcję Add > New Controller c) W wyświetlonym oknie dialogowym podajemy nazwę nowego kontrolera OsobaController oraz zaznaczamy opcję Add action methods for Create, Update, Delete and Details scenarios. Dzięki tej zaznaczeniu tej opcji Visual Studio wygeneruje dla nas szablon dla podstawowych akcji pozwalających m. in. na dodwanie, edycję i usuwanie danych. 4
d) Kod wygenerowanej klasy przedstawia się następująco: public class OsobyController : Controller public ActionResult Index() public ActionResult Details( id) public ActionResult Create() ❶ [HttpPost] public ActionResult Create(FormCollection collection) try return RedirectToAction("Index"); catch ❷ public ActionResult Edit( id) [HttpPost] public ActionResult Edit( id, FormCollection collection) try return RedirectToAction("Index"); catch public ActionResult Delete( id) 5
[HttpPost] public ActionResult Delete( id, FormCollection collection) try return RedirectToAction("Index"); catch Państwa zadaniem obecnie będzie wypełnienie poszczególnych metod, odpowiednim kodem. Należy zwrócić uwagę na fakt, że niektóre metody mają te same nazwy (np. ❶,❷). Pierwsza z nich (❶) wywoływana jest przed danym działaniem (w tym przypadku stworzeniem em artykułu) i ma za zadanie stworzenie oraz zwrócenie użytkownikowi odpowiedniego widoku (np. formularz do wprowadzania danych). Druga jest wywoływana po przesłaniu przez użytkownika danych i w większości przypadków odpowiada za wywołanie funkcji modyfikującej zawartość bazy danych. Ponieważ akcje są wywoływane na podstawie nazwy, aby możliwe było ich rozróżnienie, konieczne jest oznaczenie jednej z nich za pomocą atrybutu [HttpPost]. Atrybut ten określa, że dana metoda może być wywołana tylko jeżeli żądanie zostało przesłane za pomocą metody POST. W przypadku, gdy metoda nie posiada tego atrybutu może być wywołana tylko jeżeli żądanie za pomocą metody GET. e) Proszę o zmodyfikowanie wygenerowanego szablonu zgodnie z kodem przedstawionym poniżej: public class OsobaController : Controller IOsobaUslugi _osoby; ITelefonUslugi _telefony; public OsobaController() : this(new OsobaUslugi(), new TelefonUslugi()) public OsobaController( IOsobaUslugi osobauslugi, ITelefonUslugi telefonyuslugi) _osoby = osobauslugi; _telefony = telefonyuslugi; 6
public ActionResult Index() ViewData["Osoby"] = _osoby.zwrocosoby(); ❶ public ActionResult Details( id) OsobaModel osoba = _osoby.zwrocosobywgid(id); ViewData["Imie"] = osoba.imie; ViewData["DrugieImie"] = osoba.drugieimie; ViewData["Nazwisko"] = osoba.nazwisko; ViewData["ID"] = osoba.id; ViewData["Telefony"] = _telefony.pobierztelefonydlaosoby(id); public ActionResult Create() [HttpPost] public ActionResult Create(OsobaModel osoba) try ❷ _osoby.dodajosobe(osoba); return RedirectToAction("Index" "Index"); catch public ActionResult Edit( id) OsobaModel osoba = _osoby.zwrocosobywgid(id); ViewData["Imie"] = osoba.imie; ViewData["DrugieImie"] = osoba.drugieimie; ViewData["Nazwisko"] = osoba.nazwisko; ViewData["ID"] = osoba.id; 7
[HttpPost] public ActionResult Edit( id, OsobaModel osoba) try _osoby.edytujosobe(osoba); return RedirectToAction("Index" "Index"); catch public ActionResult Delete( id) [HttpPost] public ActionResult Delete( id, FormCollection collection) try return RedirectToAction("Index" "Index"); catch ❶ Słownik ViewData pozwala na przesyłanie danych pomiędzy kontrolerem i widokiem, który będzie tworzony w następnym punkcie. Słownik ten przechowuje obiekty typu object, tak więc w widoku konieczne będzie ich zrzutowanie na odpowiedni typ. ❷ Do metod, których zadaniem jest przetwarzanie danych uzyskanych z formularzy HTML, wymagane informacje mogą być przekazane albo za pomocą kolekcji typu FormCollection albo wykorzystać możliwości framework a pozwalające na automatyczne zrzutowanie uzyskanych danych na odpowiedni typ danych. W przypadku kolekcji FormCollection wszystkie informacje przekazywane są tylko w postaci tekstowej, tak więc odpowiednie konwersje należy wykonać samemu. Jeżeli skorzystamy z możliwości ASP.NET MVC Framework należy jedynie pamiętać, aby odpowiednie pola do wprowadzania danych w widoku nazywały się dokładnie tak jak właściwości obiektu przekazywanego jako parametr. 8
V. Stworzenie widoków a) Mając otwarty kod kontrolera, który przygotowaliśmy w poprzednim punkcie proszę kliknąć prawym klawiszem myszy wewnątrz metody public ActionResult Edit( id) i wybrać pozycję Add View. b) W wyświetlonym okienku do generowania widoku poszczególne pola wypełniamy tak, jak na poniższym rysunku Kliknięcie przycisku Add spowoduje wygenerowanie odpowiedniego szablonu pliku z widokiem, który będzie korzystał z pliku zawierającego kod strony typu Master Page ~/Views/Shared/Site.Master. Plik ten zostanie automatycznie umieszczony w odpowiednim katalogu. 9
c) W pliku z widokiem odszukujemy kontrolkę typu Content, której właściwość ContentPlaceHolderID jest ustawiona na wartość MainContent. d) Wewnątrz niej wystawiamy kod naszego formularza pozwalającego na edycję danych: <h2>edit</h2> <form enctype="application/x-www-form-urlencoded" method="post" action="/osoba/edit/<%: ViewData["ID"] %>"> ❶ <input type="hidden" name="id" value="<%: :ViewData["ID"] %>"/> <fieldset> <div class="editor-field"> <label for="imie">imię</label> <input type="text" name="imie" value="<%: ViewData["Imie"] %>"/> </div> <div class="editor-field"> <label for="drugieimie">drugie imię</label> <input type="text" name="drugieimie" value="<%: ViewData["DrugieImie"] %>"/> </div> <div class="editor-field"> <label for="nazwisko">nazwisko</label> > <input type="text" name="nazwisko" value="<%: ViewData["Nazwisko"] %>"/> </div> <div class="editor-field"> <input type="submit" value="ok" /> </div> </fieldset> </form> <div> <a href="/osoba">wróć do listy osób</a> </div> ❶ W powyższym kodzie należy zwrócić uwagę na dwa elementy: adresy w odnośnikach oraz sposób wstawiania danych przekazywanych do widoku z kontrolera. W połączeniach należy wprowadzać trasy w formacie /<nazwa kontrolera>/<nazwa akcji>/<parametry>, natomiast dane, które mają być wygenerowane na stronie powinno się umieszczać wewnątrz specjalnego zestawu znaczników <%: %>. e) Kolejnym krokiem, będzie stworzenie widoku dla akcji Index. W tym celu należy podjąć podobne kroki jak powyżej, wprowadzając oczywiście inny kod (w tym przypadku w instrukcji umieszczony jest kompletny kod strony): 10
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> <%@ Import Namespace="Lab03.Models" %> ❶ <asp:content ID="Content1" ContentPlaceHolderID="TitleContent" Index </asp:content> runat="server"> <asp:content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>index</h2> <a href="/osoba/create/"> ="/Osoba/Create/">Dodaj nową osobę</a> <%if (((List<OsobaModel>)ViewData["Osoby"]).Count > 0) ❷ %> <table> <tr> <th th>imie</th> <th>nazwisko</th> <th></th> </tr> <% foreach (OsobaModel o in (List<OsobaModel>)ViewData[ >)ViewData["Osoby"]) ❸ %> <tr> <td><%: o.imie%></td> <td><%: o.nazwisko%></td> <td> <a href="/osoba/details/<%: o.id %>">Pokaż</a> <a href="/osoba/edit/<%: o.id %>">Edytuj</a> </td> </tr> <% %> </table> <% else %> <div> >Nie wprowadzono jeszcze żadnych osób</div> <% %> </asp:content> ❶ Linijka ta odpowiada za podłączenie do widoku wymaganej przestrzeni nazw. Jest to konieczne, ponieważ do widoku przekazujemy listę obiektów typu Osoba. Należy jednak pamiętać, że poprzez ViewData mogą być tylko przekazywane obiekty typu Object, należy więc dokonać odpowiedniego rzutowania ❸. Bez dołączenia przestrzeni klas w której znajduje się klasa Osoba, rzutowanie to nie było by możliwe. ❷ Sprawdzenie czy przekazana do widoku lista zawiera jakieś obiekty. Jeżeli tak, to generujemy tabelę osób. W przeciwnym przypadku generujemy komunikat Nie wprowadzono jeszcze żadnych osób. Należy zwrócić szczególną uwagę na zestaw znaczników, który został tu zastosowany <% %> Wewnątrz tych znaczników 11
umieszczamy wewnątrz widoku kod C#, który ma zostać wykonany, ale który sam nie generuje fragmentów wynikowego kodu strony WWW. ❸ Ten fragment kodu prezentuje w jaki sposób można w widoku przechodzić po kolekcji danych i dla każdego obiektu z tej kolekcji generować np. wiersz w tabeli. f) Proszę rozbudować stronę Master Page, aby możliwy był z niej dostęp do generowanej strony. Należy dołączyć do niej (np. jako pozycję menu) odnośnik do kontrolera OsobaController VI. Zadania do samodzielnego wykonania 1. Proszę stworzyć pozostałe, brakujące widoki. a. Widok do akcji Create będzie bardzo podobny do widoku z akcji Edit. Nie będzie zawierał tylko fragmentów pozwalających na umieszczenie treści wewnątrz generowanych kontrolek. b. Widok dla akcji Details powinien wyświetlać szczegółowe informacje o osobie w tym odpowiednie adresy i numery telefonów. 2. Proszę dopisać kod brakujących akcji Delete. 3. Proszę stworzyć kod pozwalający na dodawanie, modyfikowanie i usuwanie numerów telefonów i adresów. Dla każdego z tych elementów powinien być stworzony osobny kontroler i zestaw widoków. 4. Jeżeli ktoś nie skończy tworzenia tej aplikacji na zajęciach, bardzo proszę o dokończenie jej w domu i przyniesienie na następne laboratorium, gdyż będzie ona modyfikowana. 12