Projektowanie Graficznych Interfejsów Użytkownika. Robert Szmurło



Podobne dokumenty
Infrastruktura aplikacji WWW

MasterPage w ASP.NET

ASP.NET MVC. Podstawy. Zaawansowane programowanie internetowe Instrukcja nr 3

Wzorce prezentacji internetowych

Poznaj ASP.NET MVC. Kamil Cieślak Microsoft Student Partner

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło

1 LINQ. Zaawansowane programowanie internetowe Instrukcja nr 1

Projektowanie Graficznych Interfejsów Użytkownika. Robert Szmurło

Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC

Wzorce logiki dziedziny

ASP.NET MVC. Grzegorz Caban 20 stycznia 2009

MVC w praktyce tworzymy system artykułów. cz. 1

Microsoft.NET: LINQ to SQL, ASP.NET AJAX

Programowanie zorientowane obiektowo. Mateusz Kołecki

Wprowadzenie do programowania aplikacji mobilnych

Wykład 12. Programowanie serwera MS SQL 2005 w C#

Podstawy wzorca MVC MODEL KON- TROLER WIDOK. Odpowiada za wyświetlenie danych użytkownikowi. Zawiera dane aplikacji oraz jej logikę.

Programowanie obiektowe

ASP.NET Wprowadzenie. provided by Przemysław Bykowski

Technologie internetowe ASP.NET Core. Paweł Rajba

Wzorce architektoniczne

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Grzegorz Ruciński. Warszawska Wyższa Szkoła Informatyki Promotor dr inż. Paweł Figat

Microsoft.NET: ASP.NET MVC + Entity Framework (Code First)

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło

Leszek Stasiak Zastosowanie technologii LINQ w

Przygotowanie do nowoczesnego programowania po stronie przeglądarki. (HTML5, CSS3, JS, wzorce, architektura, narzędzia)

Warstwa prezentacji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe.

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Realizacja Aplikacji Internetowych 2013 laboratorium cz. 2 K.M. Ocetkiewicz

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Dostęp do baz danych w ASP.NET.

Aplikacje WWW - laboratorium

Laboratorium 10 - Web Services

Tworzenie i wykorzystanie usług sieciowych

Programowanie obiektowe

Instrukcja laboratoryjna cz.2

Programowanie wielowarstwowe i komponentowe

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Wzorce projektowe cz. II. Wzorce projektowe cz. II 1/35

Zaawansowane aplikacje internetowe - laboratorium

Materiały oryginalne: ZAWWW-2st1.2-l11.tresc-1.0kolor.pdf. Materiały poprawione

Architektura MVC w ASP.NET. Autor wykładu: Marek Wojciechowski

Ćwiczenie 8. Kontrolki serwerowe

Walidacja danych w ASP.NET MVC

Politechnika Poznańska Wydział Budowy Maszyn i Zarządzania

Instrukcja 5 Laboratorium z Podstaw Inżynierii Oprogramowania. Warstwy integracji z bazą danych: Wzorzec DAO Technologia ORM

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło

Tworzenie aplikacji Web Alicja Zwiewka. Page 1

Metody Metody, parametry, zwracanie wartości


Baza danych sql. 1. Wprowadzenie

REFERAT PRACY DYPLOMOWEJ

Budowa aplikacji wielowarstwowych zastosowanie szablonów. Laboratorium 2 Programowanie komponentowe Zofia Kruczkiewicz

PHP 5 język obiektowy

Podstawowe wykorzystanie Hibernate

Zrąb JavascriptMVC. Krzysztof Płocharz. 6 kwiecień Uniwersytet Warszawski

Automatyzacja Testowania w WEB 2.0

Laboratorium 1. Wzorce oprogramowania lab1, Zofia Kruczkiewicz

Forum Client - Spring in Swing

Zaawansowane aplikacje internetowe laboratorium REST

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło

Zaawansowane aplikacje WWW - laboratorium

Walidacja po stronie serwera Walidacja po stronie klienta:

Podstawy programowania III WYKŁAD 6

Programowanie MorphX Ax

Programowanie obiektowe

