środa, 18 lipca 2012

ASP.NET MVC

Zgodnie z zaleceniami w komentarzach w jednym z poprzednich postów ruszyłem w stronę MVC.
Opiszę poniżej czego dowiedziałem się wczoraj i postaram się tym samym wprowadzić w MVC tych, którzy nie mieli jeszcze z tym do czynienia.
Ja osobiście z modelem MVC miałem do czynienia już wcześniej gdy pisałem jeszcze w PHP używając Zend Frameworka.

Po pierwszym spotkaniu z MVC w ASP.NET wydaje mi się przyjemniejszy niż w Zendzie.

  • Co to znaczy MVC?
  • To znaczy Model, View, Controller
  • Co oznaczają te słowa?
  • Oznaczają to że całą stronę dzielimy na 3 części. Poruszanie się po stronie nie przypomina już odwoływania się do kolejnych plików i renderowania ich zawartości.
  • Więc jak to działa?
  • Można sobie wyobrazić tak, że wszystkie żądania naszej strony (obojętnie czy wchodzimy na stronę główną czy jakąś tam inną stronę "kontakt", "portfolio" czy jakąkolwiek inną) przechodzą przez zawsze ten sam punkt, który decyduje co robić dalej. (mechanizm trasowania)
  • Po co to?
  • Żeby ułatwić sobie pracę przy utrzymywaniu i rozbudowaniu serwisu. Dzięki stosowaniu kilku zasad i rozdzieleniu strony na moduły można łatwiej nią zarządzać. Wszystko jest poukładane dzięki rozdzieleniu strony na Modele, Widoki i Kontrolery.
  • Co to jest Model?
  • Jest to zestaw klas opisujących dane, na których pracuje aplikacja. Wszystko co związane z dostępem do danych oraz ich modyfikacji (reguły biznesowe).
  • Co to jest Widok?
  • Jest tym co widzi użytkownik. Jest częścią odpowiedzialną tylko i wyłącznie za pokazywanie wyników, przetworzonych danych, które otrzymał do wyświetlenia. No i oczywiście za wszystkie bajery które użytkownik widzi i może wchodzić z nimi w interakcję (interfejs użytkownika).
  • Co to jest Kontroler?
  • Jest to zestaw klas, który ma za zadanie łączenie modelu i widoku. Odpowiada za przepływ działań w aplikacji.

"Teoretyczny przykład"

  • Wchodzę na swoją stronę np jakaśstrona.pl/projekty/asp/10
  • Co "zobaczy" ASP.NET MVC ? Coś takiego:
  • Znajdź kontroler projekty
  • Znajdź metodę asp
  • Prześlij do niej parametr 10 co odpowiada wyświetleniu 10tego (np jakiegoś fikcyjnego) projektu
Kontrolerem jest jakaś klasa, która zawiera metody. Wpisując taki adres jak wyżej, zostaje on rozpoznany przez mechanizm trasowania i znajdowany jest właśnie ten jeden określony kontroler i z niego wywoływana jest metoda (do której przesyłany zostaje parametr będący na samym końcu adresu).

W wyniku wykonania tej metody, jej rezultat przesyłany jest do widoku który wyświetla tylko już gotowe przesłane do niego wyniki. 

Oczywiście wewnątrz metody kontrolera mogą wystąpić odwołania do modelu, który np mógłby pobierać coś z bazy danych. Model możemy wyobrazić sobie jako klasę która reprezentuje jakąś tabelę w bazie danych. Chcąc pobrać coś z bazy wywołujemy jedynie metodę modelu. Cała logika odpowiadająca za połączenie z bazą i zapytania SQL zawiera się właśnie wewnątrz tej klasy/jej metod.

Powinno być już tutaj bardziej widać podział na 3 części.

"Praktyczny przykład"


Nie owijając dalej w bawełnę, pokażę jak "ruszyć" pierwszy projekt MVC.
Od teraz zakładam że każdy wie jak utworzyć projekt i dodawać do niego istniejące lub nowe pliki ;)

Odpalamy VisualStudio,
Tworzymy nowy projekt, o taki:


Ponieważ nie chcemy (jeszcze) robić testów jednostkowych, w następnym oknie zaznaczamy


Po utworzeniu projektu i odpaleniu go (F5) zobaczymy szkielet strony. Klikając w "About" zobaczymy, że pasek adresu w przeglądarce zmienił się na mniej więcej taki: http://localhost:50843/Home/About. 
Tak jak pisałem wcześniej: Wyszukiwany jest kontroler Home i wykonywana jest jego metoda About.

Sprawdźmy czy aby na pewno.

Rzućmy okiem na Solution Explorer.


