550 likes | 675 Views
ASP.NET Atlas. Wojciech Rygielski rygielski@mimuw.edu.pl. ASP.NET 2.0 Atlas. 1. ASP.NET. Zmiany w ASP.NET 2.0. Kod można umieszczać na stronie (tzn. w pliku .aspx, nie koniecznie w .aspx.cs) Kompilacja projektu jest zbędna (jest wtedy kompilowany automatycznie przy odwołaniu się do strony).
E N D
ASP.NETAtlas Wojciech Rygielski rygielski@mimuw.edu.pl
ASP.NET 2.0 • Atlas
Zmiany w ASP.NET 2.0 • Kod można umieszczać na stronie (tzn. w pliku .aspx, nie koniecznie w .aspx.cs) • Kompilacja projektu jest zbędna (jest wtedy kompilowany automatycznie przy odwołaniu się do strony)
Zmiany w ASP.NET 2.0 cd. • Master pages • Umożliwienie tworzenia pseudo-obiektowej hierarchii wyglądu stron w aplikacji (strona może wywoływać metody publicznych obiektów w swojej master-stronie) • Łatwe dodawanie wspólnych elementów dla wszystkich stron (np. menu w plików sitemap), elementy te mogę być konfigurowalne • Wielopoziomowe zagnieżdżanie<%@ master language="C#" master="~/TopLevel.master"%>
MasterPage.master ... <asp:label runat="server" id="Header"> xyz </asp:label> ... <asp:contentplaceholder id="srodek" runat="Server"> </asp:contentplaceholder> ...
Page.aspx <script runat="server"> void Page_Load(object sender, System.EventArgs e) { Label headerLabel = (Label) Master.FindControl("Header"); headerLabel.Text = "abc"; } </script> ... <asp:content runat="server" id="Content1" contentplaceholderid="srodek"> ghi </asp:content>
Zmiany w ASP.NET 2.0 cd. • WebParts (zbiór komponentów umożliwiających użytkownikom końcowym personalizację wyglądu strony) • Lepsze cachowanie • możliwość odświeżenia cache po zmianach w bazie danych (w MSSQL7 na poziomie tabeli, w kolejnej wersji na poziomie wiersza)
Odświeżanie cache przy zmianach bazie danych Na stronie: <%@ OutputCache duration="3600" varybyparam="none" sqldependency="Northwind:Employees" %> W konfiguracji (web.config): <system.web> <cache> <sqlCacheDependency enabled = "true" pollTime = "1000" > <databases> <add name="Northwind" connectionStringName="Northwind" pollTime = "1000"/> </databases> </sqlCacheDependency> </cache> </system.web> W bazie danych (SqlCacheDependencyAdmin.EnableTableForNotifications)
Zmiany w ASP.NET 2.0 cd. • Personalizacja (role) • http://www.ondotnet.com/pub/a/dotnet/2004/10/25/libertyonwhidbey.html?page=1 • użytkownik/role wbudowane w logikę ASP • kontrolki w rodzaju <asp:Login>, <asp:LoginView>, <asp:PasswordRecovery>, <asp:CreateUserWizard> itp. • Mechanizm logowania można stworzyć całkowiecie deklaratywnie
Sposoby przechowywania stanu aplikacji • Application • ViewState • Session • Profile (nowość)
-> Application // global.asax: void Application_Start(object sender, EventArgs e) { Application.Add("clickCount", 0); Application.Add("userCount", 0); } void Session_Start(object sender, EventArgs e) { Application["userCount"] = ((int)Application["userCount"]) + 1; } void Session_End(object sender, EventArgs e) { Application["userCount"] = ((int)Application["userCount"]) - 1; } // *.aspx.cs: protected void Button1_Click(object sender, EventArgs e) { Application["clickCount"] = ((int)Application["clickCount"]) + 1; this.Label1.Text = Application["clickCount"].ToString(); }
-> ViewState / Session • ViewState • Zapisywane w formularzu na stronie • EnableViewState w wielu kontrolkach • Nie przeterminowuje się • Session • Przechowywane w pamięci serwera • Dane usuwane po wygaśnięciu sesji
Fragment „wyprodukowanej” strony z ViewState <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTkyODQzNTM0NGRkTWNuBnFzfOqEto/CAI4sdj057c0=" />
ViewState / Session / Profile • liczniki („na żywo”)
Zmiany w ASP.NET 2.0 cd. • Profile • http://pluralsight.com/blogs/fritz/archive/2004/09/28/2450.aspx • Sprawdzanie typów, obsługa IntelliSense • Miała być możliwość zapisania danych w pamięci, bazie danych, pliku XML (domyślnie: AspNetSqlProfileProvider), można pisać własne Providery
-> Profile (web.config) <profile> <properties> <group name="Name"> <add name="Last" /> <add name="First" /> </group> <add name="phoneNumber" /> <add name="birthDate" type="System.DateTime"/> </properties> </profile>
Profile (wykorzystanie w kodzie) void save_Click(object sender, EventArgs e) { Profile.lastName = this.lastName.Text; Profile.firstName = this.firstName.Text; Profile.phoneNumber = this.phone.Text; Profile.birthDate = Convert.ToDateTime(this.birthDate.Text); Response.Redirect("Default.aspx"); }
Zmiany w ASP.NET 2.0 cd. • Themes • Pliki *.skin – domyślne ustawienia kontrolek <asp:Button runat="server" BackColor="Black" ForeColor="White" Font-Name="Arial" Font-Size="10px" /> • Można powiązać ze wszystkimi stronami, lub z wybranymi: <%@Page theme="Testheme" %> • Można zmieniać w trakcie wykonania (Page.Theme) • Wartości nie tylko spośród adekwatnych im wartości CSS
Zmiany w ASP.NET 2.0 cd. • Nowe źródła danych • <asp:SqlDatasource> • <asp:ObjectDatasource> • obiekt jako wiersz/tabela (więcej zaraz) • <asp:AccessDatasource> • <asp:XmlDatasource> • <asp:SitemapDatasource> • używany np. przez komponent menu
ObjectDataSource • atrybuty (właściwości? pary set+get) obiektów widoczne jako wartości kolumn (interpretacja: wiersz) • obiekt może mieć metodę zwracającą kolekcję obiektów (interpretacja: tabela) public ICollection GetData() { ArrayList list = new ArrayList(); list.Add(new InnyObiekt(bla,bla,bla)); list.Add(new InnyObiekt(bla,bla,bla)); return list; }
Wykorzystanie źródeł danych • Wiele funkcjonalności możemy opisać bez pisania kodu (nie chodzi tylko o zapytania select, ale również update/insert/delete) • Dużo kontrolek obsługujących źródła danych (<asp:gridview>, <asp:formview>, <asp:detailsview>), radzących sobie z problemami konkurencyjności itp. • Spójny model i API
Podsumowanie aplikacji webowych w ASP.NET • Logika aplikacji webowej nie odbiega bardzo od logiki tworzenia zwykłej aplikacji okienkowej • W czystym ASP.NET (bez ręcznie pisanych skryptów), praktycznie każde kliknięcie myszką oznacza przeładowanie całej strony
Przykładowa aplikacja ASP.NET • („na żywo”)
ComfortASP.NET MagicAJAX.NET ZumiPage ATLAS (CTP) OutPost FastPage ComponentArt Telerik Dart PowerWeb Anthem Syncfusion Studio Realizacje AJAX dla ASP.NET
AJAX+ASP – dwie koncepcje • Rozwiązanie 1 – dynamiczne odświeżanie całej strony • zamiast przeładowywać całą stronę, wysyłany jest request w tle • po stronie serwera sporządzana jest lista zmian na stronie (diff) i sama lista zmian jest przesyłana do klienta • lista zmian jest aplikowana dynamicznie po stronie klienta
(1) Dynamiczne odświeżanie strony • Założenia: • Strona jest wyświetlana tak jak bez AJAX • W kodzie aplikacji generalnie nic się nie zmienia • Wpływ na wzorzec aplikacji • Logika aplikacji zostaje po stronie ASP (ograniczenie używanych skryptów JS) • „Stan” aplikacji zmienia się wciąż tylko podczas przeładowywania strony
(1) Dynamiczne odświeżanie strony • Problemy (implementacji rozwiązania): • Rozmiar przesyłanych danych; po każdym AJAXowym żądaniu, przesyłane są te rzeczy, które zmieniły się na stronie ASP („diff”) • Ewentualne skrypty JS powinny być po takim żądaniu odświeżane i resetowane (tak jak by to było po odświeżeniu strony)
AJAX+ASP – dwie koncepcje • Rozwiązanie 2 – odświeżanie kontrolek • decyzję o tym co ma być odświeżane podejmuje programista
(2) Odświeżanie kontrolek • Założenia: • Oznaczamy na stronie kontrolki, które mogą się zmienić („partial/selective update”) • Wpływ na wzorzec aplikacji • Możliwy rozwój „prawdziwej” aplikacji AJAXowej (w sensie: takiej jak do tej pory, a nie „symulowanej” jak w (1)) • W dalszym ciągu możliwy rozwój „normalnej” aplikacji ASP • Przeniesienie części logiki AJAXowej do zapisu deklaratywnego (w Atlasie: UpdatePanel) • (Różne inne zależności zależne od implementacji)
Sposoby oznaczania zmieniających się kontrolek • Różne sposoby w różnych implementacjach: • Najbardziej popularny: zamknięcie kontrolek w „odświeżającym się” panelu • Oznaczenie poszczególnych kontrolek w kodzie aplikacji • „Ręczne” zdecydowanie, które kontrolki mają być przesłane, podczas odpowiadania na żądanie • Wykrywanie po stronie klienta, które kontrolki powinny być zmienione, przesyłanie ich ID w żądaniu (?)
ATLAS • Microsoftowa implementacja biblioteki AJAX pod ASP.NET • Na razie uboga, rozwija się • „Atlas” to tylko tymczasowa nazwa • Omawiana tutaj wersja - April (2006) Community Technology Preview (CTP) • API wciąż się zmienia (używać na własne ryzyko)
Szok ;) • Atlas działa pod Firefoxem • (dla przypomnienia: Atlas jest Microsoftu)
Czym jest Atlas • zbiorem plików .js dołączanych do emitowanych stron, rozszerzających możliwości JavaScriptu • sposobem deklaratywnego opisania interakcji komponentów na stronie (XML-script) • zbiorem komponentów do wykorzystania po stronie serwera, emitujących odpowiedni XML-script interpretowany przez (1) Możemy zaprzestać na każdej z tych trzech warstw abstrakcji (stąd np. pomysły wykorzystania niższych warstw Atlasa w PHP)
(1) Rozszerzenia do JavaScriptu • AtlasRuntime.js • Atlas.js • AtlasCompat.js • AtlasCompat2.js • AtlasFX.js • AtlasUIDragDrop.js • AtlasUIGlitz.js • AtlasUIMap.js • AtlasWebParts.js • GadgetRuntime.js
Atlasowy JavaScript • Dodatkowe obiekty, funkcje i typy danych (klasy, przestrzenie nazw, enumeracje, interfejsy, dziedziczenie). • Klasy do debuggowania, obsługi zdarzeń (events) i stringów, wywołań XML (webservices), timery i inne • Obsługa UI – kontrolki, zachowania (behaviors), walidacja, wiązanie danych, drag&drop... • Atlasowe „implementacje” wielu standardowych kontrolek HTML (hyperlink, listview, select, dataview, button, checkbox, textbox, label, datasource, counter)
Przykład: dodawanie klasy do przestrzeni nazw Type.registerNamespace("Demo"); Demo.Person = function(firstName, lastName, emailAddress) { var _firstName = firstName; var _lastName = lastName; var _emailAddress = emailAddress; this.getFirstName = function() { return _firstName; } // ...pozostałe akcesory... this.dispose = function() { alert('bye ' + this.getName()); } } Demo.Person.registerClass('Demo.Person', null, Web.IDisposable);
Przykład: dziedziczenie Demo.Employee = function(firstName, lastName, emailAddress, team, title) { Demo.Employee.initializeBase(this, [firstName, lastName, emailAddress]); var _team = team; var _title = title; this.getTeam = function() { return _team; } this.setTeam = function(team) { _team = team; } ... } Demo.Employee.registerClass('Demo.Employee', Demo.Person);
Przykład: override Demo.Person.prototype.toString = function() { return this.getName() + ' (' + this.getEmailAddress() + ')'; } Demo.Employee.prototype.toString = function() { return Demo.Employee.callBaseMethod(this, 'toString') + '\r\n' + this.getTitle() + '\r\n' + this.getTeam(); }
Przykład: obsługa atlasowych „obiektów” g_panel = new Sys.UI.Control($('panel')); g_panel.initialize(); g_panel.set_cssClass('normal'); g_selColor = new Sys.UI.Select($('colorSelect')); g_selColor.initialize(); g_selColor.selectionChanged.add(onSelectColor); g_tbx = new Sys.UI.TextBox($('textBox')); g_tbx.initialize(); g_tbx.set_text("Simple text box control"); g_tbx.set_cssClass("textBox"); var btnVisibility = new Sys.UI.Button($('visibilityButton')); btnVisibility.initialize(); btnVisibility.click.add(onSetVisibilityClick);
(2) XML-script • Możliwość deklaratywnego zapisu wielu (AJAX-owych) aspektów aplikacji w postaci XML (zamiast kodu JS)
<input type="text" id="searchText" /> <input type="button" id="searchButton" /> <script type="text/xml-script"> <page xmlns="http://schemas.microsoft.com/xml-script/2005"> <references> <add src="ScriptLibrary/Atlas/AtlasUI.js" /> <add src="ScriptLibrary/Atlas/AtlasControls.js" /> </references> <components> <textbox id="searchText" /> <button id="searchButton"> <bindings> <binding property="enabled" dataContext="searchText" dataPath="text.length" transform="NumberToBoolean" /> </bindings> <click> <invokeMethod target="searchMethod" method="invoke" /> </click> </button> <serviceMethod id="searchMethod"> <bindings> <binding property="parameters" propertyKey="query" dataContext="searchText" dataPath="text" /> </bindings> </serviceMethod> </components> </page> </script>
Argumenty twórców Atlasa za wprowadzeniem XML-script • Deklaratywny XML jest dużo łatwiejszy do przetwarzania w sposób automatyczny niż kod (Designer w Visual Studio) • W Atlasowych kontrolkach serwera - łatwiej jest emitować XML niż JavaScript (XmlTextWriter) • Deklaratywny sposób zapisu pozwala zdefiniować potrzeby zamiast akcji • Niektóre proste sytuacje mogą być opisane dużo łatwiej i bezpieczniej niż w JS [zdaje się, że chodzi tutaj w szczególności o wiązanie (binding)]
Przykład: sprawdzanie poprawności formularza <textBox id="value1TextBox"> <validators> <requiredFieldValidator errorMessage="You must enter some text." /> </validators> </textBox> <validationErrorLabel id="validator1" associatedControl="value1TextBox" /> <label id="value1Label"> <bindings> <binding dataContext="value1TextBox" dataPath="text" property="text" /> </bindings> </label>
Przykład: sprawdzanie poprawności formularza cd. <textBox id="value2TextBox"> <validators> <requiredFieldValidator errorMessage="You must enter a number." /> <typeValidator type="Number” errorMessage="You must enter a valid number." /> <rangeValidator lowerBound="10" upperBound="20” errorMessage="You must enter a number between 10 and 20." /> </validators> </textBox> <validationErrorLabel id="validator2" visibilityMode="Hide" associatedControl="value2TextBox" />
Przykład: inne wymysły <label id="hideLabel"> <behaviors> <clickBehavior> <click> <setProperty target="panel" property="visible" value="false" /> </click> </clickBehavior> </behaviors> </label> <control id="DescriptionDrag”> <behaviors> <floatingBehavior handle="DescriptionDrag"> </floatingBehavior> </behaviors> </control>
Przykład: łączenie XML-scriptu z javascriptem <script type="text/xml-script"> <page xmlns:script="http://schemas.microsoft.com/xml-script/2005"> <components> <label id="greeting" /> <button id="helloButton" click="sayHello" > <click> <setProperty target="greeting" property="text" value="hello there" /> </click> </button> </components> </page> </script> <script type="text/javascript"> function sayHello() { alert("hello"); } </script>