Platforma.NET laboratorium 4 Aktualizacja: 15/11/2013. Visual Basic.NET dostęp do bazy danych. Baza Microsoft SQL Server Compact

Aplikacja webowa w Javie szybkie programowanie biznesowych aplikacji Spring Boot + Vaadin

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL III TI 4 godziny tygodniowo (4x30 tygodni =120 godzin ),

JavaServer Faces (JSF)

Microsoft.NET: Warstwa dostępu do danych (DAL) w aplikacjach ASP.NET Web Forms

Programowanie obiektowe

xmlns:prism= c. <ContentControl prism:regionmanager.regionname="mainregion" />

MVC w praktyce tworzymy system artykułów. cz. 2

Laboratorium 1 Wprowadzenie do PHP

Programowanie obiektowe

Aplikacje WWW - laboratorium

Spring Web MVC, Spring DI

Aplikacje internetowe i rozproszone - laboratorium

STWORZENIE MOBILNEJ APLIKACJI,

Programowanie obiektowe i zdarzeniowe

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Projektowanie i wdrażanie systemów informatycznych. Dodanie aplikacji klienta uruchamianej przez przeglądarkę kontynuacja projektu:

4 AS SP.NET MVC. Widok. Zaawansowane programowanie internetowe Instrukcja nr 4

Kurs ASP.NET ASP.NET CORE APLIKACJE WEBOWE

Visual Basic.NET ASP.NET + Microsoft SQL Server

Db4o obiektowa baza danych wersja.net

Plik pobrano z Tytuł: Wzorce projektowe, cz. 2 Strategy Ostatnia aktualizacja:

Microsoft.NET: ASP.NET MVC + Entity Framework (Code First)

Ekspert radzi. mechanizm w enova, umożliwiający wskazanie domyślnej drukarki dla danego stanowiska i wydruku. Strona 1 z 8. Ekspert radzi.

Programowanie komponentowe. Przykład 1 Bezpieczeństwo wg The Java EE 5 Tutorial Autor: Zofia Kruczkiewicz

akademia androida Składowanie danych część VI

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Transkrypt:

Projektowanie Graficznych Interfejsów Użytkownika Robert Szmurło 1

Wzorce Web Model View Controller Page Controller każda strona ma własny Front Controller jeden uniwersalny, Interpretujący komendy. Template View 2

Wzorce projektowe Web Na podstawie: Enterprise Solution Patterns Using Microsoft.NET Projekt MVC Page Cache Page Controller Intercepting Filter Front Controller Implementacja Implementacja Pache Cache w ASP.NET Implementacja Page Controller w ASP.NET Implementacja Intercepting Filter w ASP.NET Implementacja MVC w ASP.NET Implementacja Front Controller w ASP.NET 3

MVC cd Struktura Modelu MVC Kontroler Model Widok 4

Model pasywny MVC (wg.net) cd MVC Pasywny :Kontroler :Model :Widok obsłużzdarzenie Uzytkownik uaktualnij wyświ etlda ne podajstan 5

Model aktywny MVC (wg.net) sd MVC.Active Źródło zmian :Model :W idok Tylko poinformuj, że zaszła jakaś zmiana! obsłużzdarzenie() powiadom() uaktualnij() daj AktualneWartości() dane() 6

Model aktywny - obserwator Rozwiązanie problemu zależności Modelu od reszty modułów za pomocą ogólnego interfejsu obserwatora, który jest realizowany przez pozostałe moduły. cd MVC Obserwator Kontroler «realize» Model «interface» Obserwator + uaktualnij() : void «realize» Widok 7

Wady i zalety MVC Zalety Wady Wiele widoków różne strony aplikacji webowej mogą prezentować dane z tych samych obiektów modelu, Zmiany łatwiejsze zmiany zmieniającego się dużo częściej od modelu interfejsu Zależność od platformy Kod interfejsu użytkownika często ściśle zależy od specyficznych cech platformy.. Nadmierne skomplikowanie dodatkowe warstwy oraz rygor niezależności; intensywne wykorzystanie programowania zdarzeniowego, które jest trudne w debugowaniu. Koszt częstych uaktualnień/powiadomień uaktualnienie widoku zabiera formularzowi jakiś czas; gdy model często zmienia swój stan, może zablokować ekran, a przez to uniemożliwić pracę dla użytkownika. 8