Mamy foldery Models, Views, Controllers. Chyba nazwy same sugerują co należy tam umieszczać :)
Otwórzmy HomeController. Co widzimy w środku?

public ActionResult About()
{
    return View();
}

No i mamy naszą metodę About.

Kilka uwag co do konwencji

  • Wszystkie nazwy plików wewnątrz folderu Controllers muszą się kończyć na "Controller"
  • W folderze Views każdy kontroler ma swój własny folder z widokami. Nazwy folderów nie zawierają już końcówki "Controller".
  • W tych folderach, pliki .aspx reprezentują widoki. To one są renderowane i wyświetlane po przejściu przez metodę kontrolera.
A co z "Home"? Przecież klikając na Home nie mamy adresu http://localhost:50843/Home/Index tylko http://localhost:50843/.

Racja. Otwórzmy więc plik Global.asax.
Jest to plik w którym definiowane są "ścieżki" naszej aplikacji.
Widzimy w środku funkcję:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

Widać z grubsza co ona "robi".
Mamy tutaj coś takiego jak MapRoute(...). określona jest tutaj ścieżka, która zawiera w sobie najpierw nazwę kontrolera, później nazwę akcji (metody kontrolera) i parametr "id". Jak na razie nasza strona rozpoznaje tylko taki rodzaj adresu. Własnie tutaj możemy zdefiniować inne ścieżki oraz dodawać wiele innych parametrów. Dalej mamy ustawiony domyślny kontroler akcję oraz parametr, który jest pomijany. Dzięki temu po wejściu na "Home" mamy "czysty" URL.

Wróćmy do pliku HomeController.cs.
Za co odpowiada ViewData["Message"] = "Welcome to ASP.NET MVC!"; ?
Żeby się tego dowiedzieć musimy otworzyć Views/Home/Index.aspx.

Znajdziemy tam linijkę

<h2><%: ViewData["Message"] %></h2>

Widać że odwołuje się do tego samego "elementu".


ViewData jest typem ViewDataDictionary a więc jest słownikiem. Można go używać jak tablicy, do której w kontrolerze w pole "Message" przypisujemy "Welcome to ASP.NET MVC!" aby potem odczytać je w widoku. Zamiast Message możemy wpisać jakiś inny string np "komunikat" czy cokolwiek. Wiemy o co chodzi...



Odnośnie komentarza mgibas w moim wcześniejszym poście, również polecam zainteresowanie się  materiałami Scotta Hanselmana. Sam się właśnie za nie zabieram. Nawet wczoraj w swojej nieszczęsnej książce do ASP.NET w rozdziale właśnie o MVC było o nim wspomniane (nawet jest on jednym z autorów oryginału tej książki), tym bardziej wzbudził moje zanteresowanie.

sobota, 14 lipca 2012

ASP Wiązanie danych cz. 2

W dzisiejszym poście przedstawię kontrolkę LinqDataSource oraz sposób jej implementacji w projekcie Web Site oraz Web Application.

LinqDataSource odwołuje się do bazy danych inaczej niż SqlDataSource. Nasza dzisiejsza kontrolka do pracy potrzebuje obiekt kontekstu. Zanim pokażę jak go utworzyć potrzebujemy znowu jakieś przykładowe dane. Tym razem nasze dane utworzymy sami:

Tworzymy nową aplikację Asp.NET Empty Web Application:


Następnie w Solution Explorerze klikamy prawym przyciskiem na nazwę projektu i wybieramy Add->Add ASP.NET Folder-> App_Data. Na poniższym screenie jest na szaro ponieważ już dodałem go do swojego projektu.

App_Data jest to jeden ze specjalnych folderów dla ASP.NET. W nim będzie przechowywana nasza baza danych, którą teraz utworzymy:
Klikamy w Solution Explorerze na App_Data prawym i dajemy kolejno Add->New Item...
Wybieramy SQL Server Database


Po dodaniu nowej bazy danych będzie ona widoczna w oknie Solution Explorera. Rozwijamy zatem drzewo naszej bazy i klikamy prawym na Tables i wybieramy Add New Table:


Po wybraniu tej opcji ukaże nam się projektant tabeli, gdzie możemy ustalić jej kolumny, typ przechowywanych danych i wiele innych rzeczy. Ja ustawiłem w swoim przypadku taką strukturę:


Pierwsza kolumna oznacza w moim przpadku identyfikator filmu i jest oznaczona jako klucz główny tabeli. Dzięki temu każdy wiersz będzie miał odmienną wartość MovieID, która zresztą będzie się zwiększała automatycznie (przekonamy się o tym przy wprowadzaniu danych).
Myślę że nie trzeba tłumaczyć jak wprowadzać dane do projektanta. Dopiszę tylko, że klucz główny ustawia się po kliknięciu prawym przyciskiem np na nazwie kolumny. Zapiszmy naszą tabelę.

