Oddzielanie kodu od tre
ś
ci
W osiemnastu poprzednich rozdziałach ksiąŜki przedstawionych zostało kilka sposobów na
oddzielanie interfejsu uŜytkownika stron ASP.NET od kodu który go obsługuje (napisanego w
języku VB.NET). Przykładowo, zostały przedstawione sposoby przenoszenia kodu, który nie jest
bezpośrednio związany z interfejsem uŜytkownika do obiektów biznesowych, dzięki czemu strony
ASP.NET mogą zawierać wyłącznie kod związany z obsługą prezentacji danych. Co więcej,
wszelkie polecenia SQL moŜna zapisać w bazie danych w formie procedur zachowanych i usunąć
je ze stron ASP.NET (zagadnienia te zostały omówione w rozdziale 12., pt.: „Zastosowanie
zaawansowanych technik obsługi danych”). Wszelkie ustawienia i zmienne moŜna natomiast
zapisać w plikach konfiguracyjnych, takich jak
web.config
.
W tym rozdziale zostanie przedstawionych kilka bardziej zaawansowanych metod separacji kodu
ź
ródłowego od zawartości strony, czyli kodu kontrolującego działanie aplikacji od kodu
odpowiedzialnego za prezentację danych (na przykład: elementów sterujących HTML oraz
internetowych elementów sterujących). Programiści ASP.NET bardzo oczekiwali moŜliwości
takiej separacji, gdyŜ dzięki nim moŜna uprościć strony i logicznie zgrupować wykorzystywany w
nich kod. PrzecieŜ strony ASP.NET słuŜą wyłącznie do prezentacji interfejsu uŜytkownika, a
zatem po co miałby być w nich umieszczany kod o innym przeznaczeniu?
W tym rozdziale poznamy takŜe sposoby dostosowywania stron ASP.NET do pochodzenia
uŜytkownika. Metody te pozwalają na modyfikację zawartości stron ASP.NET zupełnie
niezaleŜnie od wydzielonego kodu stron.
W tym rozdziale przedstawionych zostanie bardzo wiele przykładów, a zatem… zaczynajmy!
W tym rozdziale zostaną omówione następujące zagadnienia:
•
Czym jest kod obsługi formularzy?
•
Jak uŜywać kodu obsługi przy tworzeniu stron ASP.NET.
•
W jaki sposób elementy sterujące uŜytkownika mogą korzystać z kodu obsługi.
•
Jak określić pochodzenie uŜytkownika (na podstawie uŜywanego języka).
•
Jak określić informacje o kulturze i regionie uŜytkownika.
•
W jaki sposób moŜna wydzielić ze stron ASP.NET najczęściej uŜywane łańcuchy
znaków i zapisać je w niezaleŜnych plikach zasobów.
Potrzeba rozdzielania ró
Ŝ
nych rodzajów
kodu
Być moŜe przypominasz sobie z dyskusji przedstawionej w rozdziale 2., Ŝe ASP.NET stara się
uprościć Ŝycie programistom umoŜliwiając niezaleŜne grupowanie kodu ASP.NET oraz kodu
HTML. Na przykład, większość (o ile nie cały) kod ASP.NET powinien być umieszczany w
blokach
SCRIPT
na samym początku stron ASP.NET i oddzielony od kodu HTML. Oddzielenie
obu rodzajów kodu zostało przedstawione na rysunku 19.1.
Kod ASP.NET
<%@Page Language="VB" %>
<%@Import Namespace="System.Xml" %>
<%@Import Namespace="System.Xml.XPath" %>
<script runat="server">
sub SelectData(obj as object,e as eventargs)
Dim objDocument as New XPathDocument _
(Server.MapPath("../r11/books.xml"))
Dim objNav as XPathNavigator = objDocument.CreateNavigator
lblMessage.Text = ""
try
dim objIterator as XPathNodeIterator = _
objNav.Select(tbQuery.Text)
While objIterator.MoveNext()
lblMessage.Text += "<" & _
objIterator.Current.Name & "> " & _
objIterator.Current.Value & "<br>"
end while
catch ex As Exception
lblMessage.Text = ex.Message
end try
end sub
</script>
Kod HTML
<html><body>
<form runat="server">
<h2>Zapytania XPath</h2>
<p>
Na przyład:<br>
<b><code>//book[last()]/@ISBN/text()</b></code> lub
<b><code>descendant::book/author/last-name</b></code><p>
Podaj zapytanie XPath:
<asp:Textbox id="tbQuery" runat=server/>
<asp:Button id="btnSubmit" text="Wykonaj zapytanie"
runat=server OnClick="SelectData"/><p>
<asp:Label id="lblMessage" runat=server/>
</form>
</body></html>
Tworzenie kodu w sposób przedstawiony na rysunku 19.1 jest bardzo korzystne i to z wielu
powodów — łatwiej moŜna modyfikować zarówno kod ASP.NET jak i kod HTML, kod źródłowy
strony staje się w ten sposób bardziej logiczny i nie trzeba szukać w nim bloków kodu
wykonywalnego. Niemniej jednak moŜliwości rozdzielania róŜnych rodzajów kodu jakie daje
ASP.NET są jeszcze większe. Dzięki wykorzystaniu kodu obsługi oraz plików zasobów moŜna
całkowicie oddzielić kod od zawartości strony. Pierwsze z powyŜszych rozwiązań umoŜliwia
zapisywanie kodu w niezaleŜnych plikach, natomiast drugie — zgrupowanie często
wykorzystywanych wartości (takich jak na przykład komunikaty o błędach) i zapisanie ich w
jednym miejscu, niezaleŜnym od strony ASP.NET.
Kod obsługi formularzy
Patrząc na rysunek 19.1 nie trudno zauwaŜyć korzyści płynące z oddzielenia kodu od treści strony.
Ale co by się stało, gdyby moŜna było usunąć całą początkową zawartość pliku
.aspx
? Dzięki
temu istniałaby moŜliwość faktycznego oddzielenia kod ASP.NET do zawartości strony.
Technologia ASP.NET pozwala na osiągnięcie takiej separacji dzięki wykorzystaniu kodu obsługi
formularzy. Kod obsługi formularzy jest sposobem na całkowite oddzielenie kaŜdego i całego
kodu ASP.NET od kodu interfejsu uŜytkownika. Teraz zamiast jednego pliku z rysunku 19.1
otrzymujemy dwa pliki przedstawione na rysunku 19.2.
Wył
ą
cznie kod HTML
<%@ Page Inherits="CodeBehind2" src="CodeBehind2.vb" %>
<html><body>
<form runat="server">
<asp:Calendar id="Calendar1" runat="server"
OnSelectionChanged="DateChanged"
Cellpadding="5" Cellspacing="5"
DayHeaderStyle-Font-Bold="True"
DayNameFormat="Short"
Font-Name="Arial" Font-Size="12px"
height="250px"
NextPrevFormat="ShortMonth"
NextPrevStyle-ForeColor="white"
SelectedDayStyle-BackColor="#ffcc66"
SelectedDayStyle-Font-Bold="True"
SelectionMode="DayWeekMonth"
SelectorStyle-BackColor="#99ccff"
SelectorStyle-ForeColor="navy"
SelectorStyle-Font-Size="9px"
ShowTitle="true"
TitleStyle-BackColor="#ddaa66"
TitleStyle-ForeColor="white"
TitleStyle-Font-Bold="True"
TodayDayStyle-Font-Bold="True" />
</form>
Wybrałe
ś
:
<asp:Label id="lblMessage" runat="server"/>
</body></html>
Wył
ą
cznie kod ASP.NET (kod obsługi formularza)
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class CodeBehind2 : Inherits Page
public lblMessage as Label
public Calendar1 as Calendar
Public sub Page_Load(obj as object, e as eventargs)
if not Page.IsPostBack then
Calendar1.SelectedDate = DateTime.Now
lblMessage.Text = Calendar1.SelectedDate. _
ToString("dddd, MMMM dd yyyy")
end if
End Sub
Public sub DateChanged(obj as object, e as eventargs)
if Calendar1.SelectedDates.Count > 1 then
lblMessage.Text = Calendar1.SelectedDates(0). _
ToString("dddd, MMMM dd yyyy") & " do " & _
Calendar1.SelectedDates(Calendar1.SelectedDates. _
Count - 1).ToString("dddd, MMMM dd yyyy")
else
lblMessage.Text = Calendar1.SelectedDate. _
ToString("dddd, MMMM dd yyyy")
end if
End Sub
End Class
Przeanalizujmy jeszcze raz sposób działania ASP.NET, abyśmy lepiej zrozumieli model
programowania wykorzystujący kod obsługi.
Gdy klient po raz pierwszy przesyła Ŝądanie dotyczące jakiejś strony ASP.NET (pliku z
rozszerzeniem
.aspx
), ASP.NET przetwarza tę stronę i analizuje wszystkie wykorzystywane na
niej komponenty (na przykład, elementy sterujące serwera). Następnie ASP.NET tworzy klasę
dynamiczną dla danego pliku
.aspx
. To właśnie tak klasa jest następnie kompilowana,
wykonywana i to ona generuje kod HTML przesyłany następnie do klienta. Musi to być kasa
potomna klasy
System.Web.UI.Page
, która zawiera definicje wykorzystywane przez wszystkie
stron ASP.NET. Cały ten proces jest wykonywany w sposób całkowicie niezauwaŜalny, w
momencie zgłoszenia Ŝądania dotyczącego strony ASP.NET.
Jednak plik
.aspx
nie musi być bezpośrednią klasą potomną klasy
Page
— o ile tylko w
jakikolwiek sposób będzie dziedziczyć po tej klasie, to wszystko będzie w porządku. Oznacza to,
Ŝ
e moŜna stworzyć pewną klasę pośrednią, dziedziczącą po klasie
Page
i zaŜądać, aby plik
.aspx
dziedziczył po tej klasie pośredniej. Ta nowa klasa pośrednia moŜe udostępniać dowolne
moŜliwości funkcjonalne, które będą dostępne dla plików
.aspx
. Wzajemne relacje pomiędzy tymi
wszystkimi klasami zostały przedstawione na rysunku 19.3.
Ta nowa klasa pośrednia jest naszym kodem obsługi formularzy. Definiuje ona moŜliwości
funkcjonalne z których moŜe korzystać strona ASP.NET. Jednak przy tak duŜej ilości
wykorzystywanych klas łatwo będzie się moŜna pogubić. W zasadzie wszystko sprowadza się do
tego, iŜ strona ASP.NET musi być klasą potomną klasy
Page
, lecz od programisty zaleŜy
określenie hierarchii tego pokrewieństwa.
Wprowadzenie klasy kodu obsługi nie daje Ŝadnych oczywistych korzyści. Strona kodu obsługi
nie zawiera Ŝadnych własnych moŜliwości funkcjonalnych, a zatem dziedzicząc po niej strona
ASP.NET niczego nie zyskuje. Strona kodu obsługi takŜe w Ŝaden sposób nie wspomaga
wykonywania stron ASP.NET. Niemniej jednak wykorzystanie tej strony pozwala na przeniesienie
kodu do klasy pośredniej, dzięki czemu w stronie ASP.NET moŜe pozostać znacznie uproszczony
kod obsługi interfejsu uŜytkownika.
Wykorzystanie kodu obsługi w stronach ASP.NET
Stworzenie kodu obsługi formularza jest niezwykle proste; cały proces przypomina tworzenie
obiektów biznesowych, z tą róŜnicą iŜ niczego nie trzeba kompilować. Niemniej jednak trzeba
przedsięwziąć pewne środki bezpieczeństwa, aby zapewnić Ŝe wszystko będzie działać poprawnie.
Listing 19.1 przedstawia typową postać strony ASP.NET prezentującej informacje pobierane z
bazy danych. Za chwilę, na podstawie tej strony wygenerujemy kod obsługi formularza.
Listing 19.1.
Typowa strona ASP.NET zawiera zarówno kod programu jak i kod HTML.
1
<%@ Page Language="VB" %>
2
<%@ Import Namespace="System.Data" %>
3
<%@ Import Namespace="System.Data.OleDb" %>
4
5
<script runat="server">
6
'deklarujemy poł
ą
czenie
7
dim strConnString as string = "Provider=" & _
8
"Microsoft.Jet.OLEDB.4.0;" & _
9
"Data Source=C:\ASPNET\data\banking.mdb"
10
dim objConn as new OleDbConnection(strConnString)
11
12
sub Page_Load(obj as Object, e as EventArgs)
13
if Not Page.IsPostBack then
14
FillDataGrid()
15
end if
16
end sub
17
18
private sub FillDataGrid(Optional EditIndex as integer=-1)
19
'otwieramy poł
ą
czenie
20
dim objCmd as OleDbCommand = new OleDbCommand _
21
("select * from tblUsers", objConn)
22
dim objReader as OleDbDataReader
23
24
try
25
objCmd.Connection.Open()
26
objReader = objCmd.ExecuteReader
27
catch ex as OleDbException
28
lblMessage.Text = "Bł
ą
d pobierania informacji z bazy danych."
29
end try
30
31
DataGrid1.DataSource = objReader
32
DataGrid1.DataBind()
33
34
objReader.Close
35
objCmd.Connection.Close()
36
end sub
37
</script>
38
39
<html><body>
40
<form runat="server">
41
<asp:Label id="lblMessage" runat="server" />
42
43
<asp:DataGrid id="DataGrid1" runat="server"
44
BorderColor="black"
45
GridLines="Vertical"
46
cellpadding="4"
47
cellspacing="0"
48
width="100%"
49
Font-Name="Arial"
50
Font-Size="8pt"
51
HeaderStyle-BackColor="#cccc99"
52
ItemStyle-BackColor="#ffffff"
53
AlternatingItemStyle-Backcolor="#cccccc"
54
AutoGenerateColumns="True" />
55
</asp:DataGrid><p>
56
</form>
57
</body></html>
Analiza
Kod przedstawiony na powyŜszym listingu nawiązuje połączenie z bazą danych stworzoną w
rozdziale 8, pt.: „Podstawowe wiadomości na temat tworzenia baz danych”. W wierszach od 7. do
9. jest tworzony łańcuch zapytania, a w wierszu 10. obiekt
OleDbConnection
. W procedurze
Page_Load
wywoływana jest procedura
FillDataGrid
, która pobiera informacje z bazy danych
i wiąŜe je z elementem sterujący
DataGrid
zdefiniowanym w wierszach od 43. do 55. Wykonanie
powyŜszej strony powoduje wygenerowanie wyników przedstawionych na rysunku 19.4.
Rysunek 19.4.
Prosta strona ASP.NET pobierająca informacje z bazy danych.
A teraz, bazując na kodzie przedstawionym na listingu 19.1, stworzymy kod obsługi formularza.
W pierwszej kolejności naleŜy stworzyć klasę potomną klasy
System.Web.UI.Page
. Oto
przykład szkieletu takiej klasy:
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data
Imports System.Data.OleDb
Public Class CodeBehind1 : Inherits Page
‘tu zostanie wstawiony kod klasy
End Class
PowyŜszy szkielet klasy będzie podstawą do usunięcia kodu skryptu ze strony przedstawionej na
listingu 19.1. NaleŜy pamiętać, Ŝe tworząc klasę języka VB.NET naleŜy własnoręcznie
zaimportować wszystkie przestrzenie nazw, które w ASP.NET były importowane automatycznie.
Dodatkowo trzeba takŜe zaimportować przestrzenie nazw
System.Data
oraz
System.Data.OleDb
, gdyŜ tworzona strona ASP.NET będzie z nich korzystać przy
wyświetlaniu danych.
Kolejnym krokiem jest stworzenie wszystkich zmiennych publicznych, których będziemy
potrzebować. Ze względu na naturę kodu obsługi formularzy, proces ten będzie się nieco róŜnić do
tego, do czego jesteśmy przyzwyczajeni. Przyjrzyjmy się nieco dokładniej temu zagadnieniu.
Klasa kodu obsługi będzie uŜywana do kontroli interfejsu uŜytkownika (czyli, formularza
internetowego) — zawiera ona całą logikę konieczną do obsługi zdarzeń generowanych przez
interfejs uŜytkownika. Jednak klasa ta nie zawiera Ŝadnych elementów interfejsu uŜytkownika —
bez wyjątków są one umieszczane w kodzie strony
.aspx
. A zatem mamy problem. Klasa kodu
obsługi musi kontrolować interfejs uŜytkownika, który w całości jest definiowany w odrębnym
pliku. W jaki sposób moŜna to zrobić?
Zaraz poznasz powód dla którego strona ASP.NET ma być klasą potomną klasy kodu obsługi.
OtóŜ jeśli wszystkie konieczne elementy interfejsu uŜytkownika zastaną zadeklarowane w klasie
kodu obsługi, to plik
.aspx
odziedziczy je. Oznacza to, Ŝe kod obsługi stworzy i obsłuŜy wszystkie
elementy interfejsu uŜytkownika, lecz nie będzie ich wyświetlać. Za wyświetlenie elementów
interfejsu uŜytkownika wciąŜ będzie odpowiedzialna strona ASP.NET. PowyŜsza idea została
zilustrowana na rysunku 19.5.
Przenieśmy zatem kod z listingu 19.1 do kodu obsługi formularza przedstawionego na listingu
19.2.
Listing 19.2.
Kod obsługi zawiera wszelkie moŜliwości funkcjonalne związane z obsługą
interfejsu uŜytkownika (
CodeBehind1.vb
)
1
Imports System
2
Imports System.Web
3
Imports System.Web.UI
4
Imports System.Web.UI.WebControls
5
Imports System.Data
6
Imports System.Data.OleDb
7
8
Public Class CodeBehind1 : Inherits Page
9
'deklarujemy zmienne publiczne, które oddziedziczy
10
'plik .aspx.
11
public lblMessage as Label
12
public DataGrid1 as DataGrid
13
14
'deklarujemy ła
ń
cuch poł
ą
czenia
15
private strConnString as string = "Provider=" & _
16
"Microsoft.Jet.OLEDB.4.0;" & _
17
"Data Source=C:\ASPNET\data\banking.mdb"
18
private objConn as new OleDbConnection(strConnString)
19
20
sub Page_Load(obj as Object, e as EventArgs)
21
if Not Page.IsPostBack then
22
FillDataGrid()
23
end if
24
end sub
25
26
private sub FillDataGrid(Optional EditIndex as integer=-1)
27
'otwieramy poł
ą
czenie
28
dim objCmd as OleDbCommand = new OleDbCommand _
29
("select * from tblUsers", objConn)
30
dim objReader as OleDbDataReader
31
32
try
33
objCmd.Connection.Open()
34
objReader = objCmd.ExecuteReader
35
catch ex as OleDbException
36
lblMessage.Text = "Bł
ą
d przy pobieraniu danych z bazy."
37
end try
38
39
DataGrid1.DataSource = objReader
40
DataGrid1.DataBind()
41
42
objReader.Close
43
objCmd.Connection.Close()
44
end sub
45
46
End Class
Analiza
Zapisz powyŜszy kod w pliku o nazwie
CodeBehind1.vb
. W wierszach od 1. do 6. są importowane
niezbędne przestrzenie nazw, a w wierszu 8. rozpoczyna się deklaracja klasy kodu obsługi. Zwróć
uwagę, iŜ nosi ona nazwę
CodeBehind1
i jest klasą potomną klasy
Page
.
Na stronie ASP.NET z listingu 19.1 zostały uŜyte dwa elementy sterujące serwera — etykieta o
nazwie
lblMessage
oraz element
DataGrid
nazwie
DataGrid1
. W naszej klasie kodu obsługi
elementy te zostały zadeklarowane jako zmienne (odpowiednio w wierszach 10. i 11.). Teraz
strona ASP.NET odziedziczy te elementy oraz wszelkie moŜliwości funkcjonalne zdefiniowane w
klasie. Pozostała część kodu nie róŜni się niczym do zawartości strony z listingu 19.1; oczywiście
nie dotyczy to kodu HTML który w pliku
CodeBehind1.vb
nie został umieszczony. Teraz
przyjrzyjmy się kodowi strony
.aspx
, która będzie dziedziczyć po klasie kodu obsługi.
Listing 19.3.
Dziedziczenie po klasie kodu obsługi.
1
<%@ Page Inherits="CodeBehind1" src="CodeBehind1.vb" %>
2
3
<html><body>
4
<form runat="server">
5
<asp:Label id="lblMessage" runat="server" />
6
7
<asp:DataGrid id="DataGrid1" runat="server"
8
BorderColor="black" GridLines="Vertical"
9
cellpadding="4" cellspacing="0"
10
width="100%" Font-Name="Arial"
11
Font-Size="8pt"
12
HeaderStyle-BackColor="#cccc99"
13
ItemStyle-BackColor="#ffffff"
14
AlternatingItemStyle-Backcolor="#cccccc"
15
AutoGenerateColumns="True" />
16
</asp:DataGrid><p>
17
</form>
18
</body></html>
Analiza
Zapisz powyŜszy fragment kodu w pliku o nazwie
listing1903.aspx
i umieść go w tym samym
folderze, w którym został zapisany plik zawierający klasę kodu obsługi. Za wyjątkiem pierwszego
wiersza powyŜszy kod niczym nie róŜni się od fragmentu kodu HTML z listingu 19.1. Jednak w
pierwszym wierszu pojawił się nowy element — dyrektywa
@ Page
z atrybutami
Inherits
oraz
src
. Pierwszy z tych atrybutów —
Inherits
— określa klasę nadrzędną, po której będzie
dziedziczyć strona ASP.NET. W naszym przypadku chcemy, aby klasą nadrzędną strony była
klasa kodu obsługi —
CodeBehind1
. Atrybut
src
zawiera ścieŜkę dostępu do pliku kodu obsługi
(oznacza to, iŜ plik zawierający kod obsługi oraz plik
.aspx
nie muszą być umieszczone w tym
samym folderze). I to wszystko! Wystarczy wyświetlić tę stronę w przeglądarce, a uzyskane
wyniki nie powinny się niczym róŜnić od wyników przedstawionych na rysunku 19.4.
Elementy sterujące serwera
DataGrid
oraz
Label
z listingu 19.3 są kopiami zmiennych
klasowych (klasy
CodeBehind1
), zadeklarowanych na listingu 19.2. A zatem, dowolny kod
umieszczony wewnątrz klasy kodu obsługi i odwołujący się do tych zmiennych, będzie miał pełen
dostęp do wszystkich właściwości odpowiednich elementów sterujących formularza internetowego
(takich jak tekst wyświetlany przez etykietę).
Przyjrzyjmy się teraz kodowi obsługującemu zdarzenia generowane przez formularz. Tym razem
oba pliki zostaną utworzone od samego początku. Listing 19.4 przedstawia kod strony ASP.NET
definiującej interfejs uŜytkownika.
Notatka
Nic nie stoi na przeszkodzi, aby elementy interfejsu u
Ŝ
ytkownika oraz logika działania strony
ASP.NET były umieszczone w tym samym pliku. Kod programu nie musi by
ć
w cało
ś
ci
umieszczany w klasie kodu obsługi, a w pliku kodu obsługi mo
Ŝ
na umieszcza
ć
elementy
interfejsu u
Ŝ
ytkownika. Co wi
ę
cej, elementy interfejsu u
Ŝ
ytkownika deklarowane w kodzie
obsługi, mog
ą
by
ć
obsługiwane przez kod zdefiniowany w pliku
.aspx
. Niemniej jednak nie ma
Ŝ
adnego powodu, aby umieszcza
ć
kod w stronie ASP.NET je
ś
li mo
Ŝ
na go zaimplementowa
ć
jako kod obsługi.
Listing 19.4.
Plik
.aspx
bez kodu ASP.NET.
1
<%@ Page Inherits="CodeBehind2" src="CodeBehind2.vb" %>
2
3
<html><body>
4
<form runat="server">
5
<asp:Calendar id="Calendar1" runat="server"
6
OnSelectionChanged="DateChanged"
7
Cellpadding="5" Cellspacing="5"
8
DayHeaderStyle-Font-Bold="True"
9
DayNameFormat="Short"
10
Font-Name="Arial" Font-Size="12px"
11
height="250px"
12
NextPrevFormat="ShortMonth"
13
NextPrevStyle-ForeColor="white"
14
SelectedDayStyle-BackColor="#ffcc66"
15
SelectedDayStyle-Font-Bold="True"
16
SelectionMode="DayWeekMonth"
17
SelectorStyle-BackColor="#99ccff"
18
SelectorStyle-ForeColor="navy"
19
SelectorStyle-Font-Size="9px"
20
ShowTitle="true"
21
TitleStyle-BackColor="#ddaa66"
22
TitleStyle-ForeColor="white"
23
TitleStyle-Font-Bold="True"
24
TodayDayStyle-Font-Bold="True" />
25
</form>
26
Wybrałe
ś
:
27
<asp:Label id="lblMessage" runat="server"/>
28
</body></html>
PowyŜszy listing zawiera element sterujący serwera
Calendar
oraz etykietę. Choć plik kodu
obsługi nie został jeszcze utworzony, to jednak nazwa klasy oraz ścieŜka dostępu do pliku zostały
juŜ podane w dyrektywnie
@ Page
umieszczonej w pierwszym wierszu. W ten sposób juŜ
zawczasu wiadomo jaki plik naleŜy utworzyć. W wierszu 6. określana jest procedura obsługi
zdarzenia
SelectionChanged
kalendarza (elementu sterującego serwera
Calendar
). NaleŜy
takŜe zwrócić uwagę na nazwy obu elementów sterujących —
Calendar1
oraz
lblMessage
.
Próba wyświetlenia tej strony bez wcześniejszego utworzenia kodu obsługi, spowoduje
wystąpienie błędów. Błędy te zostaną zgłoszone z dwóch powodów. Po pierwsze ASP.NET będzie
szukać klasy kodu obsługi podanej w atrybucie
Inherit
dyrektywy
@ Page
lecz nie będzie w
stanie jej znaleźć. Po drugie, do obsługi zdarzenia
SelectionChanged
ma być wykorzystana
procedura
DateChanged
, która nigdzie nie została zdefiniowana. Aby rozwiązać te problemy,
wystarczy stworzyć kod obsługi przedstawiony na listingu 19.5.
Listing 19.5.
Kontrola zdarzeń generowanych przez element sterujący kalendarza
(
CodeBehind2.vb
).
1
Imports System
2
Imports System.Web
3
Imports System.Web.UI
4
Imports System.Web.UI.WebControls
5
6
Public Class CodeBehind2 : Inherits Page
7
public lblMessage as Label
8
public Calendar1 as Calendar
9
10
Public sub Page_Load(obj as object, e as eventargs)
11
if not Page.IsPostBack then
12
Calendar1.SelectedDate = DateTime.Now
13
lblMessage.Text = Calendar1.SelectedDate. _
14
ToString("dddd, MMMM dd yyyy")
15
end if
16
End Sub
17
18
Public sub DateChanged(obj as object, e as eventargs)
19
if Calendar1.SelectedDates.Count > 1 then
20
lblMessage.Text = Calendar1.SelectedDates(0). _
21
ToString("dddd, MMMM dd yyyy") & " do " & _
22
Calendar1.SelectedDates(Calendar1.SelectedDates. _
23
Count - 1).ToString("dddd, MMMM dd yyyy")
24
else
25
lblMessage.Text = Calendar1.SelectedDate. _
26
ToString("dddd, MMMM dd yyyy")
27
end if
28
End Sub
29
End Class
Analiza
Zapisz powyŜszy fragment kodu w pliku o nazwie
CodeBehind2.vb
. W wierszu 6. deklarowana
jest klasa kodu obsługi o nazwie
CodeBehind2
; co odpowiada nazwie podanej w atrybucie
Inherit
dyrektywy
@ Page
z listingu 19.4. W wierszach 7. i 8. tworzone są dwie zmienne
publiczne —
lblMessage
oraz
Calendar1
. NaleŜy zwrócić uwagę, iŜ są to te same nazwy które
nadaliśmy elementom sterującym w pliku
.aspx
. Procedura
Page_Load
zapisana w wierszach od
10. do 16. wybiera w kalendarzu dzisiejszą datę i wyświetla stosowny komunikat wykorzystując w
tym celu element sterujący etykiety.
I w końcu, metoda
DataChanged
której kod rozpoczyna się w wierszu 18. słuŜy do obsługi
zdarzeń
SelectionChanged
kalendarza (patrz wiersz 6. listingu 19.4). Metoda ta wyświetla na
stronie datę w rozbudowanym formacie. Jeśli jednocześnie zostanie wybranych kilka dni (co
moŜna sprawdzić za pomocą właściwości
SelectedDates.Count
), to chcemy poinformować
uŜytkownika o tym fakcie wyświetlając na stronie odpowiedni przedział dat (patrz wiersze od 19.
do 23.). W przeciwnym przypadku wyświetlana jest jedna — wybrana data (patrz wiersze 25. i
26.). Teraz wyświetlenie w przeglądarce strony z listingu 19.4 da rezultaty przedstawione na
rysunku 19.6.
Rysunek 19.6.
Kod obsługi formularza obsługuje zdarzenia generowane na stronie ASP.NET
Teraz moŜesz juŜ całkowicie oddzielić kod obsługujący formularze internetowe od warstwy
prezentacji danych.
Wykorzystanie kodu obsługi w elementach
steruj
ą
cych u
Ŝ
ytkownika
Wykorzystanie kodu obsługi w elementach sterujących uŜytkownika róŜni się nieco od
wykorzystania go do obsługi interfejsu uŜytkownika stron ASP.NET. Konkretnie rzecz biorąc, w
tym przypadku, kod obsługi musi być klasą potomną klasy
System.Web.UI.UserControl
(a
nie klasy
Page
). Więcej informacji na temat tworzenia i wykorzystania elementów sterujących
uŜytkownika moŜna znaleźć w rozdziale 6., pt.: „Ciąg dalszy wiadomości na temat tworzenia
formularzy internetowych”. Na listingach od 19.6 do 19.8 przedstawiony został zmodyfikowany
kod aplikacji kalkulatora stworzonej w rozdziale 2., w którym został wykorzystany element
sterujący uŜytkownika oraz kod obsługi formularza.
Listing 19.6.
Element sterujący uŜytkownika (
Calculator.ascx
).
1
<%@ Control Inherits="CalculatorControl" src="Calculator.vb" %>
2
3
Liczba 1: <asp:textbox id="tbNumber1" runat="server"/><br>
4
Liczba 2: <asp:textbox id="tbNumber2" runat="server"/><p>
5
<asp:button id="btAdd" runat="server" Text="+"
6
OnClick="btOperator_Click" />
7
<asp:button id="btSubtract" runat="server" Text="-"
8
OnClick="btOperator_Click"/>
9
<asp:button id="btMultiply" runat="server" Text="*"
10
OnClick="btOperator_Click"/>
11
<asp:button id="btDivide" runat="server" Text="/"
12
OnClick="btOperator_Click"/><p>
13
Wynik:
14
<asp:label id="lblMessage" runat="server"/>
Analiza
Zapisz powyŜszy fragment kodu w pliku o nazwie
Calculator.ascx
. Element sterujący
uŜytkownika przedstawiony na powyŜszym listingu jest bardzo prosty. Zawiera on kod HTML
wyświetlający dwa pola tekstowe w których uŜytkownicy mogą wpisywać liczby, cztery przyciski
umoŜliwiające wykonywanie podstawowych operacji arytmetycznych oraz etykietę słuŜącą do
wyświetlania wyników. W pierwszym wierszu powyŜszego kodu, zamiast dyrektywy
@ Page
została umieszczona dyrektywa
@ Control
, jednak składnia jej zapisu jest identyczna — takŜe w
tym przypadku klasa kodu obsługi jest określana przy uŜyciu atrybutu
Inherits
a nazwa pliku w
jaki został on zapisany — przy uŜyciu atrybutu
src
. Koniecznie naleŜy zapamiętać nazwy
wszystkich elementów sterujących, gdyŜ będą one konieczne przy tworzeniu kodu obsługi
formularza. Plik kodu obsługi dla powyŜszego elementu sterującego uŜytkownika został
przedstawiony na listingu 19.7.
Listing 19.7.
Klasa kod obsługi (
Calculator.vb
).
1
Imports System
2
Imports System.Web
3
Imports System.Web.UI
4
Imports System.Web.UI.WebControls
5
6
Public Class CalculatorControl : Inherits UserControl
7
public lblMessage as Label
8
public btAdd as Button
9
public btSubtract as Button
10
public btMultiply as Button
11
public btDivide as Button
12
public tbNumber1 as TextBox
13
public tbNumber2 as TextBox
14
15
Sub btOperator_Click(obj as object, e as eventargs)
16
lblMessage.Text = Operate(CType(obj, Button).Text, _
17
tbNumber1.Text, tbNumber2.Text).ToString
18
End Sub
19
20
private function Operate(operator as string, number1 as string,
optional number2 as string = "1") as double
21
select case operator
22
case "+"
23
Operate = CDbl(number1) + CDbl(number2)
24
case "-"
25
Operate = CDbl(number1) - CDbl(number2)
26
case "*"
27
Operate = CDbl(number1) * CDbl(number2)
28
case "/"
29
Operate = CDbl(number1) / CDbl(number2)
30
end select
31
end function
32
End Class
Analiza
Zapisz powyŜszy kod w pliku o nazwie
Calculator.vb
. MoŜliwości funkcjonalne
zaimplementowane w tym przykładzie są znacznie bardziej skomplikowane do tych z listingu
19.5, niemniej jednak sposób ich zapisu jest identyczny. W pierwszej kolejności, w wierszach do
1. do 4., są importowane niezbędne przestrzenie nazw. W wierszu 6. rozpoczyna się deklaracja
klasy
CalculatorControl
, będącej klasą potomną klasy
UserControl
(a nie klasy
Page
).
Następnie, w wierszach od 7. do 13. zostały zadeklarowane publiczne zmienne klasowe
odpowiadające elementom sterującym wykorzystywanym w tworzonym elemencie sterującym
uŜytkownika.
Gdy uŜytkownik kliknie jeden z przycisków elementu sterującego, zostanie wykonana procedura
obsługi zdarzenia o nazwie
btOperator_Clicked
. Procedura ta wywoła metodę
Operate
pobierającą trzy argumenty — operację jaką naleŜy wykonać oraz dwa operandy. W momencie
przesyłania Ŝądania, przycisk jaki spowodował zgłoszenie zdarzenia będzie reprezentowany przez
zmienną
obj
(patrz wiersz 15.) Przyjrzyjmy się pierwszemu argumentowi wywołania metody
Operate
zapisanemu w wierszu 16.:
Ctype(obj, Button).Text
PowyŜsze wyraŜenie pobiera wartość właściwości
Text
przycisku, który spowodował zgłoszenie
zdarzenia (na przykład, dla przycisku
btAdd
będzie to „+”). Jeśli tą samą czynności mielibyśmy
wykonać w kodzie strony ASP.NET, to wystarczyłoby uŜyć wyraŜenia
obj.Text
, niezaleŜnie od
tego, Ŝe klasa
Object
nie dysponuje właściwością o nazwie
Text
. Jednak klasy języka VB.NET
działają inaczej niŜ strony ASP.NET. Konkretnie rzecz biorąc nie dysponują one moŜliwością
późnego łączenia.
Nowe wyraŜenie
Późne łączenie
(ang.: late binding) oznacza, Ŝe zmienne typu
Object
(takie jak
obj
) nie są
przetwarzane aŜ do czasu wykonania programu. AŜ do tego momentu moŜna ich uŜywać do
reprezentacji obiektów dowolnych typów. To właśnie z tego względu moŜna uŜyć wyraŜenia
obj.Text
pomimo faktu, iŜ klasa
Object
nie dysponuje właściwością o tej nazwie. ASP.NET
zezwoli na wykorzystania wyraŜenia
obj.Text
gdyŜ wie, Ŝe w czasie obsługi Ŝądania zmienna
obj
moŜe się stać obiektem klasy
Button
(gdyby się jednak nie stała, to moglibyśmy mieć
powaŜne problemy).
Gdyby mechanizm późnego łączenia nie był wykorzystywany, to klasa
Object
byłaby od razu
przetwarzana a kompilator zgłosiłby błąd zaraz po określeniu Ŝe została podjęta próba uzyskania
dostępu do właściwości której nie ma (klasa
Object
nie posiada bowiem Ŝadnej właściwości o
nazwie
Text
). Właśnie z tego powodu naleŜy sprawić, aby kompilator VB.NET sądził Ŝe zmienna
obj
jest przyciskiem jeszcze zanim zostanie przesłane Ŝądanie, gdyŜ dzięki temu będzie moŜna
wykorzystać w kodzie właściwość
Text
. Metoda
CType
rzutuje jeden typ danych na inny, a
wyraŜenie uŜyte w wierszu 16. rzutuje zmienną typu
Object
na zmienną typu
Button
. MoŜe się
wydawać, Ŝe jest to dosyć złoŜone rozwiązanie, jednak gdy stworzysz więcej stron ASP.NET i
zdobędziesz więcej informacji na temat łączenia, wszystko stanie się znacznie prostsze.
Metoda
Operate
zdefiniowana w wierszach od 20. do 31. analizuje operator przekazany przez
metodę
btOperator_Clicked
przy wykorzystaniu instrukcji wyboru
select case
. W
zaleŜności od przekazanego operatora wykonywane jest odpowiednie działanie. Jego wynik jest
następnie zwracany do metody
btOperator_Clikced
i wyświetlany na stronie WWW.
Na listingu 19.8 przedstawiony został kod wyjątkowo krótkiej strony ASP.NET która
wykorzystuje stworzony przed chwilą element sterujący uŜytkownika.
Listing 19.8.
Strona ASP.NET wykorzystująca element sterujący uŜytkownika oraz kod
obsługi formularza.
1
<%@ Page language="VB" %>
2
<%@ Register TagPrefix="ASPNETDK" TagName="Calculator"
src="Calculator.ascx" %>
3
4
<html><body>
5
<form runat="server">
6
<ASPNETDK:Calculator id="Calc1" runat="server"/>
7
</form>
8
</body></html>
Analiza
PowyŜsza strona jest wyjątkowo prosta. Zapewne pamiętasz, Ŝe element sterujący uŜytkownika
musi zostać zarejestrowany na stronie ASP.NET. SłuŜy do tego dyrektywa
@ Register
, opisana
w szczegółowo w rozdziale 6., pt.: „Ciąg dalszy wiadomości na temat tworzenia formularzy
internetowych”. Po zarejestrowaniu, elementu sterującego uŜytkownika będzie moŜna uŜywać tak
samo, jak wszelkich innych elementów sterujących (patrz wiersz 5.). Wyświetl tę stronę w
przeglądarce, a następnie spróbuj wpisać jakieś liczby w polach formularza i wykonać jakieś
działania. Wyniki powinny przypominać te, przedstawione na rysunku 19.7.
Rysunek 19.7.
Kod obsługi formularza obsługuje zdarzenia generowane przez element sterujący
uŜytkownika umieszczony na stronie ASP.NET
Pliki zasobów i lokalizacja
Udając się na wakacje zabieramy walizkę z ubraniami, przyborami toaletowymi oraz innymi
rzeczami osobistymi. MoŜna by takŜe zabrać te wszystkie rzeczy bezpośrednio ze sobą (albo i na
sobie) ale było by to bardzo dziwne i niewygodne (nie wspominając w ogóle o ograniczonej ilości
kieszeni!). Ta walizka jest na wakacjach przedmiotem o pierwszorzędny znaczeniu — bez niej
nasza wycieczka stała by się koszmarem.
ASP.NET pozwala nam na „pakowanie walizki” dla tworzonej aplikacji. Wszelkie informacje
(takie jak zmienne, komunikaty, notatki, rysunki, itp.) moŜna zapisać w pliku zasobu. Strony
ASP.NET bez trudu mogą następnie pobierać zasoby zgromadzone w takim pliku, gdy tylko będą
potrzebne.
Nowe wyraŜenie
Pliki zasobów są zazwyczaj wykorzystywane do lokalizowania aplikacji.
Lokalizowanie
jest
procesem polegającym na modyfikacji wyników generowanych przez aplikację tak aby były one
zgodne z róŜnymi kulturami i językami. MoŜna tworzyć pliki zasobów dla wszystkich kultur jakie
będą korzystać z danej aplikacji. Na przykład, w pliku zasobów moŜna zapisać wiadomość
powitalną. Jeśli aplikację odwiedzi osoba anglojęzyczna komunikat powitalny będzie miał postać
„Hello”, dla uŜytkowników z Francji lub innych krajów francuskojęzycznych komunikat ten
będzie miał postać „Bonjour”. Zapisując wiadomość powitalną dla kaŜdego z języków w
odrębnym pliku zasobów nie trzeba będzie tworzyć róŜnych stron ASP.NET dla róŜnych języków.
Znacznie łatwiej jest stworzyć nowy plik zasobów.
W ASP.NET lokalizacja aplikacji oraz grupowanie zasobów jest bardzo łatwym procesem.
Pozwala on na modyfikację wyników działania aplikacji bez konieczności wprowadzania
jakichkolwiek zmian w kodzie, czyli stanowi jeszcze jedną formę oddzielania kodu od treści. W
kilku kolejnych częściach niniejszego rozdziału przedstawione zostaną sposoby określania jacy
uŜytkownicy korzystają z aplikacji, metody modyfikacji aplikacji pod ich kątem oraz zapisywania
zasobów w plikach.
Lokalizowanie aplikacji
W idealnym przypadku lokalizowania aplikacji będziemy dąŜyć do automatycznego określenia
pochodzenia korzystających z niej uŜytkowników, tak aby moŜna było wykorzystać odpowiednie
języki oraz inne informacje kulturowe. Niestety ze względu na charakter WWW nie ma Ŝadnego
standardowego sposobu na określenie geograficznego połoŜenia osoby odwiedzającej witrynę.
Na szczęście jednak istniej kilka sposobów rozwiązania tego problemu. MoŜna określić główny
język ustawiony w przeglądarce uŜytkownika. Zazwyczaj, choć oczywiście nie zawsze, ustawienie
to określa język oraz informacje kulturowe, które najbardziej odpowiadają uŜytkownikowi
przeglądarki; na tej podstawie będzie moŜna określić działanie aplikacji. Odstęp do tych
informacji zapewnia obiekt
Request.UserLanguages
, który gromadzi informacje o językach
przekazane przez przeglądarkę i przechowuje je w formie listy posortowanej zgodnie z
priorytetami określonymi przez uŜytkownika. Przykład kodu umoŜliwiającego określenie
głównego języka przedstawiony została na listingu 19.9.
Listing 19.9.
Wykorzystanie obiektu
Request
do określenia językowych preferencji
uŜytkownika.
1
<%@Page Language="VB" %>
2
<%@Import Namespace="System.Globalization" %>
3
4
<script runat="server">
5
sub Page_Load(obj as object,e as eventargs)
6
lblMessage.Text =Request.UserLanguages(0).ToString
7
end sub
8
</script>
9
10
<html><body>
11
Twoim głównym j
ę
zykiem jest:
12
<asp:Label id="lblMessage" runat="server"/>
13
</body></html>
Analiza
W wierszu 2. importowana jest zupełnie nowa przestrzeń nazw —
System.Globalization
.
Zawiera ona wiele klas, które będą konieczne przy modyfikacji wyników działania aplikacji w
zaleŜności od ustawień językowych i kulturowych. Warto zwrócić uwagę, iŜ w powyŜszym
przykładzie nie jest uŜywany Ŝaden obiekt którejkolwiek z klas dostępnych w tej przestrzeni nazw.
JuŜ nie długo będziemy jednak z nich korzystać! W wierszu 6. jest pobierany i wyświetlany
główny język uŜytkownika. Właściwość
UserLanguages
zwraca tablicę języków wybranych
przez uŜytkownika (określonych w przeglądarce), posortowaną według priorytetów tych języków
(najczęściej uŜywane języki oraz ich kody zostały przedstawione w tabeli 19.1). Język główny (lub
język o najwyŜszym priorytecie) moŜna określić przy uŜyciu wyraŜenia
UserLanguages(0)
.
Wyniki wykonania strony z listingu 19.9 zostały przedstawione na rysunku 19.8.
Tabela 19.1.
Najczęściej wykorzystywane języki i ich kody.
Język
Kod
Angielski (Anglia)
en-uk
Angielski (Australia)
en-au
Angielski (Kanada)
en-ca
Angielski (Stany Zjednoczone)
en-us
Arabski (Egipt)
ar-eg
Chiński (Hong-Kong)
zh-hk
Flamandzki (Belgia)
nl-be
Francuski (Francja)
fr
Hiszpańki (tradycyjny)
es
Hiszpański (Meksyk)
es-mx
Japoński
ja
Koreański
ko
Niemiecki (Niemcy)
de
Polski
pl
Portugalski (Portugalia)
pt
Rosyjski (Rosja)
ru
Włoski (Włochy)
it
Rysunek 19.8.
Obiekt
Request
moŜe posłuŜyć od określenia głównego języka wybranego w
przeglądarce
Teraz, po określeniu głównego języka moŜna na jego podstawie określić informacje kulturowe,
które będą wykorzystywane w aplikacji ASP.NET. W tym celu posłuŜymy się obiektem klasy
System.Globalization.CultureInfo
. Obiekty tej klasy zawierają kompletne informacje
reprezentujące kulturę określaną przez uŜywany język. Do informacji tych, oprócz języka, naleŜy
takŜe uŜywany kalendarz, nazwy krajów, format zapisu liczb i dat, oraz wiele innych elementów.
Przykład wykorzystania obiektu tej klasy został przedstawiony na listingu 19.10.
Listing 19.10.
Wykorzystanie obiektu klasy
CultureInfo
.
1
<%@ Page Language="VB" %>
2
<%@ Import Namespace="System.Globalization" %>
3
4
<script runat="server">
5
sub Page_Load(obj as object, e as eventargs)
6
dim strLanguage as string = Request.UserLanguages(0).ToString
7
8
lblMessage.Text = "J
ę
zyk główny: " & _
9
strLanguage & "<br>"
10
11
dim objCulture as new CultureInfo(strLanguage)
12
lblMessage.Text += "Pełna nazwa: " & _
13
objCulture.EnglishName & "<br>"
14
lblMessage.Text += "Nazwa rodzima: " & _
15
objCulture.NativeName & "<br>"
16
lblMessage.Text += "Skrót: " & _
17
objCulture.ThreeLetterISOLanguageName & "<br>"
18
lblMessage.Text += "Godzina: " & _
19
DateTime.Now.ToString("D", objCulture) & "<br>"
20
21
end sub
22
</script>
23
24
<html><body>
25
<b>Informacje kulturowe o u
Ŝ
ytkowniku:</b> <p>
26
<asp:Label id="lblMessage" runat="server"/>
27
</body></html>
Analiza
PowyŜszy kod jest modyfikacją przykładu z listingu 19.9. W wierszu 2. importowana jest
przestrzeń nazw
System.Globalization
. W wierszach 6. i 7. pobierany jest główny język
przeglądarki uŜytkownika (w identyczny sposób jak na listingu 19.9). Język ten jest następnie
wyświetlany w etykiecie zdefiniowanej w wierszu 26. W wierszu 12., tworzony jest nowy obiekt
klasy
CultureInfo
bazujący na pobranym wcześniej języku głównym
1
. W wierszach od 13. do
20. wyświetlane są róŜne informacje kulturowe. W celu poprawnego sformatowania daty została
wykorzystana metoda
ToString
akceptująca dwa argumenty — łańcuch znaków określający
sposób wyświetlenia daty oraz obiekt
CultureInfo
zawierający dodatkowe informacje
określające postać daty. Na rysunku 19.9 zostały przedstawione wyniki wykonania powyŜszej
strony ASP.NET w przypadku gdy głównym językiem wybranym w przeglądarce jest francuski.
Rysunek 19.9.
Wyniki wygenerowane przez stronę zostały dostosowane do ustawień
kulturowych uŜytkownika i to bez wprowadzania jakichkolwiek modyfikacji w kodzie
Klasa
CultureInfo
udostępnia więcej właściwości, które pozwalają na uzyskanie bardziej
szczegółowych informacji na temat ustawień kulturowych. Najczęściej stosowane właściwości tej
klasy zostały przedstawione w tabeli 19.2.
Tabela 19.2.
Właściwości klasy
CultureInfo
.
Właściwość
Opis
Calendar
Kalendarz uŜywany w danej kulturze (na przykład:
gregoriański, koreański, itp.).
CurrentCulture
Właściwość określa informacje kulturowe ustawione na
serwerze (a nie w przeglądarce uŜytkownika).
Właściwość ta zwraca obiekt klasy
CultureInfo
.
1
Jest całkiem prawdopodobne, Ŝe przy domyślnych ustawieniach przeglądarki, na przykład polskiej wersji
Internet Explorera, powyŜszy przykład nie będzie działać poprawnie. W przeglądarce moŜe zostać
wyświetlone komunikat o błędzie rozpoczynający się od słów: „Culture "pl" is a neutral culture....” NaleŜy
go rozumieć w ten sposób, iŜ informacje kulturowe określone przez przeglądarkę nie są wystarczające by na
ich podstawie moŜna było określić sposób formatowania informacji. Rozwiązanie tego problemu sprowadza
się do określenia (w przeglądarce) bardziej szczegółowych informacji na temat wybranego języka głównego,
na przykład zamiast języka
Polski [pl]
, naleŜy podać język
pl-pl
. Po wybraniu języka głównego o takiej
postaci powyŜszy przykład będzie działać poprawnie.
Właściwość jest przeznaczona wyłącznie do odczytu.
CurrentUICulture
Właściwość pobiera informacje kulturowe uŜywane na
serwerze. Jest ona uŜywana do określania ustawień
kulturowych plików zasobów. (Patrz podrozdział
„Zapisywanie zasobów w plikach”, w dalszej części tego
rozdziału.) Właściwość taj jest przeznaczona wyłącznie
do odczytu.
DateTimeFormat
Zwraca obiekt klasy
DateTimeFormatInfo
określający
sposób formatowania daty i czasu zgodnie z bieŜącymi
ustawieniami kulturowymi. Więcej informacji na ten
temat moŜna znaleźć w dokumentacji .NET SDK.
DisplayName
Pełna nazwa kultury reprezentowanej przez dany obiekt
CultureInfo
, w języku określonym przez interfejs
uŜytkownika.
EnglishName
Pełna nazwa obiektu klasy
CultureInfo
w języku
angielskim.
Name
To samo co właściwość
DisplayName
, z tym iŜ ta jest
przeznaczona wyłącznie do odczytu.
NativeName
Pełna nazwa obiektu klasy
CultureInfo
w danym
języku.
NumberFormat
Właściwość określa format wyświetlania liczb (czyli
gdzie umieszczać przecinki, punkty dziesiętne, itp.)
Zwraca obiekt klasy
NumberFormatInfo
.
ThreeLetterISOLanguageName
Trzyliterowy kod oznaczający daną kulturę w standardzie
ISO 3166.
ThreeLetterWindowLanguageName
Wersja trzyliterowego oznaczenia kultury stosowana w
systemie Windows.
TwoLetterISOLanguageName
Dwuliterowy kod oznaczający daną kulturę w standardzie
ISO 3166.
Informacje kulturowe dla danej strony ASP.NET moŜna takŜe określić przy uŜyciu atrybutu
Culture
dyrektywy
@ Page
. PoniŜsza dyrektywa sprawi, Ŝe na stronie zostaną wykorzystane
ustawienia kulturowe dla języka niemieckiego:
<%@ Page Language="VB" Culture="de" %>
W tym przypadku, jeśli na stronie będą wykorzystywane obiekty związane z ustawieniami
kulturowymi, to wykorzystają one ustawienia kulturowe podane w dyrektywie
@ Page
a nie
określone przez serwer. Na przykład, w przypadku wykorzystania ustawień kulturowych dla
języka niemieckiego, wywołanie
DateTime.Now.ToString("D")
spowoduje wyświetlenie
następującej daty:
Montag, 3. Dezember 2001
W przypadku uŜycia ustawień kulturowych dla języka oznaczonego symbolem
en-us
, ten sam
fragment kodu wygeneruje wyniki:
Monday, December 03, 2001
To bardzo prosty sposób określania ustawień kulturowych jakie mają być wykorzystane na stronie,
o ile są one z góry znane.
Notatka
Wła
ś
ciwo
ść
CultureInfo.CurrentCulture
jest w rzeczywisto
ś
ci „skrótem” do wła
ś
ciwo
ś
ci
System.Threading.CurrentThread.CurrentCulture
. Obie te wła
ś
ciwo
ś
ci zwracaj
ą
obiekt klasy
CultureInfo
, który mo
Ŝ
e zosta
ć
wykorzystany w sposób przedstawiony na
powy
Ŝ
szych przykładach. Ró
Ŝ
nica pomi
ę
dzy nimi polega na tym, i
Ŝ
wła
ś
ciwo
ść
CultureInfo.CurrentCulture
jest przeznaczona wył
ą
cznie do odczytu, natomiast
wła
ś
ciwo
ść
System.Threading.CurrentThread.CurrentCulture
pozwala tak
Ŝ
e na
zapis informacji. Z tego powodu, je
ś
li b
ę
dziesz musiał zmieni
ć
bie
Ŝą
ce ustawienia kulturowe
powiniene
ś
posłu
Ŝ
y
ć
si
ę
t
ą
drug
ą
wła
ś
ciwo
ś
ci
ą
.
Kultura jest wła
ś
ciwo
ś
ci
ą
aktualnie wykonywanego w
ą
tku (innymi słowy — aktualnie
wykonywanego fragmentu bie
Ŝą
cej aplikacji). W przypadku okre
ś
lania ustawie
ń
kulturowych w
ASP.NET s
ą
one okre
ś
lane dla całej aplikacji. Oznacza to,
Ŝ
e te same informacje kulturowe
mo
Ŝ
na pobra
ć
za po
ś
rednictwem bie
Ŝą
cego w
ą
tku jak i z obiektu
CultureInfo
. (W dalszej
cz
ęś
ci
rozdziału
zostanie
przedstawiony
przykład
wykorzystania
obiektu
System.Threading.CurrentThread
.
Oprócz obiektu
CultureInfo
moŜna takŜe wykorzystać obiekt klasy
RegionInfo
zawierający,
między innymi, informacje o symbolu waluty oraz o tym, czy w danym regionie jest
wykorzystywany system metryczny. Sposób uŜycia obiektów obu tych klas jest bardzo podobny, z
tym, Ŝe w przypadku obiektów klasy
RegionInfo
nie moŜna podawać języka w celu określenia
postaci pobieranych informacji — zamiast nich wykorzystywane są skróty nazw krajów. Na
przykład:
US
dla Stanów Zjednoczonych bądź
FR
dla Francji. Przykład wykorzystania obiektów tej
klasy został przedstawiony na listingu 19.11.
Listing 19.11.
Wyświetlanie informacji o regionie z jakiego pochodzi uŜytkownik.
1
<%@ Page Language="VB" %>
2
<%@ Import Namespace="System.Globalization" %>
3
4
<script runat="server">
5
sub Page_Load(obj as object, e as eventargs)
6
dim objRegion as RegionInfo
7
8
if Page.IsPostBack then
9
objRegion = new RegionInfo(btRegion.Text)
10
else
11
objRegion = RegionInfo.CurrentRegion
12
end if
13
14
lblMessage.Text = "Region: " & objRegion.Name & "<br>"
15
16
lblMessage.Text += "Pełna nazwa: " & _
17
objRegion.EnglishName & "<br>"
18
lblMessage.Text += "Waluta: " & _
19
objRegion.CurrencySymbol & "<br>"
20
lblMessage.Text += "Waluta ISO: " & _
21
objRegion.ISOCurrencySymbol & "<br>"
22
lblMessage.Text += "Skrót: " & _
23
objRegion.ThreeLetterISORegionName & "<br>"
24
lblMessage.Text += "Czy jest u
Ŝ
ywany system metryczny: " _
25
& objRegion.IsMetric
26
end sub
27
</script>
28
29
<html><body>
30
<form runat="server">
31
<b>Twoje ustawienia:</b> <p>
32
<asp:Label id="lblMessage" runat="server"/><p>
33
Zmie
ń
na (i.e. 'US', 'FR', 'JP', etc):
34
<asp:TextBox id="btRegion" runat="server"
35
AutoPostBack=true />
36
</form>
37
</body></html>
Analiza
W momencie pierwszego wyświetlenia powyŜszej strony, do obiektu
RegionInfo
zostaną
wczytane domyślne informacje o regionie (patrz wiersz 11.). Informacje o aktualnie wybranym
regionie są wyświetlane w wierszach od 14. do 25., między innymi naleŜą do nich symbol i skrót
waluty. Gdy uŜytkownik wpisze jakieś informacje w polu tekstowym zdefiniowanym w wierszach
34. i 35. strona zostanie automatycznie wyświetlona ponownie (dzięki uŜyciu atrybutu
AutoPostBack
o wartości
true
). Kod regionu podany przez uŜytkownika w polu tekstowym jest
następnie wykorzystywany w celu stworzenia nowego obiektu
RegionInfo
(patrz wiersz 9.).
Wygląd strony po wybraniu regionu o kodzie
JP
(czyli Japonii) został przedstawiony na rysunku
19.10.
Rysunek 19.10. Na stronie zostają wyświetlone informacje o wybranym regionie
Najczęściej wykorzystywane właściwości klasy
RegionInfo
zostały przedstawione w tabeli 19.3.
Tabela 19.3.
Właściwości klasy
RegionInfo
.
Właściwość
Opis
CurrencySymbol
Symbol uŜywany do oznaczania wartości monetarnych w
danym regionie.
CurrentRegion
Właściwość pobiera domyślny serwer uŜywany na serwerze
(a nie na komputerze uŜytkownika). Właściwość zwraca
obiekt klasy
RegionInfo
.
DisplayName
Pełna nazwa regionu identyfikowanego przez obiekt
RegionInfo
w języku określonym przez interfejs
uŜytkownika.
EnglishName
Nazwa regionu identyfikowanego przez obiekt
RegionInfo
w języku angielskim.
IsMetric
Wartość logiczna określająca czy w danym regionie
wykorzystywany jest system metryczny.
ISOCurrencySymbol
Kod ISO znaku zapisanego we właściwości
CurrencySymbol
. Na przykład, znakowi
$
odpowiada kod
ISO
USD
.
Name
Zawiera te same informacje co właściwość
CurrencySymbol
, lecz jest przeznaczona wyłącznie do
odczytu.
ThreeLetterISORegionName
Trzyliterowy kod oznaczający daną kulturę w standardzie
ISO 3166.
ThreeLetterWindowRegionName
Wersja trzyliterowego oznaczenia kultury stosowana w
systemie Windows.
TwoLetterISORegionName
Dwuliterowy kod oznaczający daną kulturę w standardzie
ISO 3166.
Nowe wyraŜenie
Istnieje takŜe moŜliwość określenia sposobu
kodowania
wyników generowanych przez strony
ASP.NET. Kodowanie, to sposób w jaki znaki są reprezentowane przez komputer; przykładowe
sposoby kodowania to Unicode lub ASCII. Strony ASP.NET domyślnie uŜywają kodowania
Unicode, jednak ustawienie to moŜe się zmieniać w zaleŜności od regionu.
Dostępne są dwa, róŜne sposoby określania sposobu kodowania wykorzystywanego w aplikacji —
bezpośrednio na stronach ASP.NET bądź teŜ w pliku
web.config
. Na stronach ASP.NET sposób
kodowania określa się przy uŜyciu atrybutu
ResponseEncoding
dyrektywy
@ Page
; jak na
poniŜszym przykładzie:
<%@ Page Language="VB" ResponseEncoding="UTF-8" %>
W przypadku określania sposobu kodowania w pliku
web.config
naleŜy to zrobić w następujący
sposób:
<configuration>
<system.web>
<globalization fileEncoding="utf-8" />
</system.web>
</configuration>
Jak na razie przedstawione zostały wyłącznie sposoby zmieniania informacji generowanych przez
obiekty związane z ustawieniami kulturowymi i regionalnymi, a co ze zwykłym tekstem? Jak
moŜna skonwertować zwyczajny tekst, tak aby korzystał z wybranych ustawień językowych?
Niestety nie moŜna tego zrobić w Ŝaden prosty sposób — trzeba po prostu, samodzielnie
przetłumaczyć tekst. Jeśli witryna jest odwiedzana przez osoby posługujące się róŜnymi językami,
to zazwyczaj będzie to oznaczać konieczność stworzenia odrębnych wersji językowych kaŜdej ze
stron. Na szczęście w ASP.NET nie trzeba się uciekać do aŜ tak drastycznych rozwiązań — moŜna
bowiem wykorzystać pliki zasobów.
Zapisywanie zasobów w plikach
Pliki zasobów są uŜywane do przechowywania informacji wykorzystywanych w aplikacjach
niezaleŜnie od ich kodu. Istnieje moŜliwość zastosowania wielu wersji pliku zasobów, dzięki
czemu strony ASP.NET mogą prezentować róŜne informacje bez konieczności wprowadzania
jakichkolwiek zmian w kodzie. Posługując się przykładem lokalizacji, moŜna by stworzyć wiele
róŜnych plików zasobów, po jednym dla kaŜdego z ustawień kulturowych wykorzystywanych
przez uŜytkowników odwiedzających witrynę. KaŜdy z tych plików zawierałby dokładnie te same
informacje zapisane w róŜnych językach.
Przeanalizujmy przykład prostej strony ASP.NET, której treść moŜna umieścić w pliku zasobów.
Kod tej strony został przedstawiony na listingu 19.12.
Listing 19.12.
Strona ASP.NET, która posłuŜy jako przykład wykorzystania plików zasobów.
1
<%@ Page Language="VB" %>
2
3
<script runat="server">
4
sub Page_Load(obj as Object, e as EventArgs)
5
lblMessage.Text = DateTime.Now.ToString("t")
6
end sub
7
</script>
8
9
<html><body>
10
<b>Witamy!</b> Teraz jest:
11
<asp:Label id="lblMessage" runat="server"/><p>
12
13
Ta strona demonstruje sposób wykorzystywania plików zasobów
14
w ASP.NET.<p>
15
16
<font size=1>Nie zapomnij sprawdzi
ć
tego w domu!</font>
17
</body></html>
PowyŜszy przykład jest bardzo prosty — wyświetla kilka komunikatów tekstowych o stałej treści
oraz bieŜącą godzinę. Wyniki wykonania tej strony zostały przedstawione na rysunku 19.11.
Rysunek 19.11. Prosta strona ASP.NET w której moŜna wykorzystać pliki zasobów
ZałóŜmy, Ŝe chcielibyśmy przetłumaczyć tę stronę na język francuski. Oczywiście moŜna by
stworzyć nową wersję strony o tej samej postaci lecz z innymi komunikatami tekstowymi, ale po
co utrudniać sobie Ŝycie? Znacznie lepszym rozwiązaniem będzie stworzenie dwóch plików
zasobów. Są to zwyczajne pliki tekstowe, które moŜna utworzyć przy uŜyciu dowolnego edytora
tekstów. W pierwszej kolejności stwórzmy polską wersję takiego pliku. W tym celu, w edytorze
tekstowym naleŜy wpisać poniŜszy tekst:
[strings]
Powitanie=Witamy!
Czas=Teraz jest:
Tresc=Ta strona demonstruje sposób wykorzystywania plików zasobów w ASP.NET
Stopka=<font size=1>Nie zapomnij sprawdzi
ć
tego w domu!</font>
Zapisz ten fragment tekstu w pliku o nazwie
data.pl.txt
(za chwilę wyjaśnię dlaczego nazwa pliku
ma akurat taką postać). Utworzony plik zawiera jedną sekcję, w której zostały zapisane wszystkie
wykorzystywane łańcuchy znaków. Informacje zostały zapisane w formie par nazwa-wartość:
Powitamie=Witamy!
Powitanie
jest nazwą zasobu do którego będziemy się odwoływać w kodzie strony ASP.NET,
natomiast
Witamy!
jest wartością jaka zostanie wyświetlona na stronie wynikowej. PoniŜej
przedstawiona została francuskojęzyczna wersja pliku zasobów:
[strings]
Powitanie=Bonjour!
Czas=L'heure maintenent est:
Tresc=Cette page demonstrate utiliser files de resource avec ASP.NET
Stopka=<font size=1>N'oublie pas essayez de faire ceci chez soi!</font>
PowyŜszy tekst zapisz w pliku o nazwie
data.fr.txt
. (Tworząc oba pliki tekstowe naleŜy pamiętać,
aby kaŜdy z łańcuchów znaków został zapisany w osobnym wierszu. Jeśli w łańcuchu znaków
znajdą się znaki nowego wiersza, to podczas generacji właściwych plików zasobów pojawią się
błędy.) Warto zwrócić uwagę, iŜ w obu plikach zostały uŜyte te same nazwy kluczy. Nazwy te
muszą być identyczne, gdyŜ w przeciwnym przypadku ASP.NET nie będzie w stanie odszukać
zasobów.
ASP.NET nie jest jednak w stanie korzystać z plików zasobów w ich obecnej postaci. Trzeba je
zatem skonwertować do postaci, którą ASP.NET będzie rozumieć. Do tego celu słuŜy program
narzędziowy
resgen.exe
(nazywany takŜe generatorem zasobów). Program ten konwertuje
tekstowe pliki zasobów i na ich podstawie generuje pliki z rozszerzeniem
.resources
. A zatem,
wyświetl okno wiersza poleceń i przejdź do folderu, w którym zapisałeś stworzone wcześniej pliki
.txt
. Następnie wydaj poniŜsze polecenie (i nie zapomnij nacisnąć klawisza
Enter
):
resgen data.pl.txt
resgen data.fr.txt
Program powinien wyświetlić następujące wyniki:
Read in 4 resources from 'data.pl.txt'
Writing resource file... Done.
Po wykonaniu powyŜszych poleceń w folderze pojawią się dwa nowe pliki —
data.pl.resources
oraz
data.fr.resources
. Z tych plików moŜe juŜ korzystać zarządca zasobów ASP.NET. A zatem,
uŜyjmy tych zasobów na stronie ASP.NET!
Za obsługę wszystkich zasobów w ASP.NET odpowiada obiekt klasy
System.Resources.ResourceManager
. Obiekt taki jest w stanie odnaleźć plik zasobów
odpowiadający ustawieniom kulturowym wykorzystywanym przez uŜytkownika i pobrać zapisane
w nim zasoby. Sposób uŜycia tego obiektu został przedstawiony na listingu 19.13.
Listing 19.13.
Pobieranie informacji z plików zasobów przy wykorzystaniu obiektu
ResourceManager
.
1
<%@ Page Language="VB" %>
2
<%@ Import Namespace="System.Globalization" %>
3
<%@ Import namespace="System.Resources" %>
4
<%@ Import namespace="System.Threading" %>
5
6
<script runat="server">
7
sub Page_Load(obj as object, e as eventargs)
8
dim objRM as ResourceManager
9
dim strLanguage as string = _
10
Request.UserLanguages(0).ToString
11
dim objCulture as new CultureInfo(strLanguage)
12
Thread.CurrentThread.CurrentCulture = _
13
new CultureInfo(strLanguage)
14
Thread.CurrentThread.CurrentUICulture = _
15
new CultureInfo(strLanguage)
16
17
objRM = ResourceManager. _
18
CreateFileBasedResourceManager("data", _
19
Server.MapPath("."), Nothing)
20
21
lblGreeting.Text = objRM.GetString("Powitanie")
22
lblTime.Text = objRM.GetString("Czas") & " " & _
23
DateTime.Now.ToString("t")
24
lblBlurb.Text = objRM.GetString("Tresc")
25
lblDisclaimer.Text = objRM.GetString("Stopka")
26
27
objRM.ReleaseAllResources
28
end sub
29
</script>
30
31
<html><body>
32
<b><asp:Label id="lblGreeting" runat="server"/></b>
33
<asp:Label id="lblTime" runat="server"/><p>
34
35
<asp:Label id="lblBlurb" runat="server"/><p>
36
37
<asp:Label id="lblDisclaimer" runat="server"/>
38
</body></html>
Analiza
W pierwszej kolejności naleŜy zwrócić uwagę na wykorzystanie dwóch dodatkowych przestrzeni
nazw, importowanych w wierszach 3. i 4. Przestrzeń nazw
System.Resources
jest konieczna
aby moŜna było korzystać z obiektu
ResourceManager
. TakŜe przestrzeń nazw
System.Threading
jest niezbędna (w dalszej części rozdziału wyjaśnię dlaczego). W wierszu 8.,
w standardowy sposób, deklarowany jest nowy obiekt
ResourceManager
. W wierszach 9. i 10.
określany jest główny język wybrany w przeglądarce (główny język jest określany w taki sam
sposób jak w przykładzie przedstawionym na listingu 19.9.).
W wierszach do 12. do 15., na podstawie wybranego języka głównego, określane są ustawienia
kulturowe. Pamiętasz zapewne, Ŝe informacje kulturowe moŜna podawać przy wykorzystaniu
właściwości
System.Threading.CurrentThread.CurrentCulture
, która pozwala na
pobranie lub zapis obiektu klasy
CultureInfo
(była o tym mowa we wcześniejszej części
rozdziału, w podrozdziale pt.: „Lokalizowanie aplikacji”). W wierszu 12. tworzony jest nowy
obiekt klasy
CultureInfo
zawierający informacje kulturowe wybrane na podstawie określonego
wcześniej głównego języka uŜywanego w przeglądarce. Wszystkie obiekty, które dysponują
moŜliwością lokalizacji, będą teraz wykorzystywały wybrane informacje kulturowe (na przykład,
po wybraniu informacji kulturowych dla języka angielskiego, godzina będzie wyświetlana w
formie 10:16 PM, a nie 22:16).
Niemniej jednak sam fakt zmiany ustawień kulturowych nie sprawi, Ŝe ASP.NET pobierze dane z
odpowiednich plików zasobów. W tym celu, oprócz wybrania odpowiednich informacji
kulturowych, naleŜy takŜe przypisać odpowiednią wartość właściwości
System.Threading.CurrentThread.CurrentUICulture
(patrz wiersze 14. i 15.). To
właśnie na podstawie tej właściwości ASP.NET określa jaki plik zasobów naleŜy uŜyć.
Odczytanie zasobów z pliku realizowane jest przez metodę
CreateFileBasedResourceManager
, której wywołanie zostało zapisane w wierszach od 17. do
19. Metoda ta wymaga podania trzech argumentów — początkowej części (prefiksu) nazwy
plików zasobów, ścieŜki dostępu do tych plików oraz obiektu którego naleŜy uŜyć do
przetworzenia informacji pobranych z pliku zasobów (przy czym ten trzeci argument jest
opcjonalny). Wartość drugiego argumentu określana jest przy uŜyciu metody
Server.MapPath
,
która zwraca fizyczną ścieŜkę dostępu do folderu w jakim są przechowywane pliki zasobów.
(Więcej informacji na temat metody
MapPath
moŜna znaleźć w rozdziale 4., pt.: „Stosowanie
obiektów ASP.NET w językach C# i VB.NET”, w podrozdziale „Obiekt HttpServerUtility”.) W
naszym przypadku nie jest potrzebny Ŝaden obiekt słuŜący do przetwarzania danych pobieranych z
pliku zasobów, a zatem jako trzeci argument wywołania metody
CreateFileBasedResourceManager
naleŜy przekazać wartość
Nothing
.
Przypomnij sobie, Ŝe nazwy plików zasobów mają następującą postać —
data.kultura.resources
.
Metoda
CreateFileBasedResourceManager
poszukuje plików o nazwach pasujących do
schematu
prefiks.kultura.resources
. A zatem, prefiks podany w wywołaniu tej metody musi
odpowiadać początkowej części nazw plików zasobów. W naszym przypadku, w razie wybrania
ustawień kulturowych dla języka
pl
(polskiego) metoda będzie poszukiwać pliku o nazwie
data.pl.resources
, natomiast w razie wybrania ustawień kulturowych dla języka
fr
(francuskiego)
będzie ona poszukiwać pliku
data.fr.resources
. Prefiks słuŜy do logicznego grupowania plików
zasobów.
Następnie, w wierszach do 21. do 25. wywoływana jest metoda
GetString
obiektu
ResourceManager
, która pobiera pary klucz-wartość zapisane w pliku zasobów. Pobrane
łańcuchy znaków są wyświetlane na stronie wynikowej przy uŜyciu czterech etykiet (elementów
sterujących
Label
), zdefiniowanych w wierszach do 32. do 35. Otwierając plik zasobów
zarządzający nimi mechanizm blokuje dostęp do nich, dzięki czemu Ŝadne inne aplikacje nie będą
w stanie ich zmienić. Na rysunkach 19.12 oraz 19.13 zostały przedstawione wyniki wykonania
strony z listingu 19.13, w przypadku wyboru ustawień kulturowych dla języków
pl-PL
oraz
fr-
FR
.
Rysunek 19.12. W przypadku wybrania ustawień kulturowych dla języka
pl-PL
ASP.NET
pobiera dane z pliku zasobów
data.pl.resources
Rysunek 19.13. W przypadku wybrania ustawień kulturowych dla języka
fr-FR
ASP.NET
pobiera dane z pliku zasobów
data.fr.resources
Notatka
Warto pami
ę
ta
ć
,
Ŝ
e informacje kulturowe mo
Ŝ
na tak
Ŝ
e okre
ś
li
ć
przy u
Ŝ
yciu atrybut
Culture
dyrektywy
@ Page
:
<%@ Page Language="VB" Culture="fr-FR" %>
Je
ś
li jednak zastosujesz takie rozwi
ą
zanie w ostatnim przykładzie, to zasoby nie zostan
ą
pobrane z odpowiedniego pliku. Problem polega na tym, i
Ŝ
informacje kulturowe s
ą
okre
ś
lana
na podstawie głównego j
ę
zyka u
Ŝ
ywanego w przegl
ą
darce (okre
ś
lanego w wierszu 9.), a nie na
podstawie atrybutu dyrektywy
@ Page
. Aby rozwi
ą
za
ć
ten problem, wiersze do 9. do 11. listingu
19.13 nale
Ŝ
y zast
ą
pi
ć
nast
ę
puj
ą
cym fragmentem kodu:
dim strLanguage as string = CultureInfo.CurrentCulture.ToString
Podpowied
ź
Zazwyczaj w całej aplikacji powinny by
ć
wykorzystywane te same informacje kulturowe, dlatego
mo
Ŝ
esz zastanowi
ć
si
ę
nad wykorzystaniem rozwi
ą
zania polegaj
ą
cego na podaniu tych
informacji w metodzie
Application_BeginRequest
definiowanej w pliku
global.asax
. W ten
sposób informacje kulturowe b
ę
d
ą
poprawnie ustawiane przed rozpocz
ę
ciem obsługi ka
Ŝ
dego
Ŝą
dania odbieranego na serwerze.
Innym rozwi
ą
zaniem mogłoby by
ć
stworzenie obiektu
ResourceManager
i zapisanie go jako
zmiennej aplikacyjnej w metodzie
Application_OnStart
. W ten sposób mo
Ŝ
na unikn
ąć
konieczno
ś
ci
tworzenia
obiektów
ResourceManager
podczas
obsługi
ka
Ŝ
dego
otrzymywanego
Ŝą
dania. Na przykład, do metody
Application_OnStart
mo
Ŝ
na by doda
ć
poni
Ŝ
szy fragment kodu:
Application("RM") = New ResourceManager("data", _
Server.MapPath("."), Nothing)
Powy
Ŝ
szy fragment kodu tworzy obiekt
ResourceManager
dost
ę
pny dla całej aplikacji. Dost
ę
p
do niego mo
Ŝ
na uzyska
ć
za pomoc
ą
wyra
Ŝ
enia
Application("RM")
.
To nie jest ASP!
DąŜenie od oddzielenia kodu od treści stron WWW i czerpania wynikających z tego korzyści nie
jest niczym nowym w technologii ASP.NET. W rzeczywistości programiści ASP dąŜyli do tego
celu juŜ od dłuŜszego czasu, zwłaszcza w klasycznej technologii ASP bazującej na wykorzystaniu
bloków kodu wykonywalnego a nie bloków deklarowania kodu. Brak moŜliwości separacji kodu
od treści sprawiał, iŜ kod ASP musiał się przeplatać ze zwyczajnym kodem HTML. To z kolei
niezwykle utrudniało testowanie i modyfikację stron ASP, gdyŜ programiści musieli szukać
błędów na całej stronie. Dzięki wykorzystaniu bloków deklarowania kodu problem ten niemal
całkowicie znikną, gdyŜ cały kod jest umieszczany w jednym miejscu — na samym początku
strony ASP.NET.
Programiści korzystający z tradycyjnej technologii ASP musieli oddzielać kod od treści stron przy
uŜyciu mechanizmów dołączania zawartości plików zewnętrznych (SSI). W takich dołączanych
plikach moŜna było umieszczać całkowicie dowolny kod, w tym takŜe kod HTML, dlatego teŜ
często w nich umieszczano fragmenty interfejsu uŜytkownika wraz z ich obsługą. Mechanizmy
dołączania plików są wciąŜ dostępne lecz w stronach ASP.NET znacznie częściej korzysta się
aktualnie z elementów sterujących uŜytkownika lub kodu obsługi formularzy. Oba te rozwiązania
— zarówno elementy sterujące uŜytkownika, jak i kod obsługi formularzy — dają znacznie
większe moŜliwości programistycznej kontroli nad tworzonym kodem niŜ technologia SSI, w
której moŜliwości takie praktycznie nie istniały.
Zupełnie nowym elementem ASP.NET są pliki zasobów. Programiści którzy mieli kontakt z
językami takimi jak Visual Basic (VB) lub C++ mogli się juŜ z nimi spotkać. Pliki zasobów były
w tych językach bardzo często wykorzystywane, zresztą z tych samych powodów, dla których
aktualnie są one dostępne takŜe w ASP.NET — głównie chodzi tu o moŜliwość oddzielania kodu
od treści.
W klasycznej technologii ASP nie było Ŝadnych moŜliwości oddzielenia od stron ASP informacji
wykorzystywanych przy lokalizowaniu aplikacji. Z tego względu, bardzo często trzeba było
tworzyć wiele wersji tej samej strony. Co więcej, wcześniejsze wersje technologii ASP nie
pozwalały na modyfikowanie informacji kulturowych i regionalnych.
Wszystkie te modyfikacje sprawiają, Ŝe technologia ASP.NET jest znacznie bardziej
wszechstronna niŜ jej poprzednie wersje. Aktualnie programiści mają znacznie więcej moŜliwości
związanych z rozmieszczaniem kodu na stronach.