Refaktoryzacja SP ==> MVC Prześledzimy proces refaktoryzacji z z wzorca: Single Page Controller do wzorca: MVC Single Page Aplikacja do wyświetlania albumów muzycznych. Widok Kontroler+Model Dane znajdują się w bazie (u nas plik Accessa: baza.mdb) Widok Model Kontroler Refaktoryzacja 1 Refaktoryzacja 2 1. Za pomocą menu rozwijalnego z [listą albumów] użytkownik wybiera album. 2. Użytkownik wybiera opcję Pokaż. 3. System wyświetla [tabelę z utworami] na [wybranym albumie]. 9

Na początek wszystko na stronie 1/2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>album płytowy</title> <script language="c#" runat="server"> void Page_Load(object sender, System.EventArgs e) if (!IsPostBack) String selectcmd = "select * from Plyty"; OleDbConnection myconnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source='c:\\Projekty\\svn\\pgui\\LN_2007\\NET\\baza.mdb'"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd,myConnection); DataSet ds = new DataSet(); mycommand.fill(ds, "plyty"); recordingselect.datasource = ds; recordingselect.datatextfield = "tytul"; recordingselect.datavaluefield = "id"; recordingselect.databind(); Cały kod jest wewnątrz strony ASP.NET void SubmitBtn_Click(Object sender, EventArgs e) String selectcmd = String.Format( "select * from Nagrania where albumid = 0 order by id", (string)recordingselect.selecteditem.value); OleDbConnection myconnection = new OleDbConnection( "Provider=Microsoft.Jet.OLEDB.4.0; Data Source='c:\\Projekty\\svn\\pgui\\LN_2007\\NET\\baza.mdb'"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "nagrania"); MyDataGrid.DataSource = ds; MyDataGrid.DataBind(); Kod uruchamiany podczas ładowania strony. Wypełnia danymi listę rozwijalną z płytami. Model + Kontroler? Kod uruchamiany po wciśnięciu przycisku 'Pokaż'. (czyli jest pewien typ kontrolera) protected void recordingselect_selectedindexchanged(object sender, EventArgs e) </script> </head> Dalszy ciąg tego samego pliku na następnym slajdzie. 10

Na początek wszystko na stronie 2/2 Kod ASP, który wyświetla kontrolki na formularzu. Prezentacja? <body> <form id="form1" runat="server" method="post"> <div> Album płytowy (Atchitektura Jednolita (brak MVC))</div> <br /> Wybierz płytę:<br /> <asp:dropdownlist ID="recordingSelect" runat="server" Width="332px" OnSelectedIndexChanged="recordingSelect_SelectedIndexChanged" AutoPostBack="True"> </asp:dropdownlist> <asp:button ID="Button1" runat="server" Text="Pokaż" Width="99px" OnClick="SubmitBtn_Click" /> <br /> <br /> <asp:gridview ID="MyDataGrid" runat="server" Width="433px"> </asp:gridview> <br /> </form> </body> </html> Kod ten nie podłącza odpowiednich atrybutów kontrolek do źródeł danych. Zajmuje się tym kod 'kontrolera' odwołując się za pomocą ID 11

Demo w Microsoft Visual Studio Single Page 12

Wszystko na stronie - Podsumowanie Zalety Wady Bardzo prosta, Łatwa w implementacji, Łatwo i szybko można wykonać jakiekolwiek zmiany, Kod jest zgromadzony w jednym pliku, przez co mamy nad nim pełną kontrolę. Łatwe kopiuj+wklej Mało pracy! < pozornie, ale dobre do prototypowania Problem z rozdzieleniem zadań między programistów i projektantów HTML, Problemy z powstawaniem błędów, Problem z ponownym użyciem kodu, który zapewnia dostęp do bazy danych. (Na każdej stronie musimy umieszczać kod inicjalizujący połączenie.) 13

Refaktoring 1 (Model+Kontroler) Widok Code Behind w.net każda strona ASP.NET posiada dodatkowy plik z kodem zarządzającym daną stroną ASP. W ten sposób łatwo możemy oddzielić widok od kontrolera-modelu (uwaga, ale nie kontrolera aplikacji). 14