Teraz kliknijmy prawym przyciskiem w Solution Explorerze na dopiero co utworzonej nowej tabeli i wybierzmy opcję Show Table Data. Uzupełnijmy ją jakimiś wartościami. Dla przykładu moje bezsensowne dane wyglądają tak: :)


Po zapisaniu zmian mamy już na czym eksperymentować. Teraz zajmiemy się utworzeniem obiektu kontekstu.
W projekcie Web Application tworzy się go inaczej niż w projekcie Web Site.
Musimy dodać do naszego rozwiązania nowy projekt class library. Klikamy w Solution Explorerze na nasze rozwiązanie (Solution) i dalej: prawy przycisk myszy -> Add -> New Project i wybieramy Class library.


W projekcie usuwamy automatycznie wygenerowany plik .cs i klikając na nowo dodanym projekcie prawym przyciskiem wybieramy Add->New item -> LINQ to SQL Classes


Do nowo utworzonego projektanta przeciągamy teraz naszą tabelę z Server Explorera i... tyle. Obiekt kontekstu został utworzony automatycznie.


Dodawanie kontrolki LinqDataSource

W projekcie naszej aplikacji (a nie w projekcie obiektu kontekstu) dodajmy nowy plik Web Form. Dodajmy także referencję do biblioteki z naszym obiektem kontekstu (pamiętając najpierw o skompilowaniu go).

Otwórzmy teraz nasz plik Web Form z rozszerzeniem .aspx. Z Toolboxa przeciągnijmy do niego LinqDataSource (znajdziemy tą kontrolkę pod zakładką Data w Toolboxie).


Przejdźmy na widok Design lub Split i z menu inteligentnych znaczników wybierzmy Configure Data Source

Jeśli wszystko wykonaliśmy do tej pory poprawnie to w oknie kreatora będziemy mieli widok podobny do tego:

Klikamy Next, w następnym oknie wybieramy naszą tabelę jeśli jeszcze nie została wybrana automatycznie i dajemy Finish. Znaczniki naszej kontrolki zostaną zmodyfikowane automatycznie. Dodatkowo uzyskamy możliwość zaznaczenia opcji ustawienia dodawania, zmiany i usuwania danych z poziomu strony.


Zaznaczmy wszystkie opcje.

Wyświetlanie danych na stronie

Mając wszystko ustawione spróbujmy wyświetlić dane z tabeli na stronie.
Przeciągnijmy na stronę GridView z Toolboxa.
Podpięcie naszego LinqDataSource do GridView jest banalnie proste. Wystarczy tylko w widoku split lub design włączyć menu inteligentnych znaczników i wybrać odpowiednia wartość Choose Data Source: (w moim przypadku LinqDataSource1).


Widzimy że wygląd kontrolki zmienił się. 
Zaznaczmy w naszym GridView podobnie jak w LinqDataSource dostępne checkboxy:


Trzy ostatnie checkboxy pojawią się tylko wtedy gdy zaznaczyliśmy je także wcześniej w LinqDataSource.

Zostało nam tylko uruchomić projekt (F5) i zobaczyć jak wszystko działa.
(Zamiast GridView możemy wybrać inną kontrolkę do prezentowania danych np DetailsView)

Zmiany dla projektu Web Site

W projekcie Web Site wszystko robimy niemal identycznie poza dodawaniem obiektu kontekstu.
Nie tworzymy nowego projektu Class Library i nie dodajemy referencji do naszego głównego projektu tak jak wcześniej. Zamiast tego wszystko odbywa się w jednym projekcie Website.
Musimy dodać do projektu jedynie jeden ze specjalnych folderów ASP.NET App_Code który jest dostępny jedynie dla projektu Web Site.


Do tego folderu dodajemy dopiero LINQ to SQL Classes i robimy wszystko dalej tak samo jak w projekcie Web Application.

Struktura projektu powinna wyglądać mniej więcej tak:


czwartek, 12 lipca 2012

ASP Wiązanie danych cz. 1

Ponieważ ostatnio zajmuję się ASP.NET postanowiłem napisać parę postów odnośnie wiązania danych. Tak więc lecimy:

ASP.NET idzie nam na rękę jeśli chodzi o połączenia z bazami danych. Nie trzeba pisać tak dużo zbędnego kodu jak to miało miejsce wcześniej. W tym poście zaprezentuję kontrolkę SqlDataSource która umożliwia uzyskanie dostępu do dowolnego źródła danych (należącego do grupy dostawców ADO.NET). Domyślnie kontrolka ta posiada możliwość współpracy z dostawcami ODBC, OLE DB, SQL Server, Oracle, SQL Server CE.