Diagram klas (Model+Kontroler) Widok class ModelWidok.NET _Default Default.aspx Sy s t em.web.ui.p age + Page_Load(object, System.EventArgs) : void + Subm itbtn_click(object, EventArgs) : void «partial» + Button1: asp:butt on + M ydatagrid: asp:gri dview + recordingselect: asp:dropdownlist W pliku: Default.aspx.cs W pliku: Default.aspx Uwaga! Ta notacja nie dotyczy słowa kluczowego partial, dla którego powinniśmy raczej podawać atrybuty w jednej klasie, lub ewentualnie lepiej za pomocą asocjacji. 15

Refaktoring 1 - Widok Co pozostanie w naszym widoku? Plik Default.aspx class ModelWidok.NETa _Default Sy s t em.web.ui.p age + Page_Load(object, System.EventArgs) : void + Subm itbtn_click(object, EventArgs) : void «partial» <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> Album płytowy (Widok-Kontroler)</div> <br /> Wybierz płytę:<br /> <asp:dropdownlist ID="recordingSelect" runat="server" AutoPostBack="True" Width="332px"> </asp:dropdownlist> <asp:button ID="Button1" runat="server" OnClick="SubmitBtn_Click" Text="Pokaż" Width="99px" /> <br /> <br /> <asp:gridview ID="MyDataGrid" runat="server" Width="433px"> </asp:gridview> </form> </body> </html> Default.aspx + Button1: asp:butt on + M ydatagrid: asp:gridview + recordingselect: asp:dropdownlist 16

Zawartość pliku: Default.aspx.cs (czyli Code Behind) Refaktoring 1 - Kontroler+Model using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.OleDb; public partial class _Default : System.Web.UI.Page public void Page_Load(object sender, System.EventArgs e) if (!IsPostBack) String selectcmd = "select * from Plyty"; OleDbConnection myconnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source='c:\\Temp\\baza.mdb'"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "plyty"); recordingselect.datasource = ds; recordingselect.datatextfield = "tytul"; recordingselect.datavaluefield = "id"; recordingselect.databind(); Kontroler, który jest jeszcze nadal zintegrowany z modelem, czyli klasami odwołującymi się do bazy danych. public void SubmitBtn_Click(Object sender, EventArgs e) String selectcmd = String.Format( "select * from Nagrania where albumid = 0 order by id", (string)recordingselect.selecteditem.value); OleDbConnection myconnection = new OleDbConnection( "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\\Temp\\baza.mdb"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "nagrania"); MyDataGrid.DataSource = ds; MyDataGrid.DataBind(); 17

Demo w Visual Studio: Proces refaktoringu projektu Single Page. 18

Refaktoring 2 - Zadanie 1 Stworzyć pełny Model-Widok-Kontroler na podstawie poprzedniego wzoru. Przenieść fragment związany z pobieraniem danych z bazy do osobnej klasy. class MVC.NET Kontroler ModelWidok.NET::_Default System.Web.UI.Page + Page_ Load(obj ect, System.EventArgs) : void + Subm itbtn_ Cli ck(object, EventArgs) : void Model BramaDoBazy + Bram adobazy() + dajnagrani a(string) : DataSet + dajplyty() : DataSet Widok ModelWidok.NET::Default.aspx + Button1: asp:button + M ydatagri d: asp:gri dvi ew + recordi ngsel ect: asp:dropdownlist 19

Co mógłby zawierać kontroler? using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; Tu odwołujemy się do modelu z prośbą o udostępnienie informacji o stanie zbioru z płytami. public partial class _Default : System.Web.UI.Page public void Page_Load(object sender, System.EventArgs e) if (!IsPostBack) recordingselect.datasource = BramaDoBazy.dajPlyty(); recordingselect.datatextfield = "tytul"; recordingselect.datavaluefield = "id"; recordingselect.databind(); Tu odwołujemy się do modelu z prośbą o udostępnienie stanu dotyczącego konkretnej płyty: (string)recordingselect.selecteditem.value public void SubmitBtn_Click(Object sender, EventArgs e) MyDataGrid.DataSource = BramaDoBazy.dajNagrania((string)recordingSelect.SelectedItem.Value); MyDataGrid.DataBind(); 20

Dla leniwych... (rozwiązanie) using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.OleDb; Tworzymy nową klasę i umieszczamy ją w folderze: App_Code public class BramaDoBazy public BramaDoBazy() public static DataSet dajplyty() String selectcmd = "select * from Plyty"; OleDbConnection myconnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source='c:\\Temp\\baza.mdb'"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "plyty"); return ds; public static DataSet dajnagrania(string albumid) String selectcmd = String.Format( "select * from Nagrania where albumid = 0 order by id", albumid); OleDbConnection myconnection = new OleDbConnection( "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\\Temp\\baza.mdb"); OleDbDataAdapter mycommand = new OleDbDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "nagrania"); return ds; Tworzymy obiekt DataSet, który będzie przechować STAN SESJI. Synchronizujemy stan sesji ze STANEM MODELU. W naszym przypadku stan modelu jst w bazie danych. 21

Page Controller - wprowadzenie Odseparowaliśmy model od widoku, czyli interfejs użytkownika od logiki biznesowej. 1. Teraz pora na dodanie dynamicznej nawigacji pomiędzy stronami. Często wciśnięcie tego samego przycisku może poprowadzić użytkownika do różnych stron w następnym kroku. Kasowanie e-maila w kliencie pocztowym nie zaprowadzi użytkownika do strony startowej, lecz najczęściej wyświetli następną wiadomość. Walidacja danych wprowadzonych w formularzu może w wyniku wyświetlić komunikat o błędzie lub przejść do następnego kroku procesu. Itp. 2. Jak zapewnić aby wszystkie strony zawierały wspólny nagłówek Rozwiązanie: można zastosować wzorzec Page Controller z uwzględnieniem dziedziczenia. 22

Page Controller class Page Controller Model + Logika Biznesowa: Page Controller - Obsluz zadanie HT T P (request): - Uaktualnij m odel i zdecyduj o nastepnym widoku: Widok - Wygeneruj HT M L: 23

Eliminacja duplikacji kodu W celu wyeliminowania powtarzających się fragmentów kodu (np. walidacji parametrów) można zastosować kontroler bazowy. class Kontroler Bazowy KontrolerBazowy - Wspolna funkcjonalnosc (m etody): KontrolerStrony_1 - Funkcje specyficzne dla strony 1: KontrolerStrony_2 - Funkcje specyficzne dla strony 2: 24

A automatyczne testy? Problem: Aby wykonać testy naszej aplikacji musielibyśmy uruchamiać serwer aplikacji... class KontrolerBazowyTesty (verte) ModelWidok.NET::_Default System.Web.UI.Page + Page_Load(object, System.EventArgs) : void + Subm itbtn_click(object, EventArgs) : void «partial» ModelWidok.NET::Default.aspx + Button1: asp:button + M ydatagrid: asp:gridview + recordingselect: asp:dropdownlist KontrolerBazowy - Wspolna funkcjonalnosc (m etody): KontrolerStrony_1 - Funkcje specyficzne dla strony 1: KontrolerStrony_2 - Funkcje specyficzne dla strony 2: 25

A automatyczne testy? Problem: Aby przetestować musielibyśmy uruchamiać serwer aplikacji... class KontrolerBazowyTesty ModelWidok.NET::_Default System.Web.UI.Page + Page_ Load(obj ect, System.EventArgs) : voi d + Subm itbtn_click(object, EventArgs) : void «partial» 1. Tutaj będzie znajdować się cały kod zależny od ASP.NET 2. Będziemy przekazywać parametry w formie niezlaeżnej od HTTP. (np. w postaci kolekcji) ModelWidok.NET::Default.aspx + Button1: asp:b utton + M ydatagri d: asp:gri dv iew + recordi ngsel ect: asp:dropdownlist KontrolerBazowy - Wspolna funkcjonalnosc (m etody): 3. Kontroler możemy wykorzystać również w innych aplikacjach! (Nawet typu Desktop.) KontrolerStrony_1 - Funkcje specyficzne dla strony 1: KontrolerStrony_2 - Funkcje specyficzne dla strony 2: 26