Zanim przejdziemy do rzeczy, najpierw pobierzmy jakieś dane które będziemy mogli powiązać. Posłużę się tutaj przykładem z książki z której w dalszym ciągu korzystam przy pisaniu stron ASP.NET i zaproponuję pobranie bazy danych Northwind. Jest to przykładowa baza danych dostępna na stronach Microsoftu do ściągnięcia. Dostępna jest pod adresem http://www.microsoft.com/en-us/download/details.aspx?id=23654


Po ściągnięciu instalatora i domyślnej instalacji powinniśmy na dysku C mieć folder SQL Server 2000 Sample Databases a w nim pliki:


Mamy już wszystko co potrzebne. Odpalamy teraz Visual Studio i tworzymy pusty projekt aplikacji ASP.NET:


Do projektu dodajmy nowy element (new item) Web Form


Otwórzmy go i przeciągnijmy do niego kontrolkę SqlDataSource z Toolboxa. Powinna pojawić sie taka linijka:

<asp:sqldatasource id="SqlDataSource1" runat="server"></asp:sqldatasource>

Tworzenie połączenia z bazą danych jest proste dzięki kreatorowi do którego można się dostać gdy mając ustawiony widok Design albo Split klikniemy na:



Pojawi się nowe okno gdzie wystarczy wskazać bazę danych do której chcemy się połączyć:


Jednak może się tak zdarzyć że nie mamy czego tam wybrać. Możemy zatem utworzyć nowe połączenie klikając na przycisk New Connection...

Zakładam że SQL Server jest zainstalowany na komputerze (w moim przypadku instalowany był razem z VisualStudio). Jeśli tak nie jest należy zainstalować SQL Server.

Okno, które nam się pojawiło w moim przypadku należało uzupełnić tak jak na poniższym screenie:


Klikamy OK i powinniśmy mieć do wyboru bazy danych naszego serwera. Jednak jeśli nie ma tam jeszcze NORTHWIND'a dajmy na razie Cancel i przejdźmy do Server Explorera



Kliknijmy prawym przyciskiem myszy na Data Connections a następnie Add Connection. Okno które wyskoczy uzupełniamy identycznie jak 2 screeny wyżej z tym że w sekcji Connect to a database zaznaczamy Attach a database file:. Następnie klikając na Browse wskazujemy nasz plik NORTHWIND.mdf i zatwierdzamy wszystkie okna. Po rozwinięciu Data Connections w Server Explorerze powinna nam się już pokazać nasza baza danych.

Więc wróćmy do okna "Choose Your Data Connection" i wybierzmy Northwinda:


Klikamy Next i widzimy następujące okno:


Tutaj możemy wybrać tabelę z jakiej chcemy wyświetlać dane lub wywołać niestandardowe polecenie SQL. Jeśli zdecydujemy się na wybranie jednej tabeli możemy zaznaczyć potrzebne nam kolumny lub gwiazdkę (tak jak na powyższym screenie) która oznacza wszystkie kolumny. Dodatkowo mamy jeszcze po prawej stronie przyciski WHERE gdzie możemy ustawiać warunki dla naszego zapytania SQL (np żeby wybierał tylko te wartości z tabeli gdzie w jakiejś kolumnie wartośc jest np większa od 5), ORDER BY gdzie ustalamy kolejność wyświetlania znalezionych elementów oraz Advanced gdzie możemy wybrać opcję Generate INSERT, UPDATE, and DELETE statements która pozwoli wygenerować podane instrukcje na podstawie utworzonej instrukcji SELECT.
Kolejna opcja Use optimistic concurrency sprawia że po zaznaczeniu jej, instrukcje UPDATE i DELETE będą tak modyfikowane aby zawierały wartości oryginalne jak i nowe. Dzięki temu, w momencie wykonywania zapytań, dane docelowe będą porównywane z danymi w kontrolce SqlDataSource. Jeśli rekord zmienił się od czasu pobrania go przez kontrolkę to instrukcje UPDATE i DELETE nie zostaną wykonane.

Wybierzmy kilka kolumn i naciśnijmy Next


Możemy sprawdzić wynik wygenerowanego zapytania w następnym oknie przy pomocy przycisku Test Query.


Po kliknięciu na Finish widzimy że nasza kontrolka została nieco zmodyfikowana.

<asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
            SelectCommand="SELECT [CustomerID], [ContactName], [CompanyName], [Country] FROM [Customers]"></asp:SqlDataSource>

Na tym zakończę część pierwszą.
Więcej w części drugiej już wkrótce.