A automatyczne testy? Zależy od zapytania HTTP class KontrolerBazowyTesty ModelWidok.NET::_Default System.Web.UI.Page + Page_ Load(obj ect, System.EventArgs) : voi d + Subm itbtn_click(object, EventArgs) : void Teraz aby utworzyć testy automatyczne kontrolera nie musimy symulować żądań HTTP (Request) «partial» Nie zależy od zapytania HTTP ModelWidok.NET::Default.aspx + Button1: asp:b utton + M ydatagri d: asp:gri dv iew + recordi ngsel ect: asp:dropdownlist KontrolerBazowy - Wspolna funkcjonalnosc (m etody): KontrolerStrony_1 - Funkcje specyficzne dla strony 1: KontrolerStrony_2 - Funkcje specyficzne dla strony 2: 27

A automatyczne testy? class KontrolerBazowyTesty ModelWidok.NET::_Default System.Web.UI.Page + Page_ Load(obj ect, System.EventArgs) : voi d + Subm itbtn_click(object, EventArgs) : void CodeBehind pełni rolę pośredniego model prezentacji, wykonujący transformację elementów z postaci HTTP na postać z dziedziny aplikacji lub do postaci ogólnych kolekcji. «partial» ModelWidok.NET::Default.aspx + Button1: asp:b utton + M ydatagri d: asp:gri dv iew + recordi ngsel ect: asp:dropdownlist KontrolerBazowy - Wspolna funkcjonalnosc (m etody): Kontroler uniwersalny, niezależny od samego zapytania HTTP. KontrolerStrony_1 - Funkcje specyficzne dla strony 1: KontrolerStrony_2 - Funkcje specyficzne dla strony 2: 28

Zalety Page Controller - Podsumowanie Ograniczenia Prostota ponieważ każda strona jest zarządzana przez własny kontroler. Wzorzec jest zalecany dla stron ze stosunkowo prostą nawigacją. Jest wzorcem wbudowanym i zalecanym przez.net Zastosowanie kontrolera bazowego zwiększa ponowne użycie kodu. Rozszerzalność bardziej złożona logika może być delegowana do oddzielnych klas pomocniczych. Rozdzielenie zadań programisty od projektanta www. Jeden kontroler dla każdej strony sprawdza się gdy mamy w miarę statyczną strukturę stron aplikacji oraz nawigacji między nimi. Głębokie zależności dziedziczenia prowadzą do trudnych do utrzymania i rozwoju projektów. Dodatkowo często wymagają wielu operacji warunkowych. W przypadku bardzo skomplikowanego systemu rozważ zastosowanie wzorca Front Controller. W klasycznej postaci nie umożliwia wykonywania automatycznych testów. Kontroler zależy od zawartości formularza na stronie, czyli od specyficznych pól zawartych w obiekcie Request. Dopiero zastosowanie dodatkowego kontrolera dedykowanego do samego ASP.NET. 29

Założenia do Front Controller Problem: Jaka jest najkorzystniejsza architektura dla skomplikowanej aplikacji Web aby osiągnąć wysoki wskaźnik ponownego użycia kodu oraz elastyczności przy jak najmniejszym duplikowaniu kodu. Problem: Wspólna funkcjonalność jest dzielona przez wiele widoków. Potrzebna jest centralizacja tej logiki aby uniknąć powtarzania się kodu. Problem: Zbiór widoków wykorzystuje te same dane. Najkorzystniejszym rozwiązaniem jest scentralizowane pobieranie danych. Czyli unikamy powtarzania się kodu odpowiedzialnego za pobieranie danych w poszczególnych widokach. Problem: Automatyczne testowanie. Testować chcemy nie tylko model, ale także kontroler. 30

Front Controller - Wprowadzenie W Page Controller: mamy jednego potomka wszystkich stron, ale którego funkcjonalność z czasem rozrasta się do bardzo dużych rozmiarów, aby uniknąć warunków w klasie bazowej musimy budować skomplikowane i złożone struktury dziedziczenia, zarządza JEDNĄ stroną, czyli trudno jest nam zrealizować zarządzanie nawigacją, czyli logikę aplikacji, zarządza jedną stroną a więc trudno jest w jednym miejscu zrealizować WSPÓLNĄ część funkcjonalności aplikacji (komunikaty, bezpieczeństwo, itp.) przywiązanie strony, formularza do konkretnego URLa, również wprowadza ograniczenie do aplikacji (wyobraźmy sobie np. kreator, gdzie potrzebne byłyby operacje warunkowe w kontrolerze bazowym) 31

Front Controller - Wprowadzenie Rozwiązanie: Filtracja wszystkich zapytań przez JEDEN główny kontroler. Front Kontroler jest realizowany w dwóch częściach: Handler (obsługa) oraz hierarchii akcji (Concrete Command) Zadania Handlera: Pobranie parametrów bezpośrednio z zapytania HTTP. Selekcja akcji (komendy, command) do ruchomienia. Komendy są częścią kontrolera. Zaleta: Po zakończeniu operacji przez komendę wybiera ona widok do wyświetlenia. scentralizowane zarządzanie bezpieczeństwo wątkowe możliwość konfiguracji 32

Struktura i scenariusz Front Controllera Struktura Scenariusz 33

Implementacja W.Net implementacja jest skomplikowana ze względu na wbudowany i ściśle zintegrowany ze środowiskiem wzorzec Page Controllera. Potrzebna jest budowa całego silnika Front Controllera. Należy stosować tylko i wyłącznie dla faktycznie rozbudowanych systemów. Zakładamy, że potrzebujemy stworzyć dwie strony z wspólnym nagłówkiem. 34

Kod klasy bazowej using System; using System.Web.UI; using System.Web.UI.WebControls; public class BasePage : Page protected Label email; protected Label sitename; virtual protected void PageLoadEvent(object sender, System.EventArgs e) protected void Page_Load(object sender, System.EventArgs e) if (!IsPostBack) string name = Context.User.Identity.Name; email.text = DatabaseGateway.RetrieveAddress(name); sitename.text = "Micro-site"; PageLoadEvent(sender, e); #region Web Form Designer generated code override protected void OnInit(EventArgs e) // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.oninit(e); /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() this.load += new System.EventHandler(this.Page_Load); #endregion 35

Projekt obiektu Handler using System; using System.Web; public class Handler : IHttpHandler public void ProcessRequest(HttpContext context) Command command = CommandFactory.Make(context.Request.Params); command.execute(context); public bool IsReusable get return true; using System; using System.Collections.Specialized; public class CommandFactory public static Command Make(NameValueCollection parms) string sitename = parms["site"]; Command command = new UnknownCommand(); if (sitename == null sitename.equals("micro")) command = new MicroSite(); else if (sitename.equals("macro")) command = new MacroSite(); return command; using System; using System.Web; public interface Command void Execute(HttpContext context); 36

Konfiguracja Handlera Plik konfiguracyjny: <httphandlers> <add verb="*" path="page*.aspx" type="handler,frontcontroller" /> </httphandlers> 37

Komendy 38

RedirectingCommand using System; using System.Web; public abstract class RedirectingCommand : Command private UrlMap map = UrlMap.SoleInstance; protected abstract void OnExecute(HttpContext context); public void Execute(HttpContext context) OnExecute(context); string url = String.Format("0?1", map.map[context.request.url.absolutepath], context.request.url.query); context.server.transfer(url); 39

UrlMap public class UrlMap : IConfigurationSectionHandler private readonly NameValueCollection _commands = new NameValueCollection(); public const string SECTION_NAME = "controller.mapping"; public static UrlMap SoleInstance get return (UrlMap)ConfigurationSettings.GetConfig(SECTION_NAME); object IConfigurationSectionHandler.Create(object parent, object configcontext, XmlNode section) return (object)new UrlMap(parent, configcontext, section); private UrlMap() /*no-op*/ public UrlMap(object parent, object configcontext, XmlNode section) try XmlElement entrieselement = section["entries"]; foreach (XmlElement element in entrieselement) _commands.add(element.attributes["key"].value, element.attributes["url"].value); catch (Exception ex) throw new ConfigurationException("Error while parsing configuration section.", ex, section); public NameValueCollection Map get return _commands; <controller.mapping> <entries> <entry key="/patterns/frontc/3/page1.aspx" url="actualpage1.aspx" /> <entry key="/patterns/frontc/3/page2.aspx" url="actualpage2.aspx" /> </entries> </controller.mapping> 40

MicroSite using System; using System.Web; public class MicroSite : RedirectingCommand protected override void OnExecute(HttpContext context) string name = context.user.identity.name; context.items["address"] = WebUsersDatabase.RetrieveAddress(name); context.items["site"] = "Micro-Site"; 41

MacroSite using System; using System.Web; public class MacroSite : RedirectingCommand protected override void OnExecute(HttpContext context) string name = context.user.identity.name; context.items["address"] = MacroUsersDatabase.RetrieveAddress(name); context.items["site"] = "Macro-Site"; 42

Dostęp do danych... using System; using System.Data; using System.Data.SqlClient; public class WebUsersDatabase public static string RetrieveAddress(string name) string address = null; String selectcmd = String.Format("select * from webuser where (id = '0')", name); SqlConnection myconnection = new SqlConnection("server=(local);database=webusers;Trusted_Connection=yes"); Dla Micro-Site: Dla Macro-Site: SqlDataAdapter mycommand = new SqlDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "webuser"); if (ds.tables["webuser"].rows.count == 1) DataRow row = ds.tables["webuser"].rows[0]; address = row["address"].tostring(); return address; Warstwa Modelu... using System; using System.Data; using System.Data.SqlClient; public class MacroUsersDatabase public static string RetrieveAddress(string name) string address = null; String selectcmd = String.Format("select * from customer where (id = '0')", name); SqlConnection myconnection = new SqlConnection("server=(local);database=macrousers;Trusted_Connection=yes"); SqlDataAdapter mycommand = new SqlDataAdapter(selectCmd, myconnection); DataSet ds = new DataSet(); mycommand.fill(ds, "customer"); if (ds.tables["customer"].rows.count == 1) DataRow row = ds.tables["customer"].rows[0]; address = row["email"].tostring(); return address; 43

Front Controller Wady i Zalety Zalety: Wady: Większa elastyczność (np. poprzez plik konfiguracyjny) Uproszczone widoki (bez obsługi akcji) Gotowe na rozbudowę i modyfikacje Mapowanie URL (ukrycie nazw stron przed użytkownikiem) Bezpieczeństwo wątkowe Obniżona wydajność Zwiększone skomplikowanie kodu, pogorszona czytelność i odkrywalność Front Controller jest zaimplementowany w ASP.NET trudne testowanie w oddzieleniu od serwera aplikacji Brak weryfikacji nieprawidłowych URL (ponieważ znajduje się to tylko w pliku konfiguracyjnym) 44

Page Cache Aby przyspieszyć wyświetlanie stron, które wymagają długiego czasu do generacji możemy je na jakiś czas przechowywać w pamięci podręcznej. Brak w cache Znajdujący się w cache 45

Page Cache - implementacja W.NET wzorzec Page Cache jest wbudowany w serwer aplikacji. <%@ OutputCache Duration="60" VaryByParam="none" %> <html> <script language="c#" runat="server"> void Page_Load(Object sender, EventArgs e) TimeMsg.Text = DateTime.Now.ToString("G"); </script> <body> <h3>using the Output Cache</h3> <p>last generated on: <asp:label id="timemsg" runat="server"/> </body> </html> 46

Wzorzec Łańcuch Filtrów (Filter Chain) Struktura Typowy scenariusz 47

Przykładowe zastosowanie Filtry przechwytują zdarzenia Przed... i Po.. (Before... i After...) Analiza nagłówków Analiza pól Uruchomienie logiki Zwrócenie nagłówków Zwrócenie treści 48

Interakcja Dziękuję za uwagę. Chcemy być coraz lepsi! Jeżeli coś cię zainteresowało napisz e-maila: robert@iem.pw.edu.pl Jeżeli coś cię bardzo znudziło napisz e-maila: robert@iem.pw.edu.pl Jeżeli zauważyłeś błąd napisz e-maila: robert@iem.pw.edu.pl 49