background image

Najcz

ęś

ciej popełniane bł

ę

dy 

w ASP.NET 

W tym dodatku zostało opisanych wiele błędów najczęściej popełnianych przez programistów 
ASP.NET i to niezaleŜnie od tego czy są oni zupełnie początkujący czy teŜ mają duŜe 
doświadczenie w tworzeniu aplikacji w tradycyjnej technologii ASP. Istnieje wiele przykładów 
prostych błędów, które mogą sprawić, Ŝe programiści będą łamać sobie głowy próbując określić co 
się dzieje. W rzeczywistości wiele spośród tych błędów moŜna bardzo łatwo poprawić. Dodatek 
ten został napisany w formie krótkiego poradnika prezentującego takie błędy. Dzięki niemu 
programiści ASP.NET będą w stanie błyskawicznie znaleźć przyczynę błędu, poprawić go oraz 
dowiedzieć się jak w przyszłości unikać błędów tego typu. 

Niniejszy dodatek został podzielony na dwie części. W pierwszej z nich zostały opisane błędy 
typowe dla technologii ASP.NET, które bardzo często pozostają niezauwaŜone. W drugiej części 
opisane zostały zmiany, na które naleŜy zwrócić szczególną uwagę przy przerabianiu klasycznych 
stron ASP na strony ASP.NET. Między innymi chodzi tu takŜe o ogromne róŜnice syntaktyczne 
pomiędzy językami VBScript a VB.NET. 

Zagadki ASP.NET 

ASP.NET ma wiele szczególnych cech, które mogą się stać przyczyną prawdziwych tragedii 
programistycznych. KaŜda z sekcji podanych w tej części rozdziału podaje typowe komunikaty o 
błędach wyświetlane w razie napotkanie konkretnego problemu, szczegółowy opis tego problemu 
oraz sposób jego rozwiązania. (NaleŜy zwrócić uwagę iŜ fragmenty komunikatów o błędach 
wyświetlone kursywą, mogą zostać zastąpione bardziej szczegółowymi nazwami.) 

Problemy z formularzami internetowymi 

Problem

Unexpected end of file looking for </asp:Control> tag.

 

(Nieoczekiwany koniec pliku podczas poszukiwania zamykającego znacznika </asp:Control>) 

Opis

: Zapomniano o zamykającym znaczniku elementu sterującego ASP.NET. 

Rozwiązanie

: Wszystkie elementy sterujące muszą posiadać odpowiednie znaczniki zamykające. 

NaleŜy dodać znacznik zamykający zapisany w jeden z następujących sposobów: 

<asp:Label id="lblKomunikat" runat=”server” /> 
<asp:Label id="lblKomunikat" runat=”server” /> 

Problem

Literal content ("html") is not allowed within a 'control'.

 

(Zawartość tekstowa („html”) nie moŜe być umieszczona wewnątrz elementu sterującego 
‘elemSter’

Opis

: Próbowano utworzyć element sterujący bez koniecznego znacznika zamykającego. 

Rozwiązanie

: Problemy tego typu występują zazwyczaj w przypadku stosowania elementów 

sterujących 

DataGrid

 oraz 

DataList

 i są spowodowane pominięcie zamykającego znacznika 

elementu sterującego. Bez tego znacznika ASP.NET przyjmuje Ŝe cały dalszy kod HTML strony 

background image

jest elementem tego elementu sterującego i dlatego zgłasza błąd. Aby rozwiązać problemy tego 
typu wystarczy dopisać odpowiedni znacznik zamykający. 

Problem

: Element sterujący nie jest wyświetlany lub nie działa zgodnie z oczekiwaniami. 

Opis

: ASP.NET nie obsługuje poprawnie elementu sterującego; dane przesyłane z formularza nie 

są rozpoznawane, właściwości określające wygląd elementu nie są wyświetlane, i tak dalej. 

Rozwiązanie

: Najbardziej prawdopodobną przyczyną występowania tych problemów jest 

pominięcie atrybutu 

runat="server"

 elementu sterującego. Aby rozwiązać problem, naleŜy 

dodać ten atrybut do elementu w którym występują problemu. 

Problem

: Dane nie są poprawne wyświetlane w elemencie sterującym. 

Opis

: ASP.NET w ogóle nie wyświetla danych w elemencie sterującym, bądź teŜ nie uaktualnia 

ich poprawnie. 

Rozwiązanie

: Zapomniano o wywołaniu metody 

DataBind

Problem

An exception has been thrown by the class contstructor for 

System.Drawing.Internal.SystemColorTracker.

 (Konstruktor klasy 

System.Drawing.Internal.SystemColorTracker

  zgłosił wyjątek.) 

Opis

: ASP.NET nie jest w stanie poprawnie wyświetlić danego elementu sterującego (zazwyczaj 

dotyczy to elementów 

DataGrid

). 

Rozwiązanie

: Uruchom ponownie aplikację. MoŜna to zrobić na kilka sposobów: 

 

z poziomu wiersza poleceń uruchomić program 

iisreset

 

zmodyfikować i zapisać na dysku jeden z plików 

global.asax

 lub 

web.config

 

ponownie skompilować któryś z obiektów biznesowych zapisanych w folderze 

/bin

Problem

: Procedury obsług zdarzeń nie generują oczekiwanych wyników. 

Opis

: Korzystając z formularzy internetowych i elementów sterujących wykonywanych po stronie 

serwera starasz się wygenerować odpowiednie dane wyjściowe, ale coś nie działa zgodnie z 
oczekiwaniami. Na przykład, próbujesz zmodyfikować zawartość pola tekstowego lub etykiety, 
lecz wartość ta się nie zmienia lub zmienia się nie tak byś sobie tego Ŝyczył.  

Rozwiązanie

: Trzeba pamiętać, Ŝe zdarzenie 

Page_Load

 jest zawsze wykonywane przed 

wszystkimi innymi procedurami obsługi zdarzeń, które z kolei nie są wykonywane w Ŝadnej 
określonej kolejności. Procedura 

Page_Load

 moŜe modyfikować lub przywracać oryginalną 

wartość elementu sterującego zanim procedura obsługi zdarzenia będzie miała szansę uŜyć tej 
wartości. Taką sytuację demonstruje poniŜszy fragment kodu: 

sub Page_Load(obj as Object, e as EventArgs) 
tbMessage.Text = "Witaj 

Ś

wiecie!" 

end sub 
sub HandleSubmit(obj as Object, e as EventArgs) 
Response.Write(tbMessage.Text) 
end sub 
 
... 
 
<asp:TextBox id="tbMessage" runat="server" 
OnTextChanged="HandleSubmit" 
AutoPostBack=true /> 
... 
 

W przypadku zmiany zawartości pola tekstowego, formularz jest przesyłany na serwer. Jednak w 
pierwszej kolejności jest wykonywana metoda 

Page_Load

 która za kaŜdym razem zapisuje w 

polu tekstowym łańcuch znaków „

Witaj 

Ś

wiecie!

”. Dopiero potem procedura 

HandleSubmit

 

próbuje wyświetlić zawartość pola tekstowego, lecz zamiast podanego tekstu za kaŜdym razem 
wyświetlany jest łańcuch znaków „

Witaj 

Ś

wiecie!

”.  

Jednym z moŜliwych rozwiązań jest sprawdzenie w procedurze 

Page_Load

 wartości właściwości 

Page.IsPostBack

, na podstawie której moŜna określić czy formularz został wypełniony. W 

takim przypadku a wartości jego pól nie powinne być zmieniane: 

background image

sub Page_Load(obj as Object, e as EventArgs) 
if not Page.IsPostBack then 
tb.Message.Text = "Witaj 

Ś

wiecie!" 

end if 
end sub 

Innym sposobem jest zmiana struktury uŜywanych procedur. 

Inne problemy 

Problem: 

MissingMethodException: Member not found.

 (MissingMethodException: Nie 

odnaleziono metody lub właściwości) 

Opis: Została podjęta próba odwołania się do metody lub właściwości obiektu (zazwyczaj 
zwróconego jako wynik działania jakiejś metody). 

Rozwiązanie: Choć istnieje wiele potencjalnych przyczyn tych błędów, to jednak ten najczęściej 
spotykany wiąŜe się z rzutowaniem typów. Na przykład przeanalizujmy poniŜszą procedurę 
obsługi zdarzeń: 

sub MyHandler(obj as Object, e as EventArgs) 
Response.Write(obj.Text) 
end sub 

Zakładają Ŝe powyŜsza procedura jest wywoływana w celu obsługi zdarzeń generowanych przez 
etykietę, to powinniśmy mieć moŜliwość dostępu do jej właściwości 

Text

. Jednak nigdy nie 

naleŜy polegać na tym, co dana zmienna powinna reprezentować. Powinniśmy natomiast 
odpowiednio rzutować typ obiektu: 

Response.Write(CType(obj, Label).Text) 

W ASP.NET zmienne typu 

Object

 często wykorzystują mechanizm wczesnego łącznia, co 

oznacza, Ŝe mogą być przetwarzane juŜ w czasie kompilacji strony (a nie w czasie obsługi 
zgłoszonego Ŝądania). Właśnie z tego  powodu ASP.NET uwaŜa odwołanie do właściwości 

Text

 

za błąd — bo przecieŜ klasa 

Object

 nie definiuje takiej właściwości. Niemniej jednak, w czasie 

obsługi Ŝądania zostanie przesłane odpowiednie odwołanie; wtedy jednak jest juŜ za późno. 
NaleŜy pamiętać, aby zawsze odpowiednio rzutować typy zmiennych. 

Problem: 

The type obiekt in Assembly nazwa, Version=wersja, 

Culture=kultura, PublicKeyToken=

Ŝ

eton is not marked as serializable.

 (Typ 

obiekt w komponencie nazwa, o podanej kulturze i Ŝetonie klucza publicznego nie został 
oznaczony jako umoŜliwiający serializację.) 

Opis: Została podjęta próba zachowania obiektu w sesji lub stanie aplikacji. 

Rozwiązanie: Niektóre obiekty, takie jak na przykład obiekty 

DataSet

 nie mogą być 

automatycznie zapisywane słuŜących do przechowywania stanu. Aby rozwiązać ten problem 
naleŜy spróbować wywołać metodę ShouldSerializeObiekt obiektu który sprawia problemy. 

Problem: 

Type not defined: typ.

 (Typ typ nie został zdefiniowany) 

Opis: Została podjęta próba zadeklarowania kopii obiektu nieznanego typu. 

Rozwiązanie: NaleŜy się upewnić czy nazwa typu została zapisana poprawnie. Warto takŜe 
sprawdzić czy są importowane wszystkie konieczne przestrzenie nazw. NaleŜy pamiętać, Ŝe w 
klasach języka VB.NET (takich jak kod obsługi formularzy oraz obiekty biznesowe) przestrzenie 
nazw nie są importowane domyślnie (jak to się dzieje w przypadku stron ASP.NET). 

Zmiany w stosunku do tradycyjnej 
technologii ASP 

Przekształcając strony ASP pisane w języku VBScript do postaci stron ASP.NET pisanych w 
języku VB.NET programiści często popełniać błędy syntaktyczne oraz problemy innych typów. 
Błędy te oraz sposoby ich rozwiązywania zostały opisane w tej części niniejszego dodatku. 

background image

Problemy z j

ę

zykiem VBScript 

Błąd: 

Wend is no longer supported; use End While instead.

 (Słowo kluczowe 

Wend nie jest juŜ stosowana, zamiast niej naleŜy uŜyć instrukcji End While) 

Opis: Próbowano zakończyć pętlę 

while

 przy uŜyciu słowa kluczowego 

wend

.  

Rozwiązanie: W języku VB.NET słowo kluczowe 

wend

 nie jest dostępne, zamiast niego naleŜy 

uŜyć instrukcji 

End While

Błąd: 

The syntax <lower bound> To <upper bound> is no longer supported for 

specifying array bounds.

 (Składnia <dolna granica> To <górna granica> nie jest juŜ 

stosowana do określania zakresu indeksów tablic) 

Opis: Została podjęta próba określenia stałej wielkości tablicy. 

Rozwiązanie: W języku VBScript dopuszczalne było uŜycie instrukcji 

dim MyArray(0, 5)

 w 

celu utworzenia tablicy o stałej wielkości. W ASP.NET nie jest to moŜliwe.  

Błąd: 

The name 'mojaTablica' is not declared.

 (Zmianna mojaTablica nie została 

zadeklarowana, przy czym mojaTablica jest tablicą) 

Rozwiązanie: Prawdopodobnie została podjęta próba zadeklarowania tablicy przy uŜyciu instrukcji 

ReDim

. Zanim będzie moŜna jej uŜyć trzeba zadeklarować tablicę przy uŜyciu instrukcji 

Dim

Błąd: 

A value of type 'type' cannot be conferted to object.

 (Wartość typu ‘typ’ 

nie moŜe zostać skonwertowana do obiektu) 

Opis: Zazwyczaj oznacza to, Ŝe została podjęta próba przypisania właściwości do obiektu, bez 
określania nazwy właściwości 

Rozwiązanie: W języku VBScript obiekty dysponowały tak zwanymi domyślnymi 
właściwościami. Innymi słowy, nie trzeba było podawać nazwy takiej właściwości aby określić jej 
wartość. A zatem, posługując się hipotetycznym przykładem wykorzystującym element sterujący 

Label

, w języku VBScript moŜna by uŜyć następującego fragmentu kodu: 

dim Lable as Label 
Label = "Witaj 

Ś

wiecie!" 

 

Wykonanie powyŜszego fragmentu kodu spowodowałoby przypisani właściwości 

Text

 podanego 

łańcucha znaków. W języku VB.NET domyślne właściwości nie są juŜ dostępne, chyba Ŝe 
uŜywają parametrów. Oznacza to Ŝe naleŜy jawnie podawać nazwy właściwości: 

Label.Text = "Witaj 

Ś

wiecie!" 

Problem: 

Let and Set are no longer supported on assignment statements.

 (Przy 

przypisaniach nie są juŜ stosowane słowa kluczowe Let i Set) 

Opis: Została podjęta próba przypisania czegoś do obiektu przy wykorzystaniu słowa kluczowego 
Let lub Set. 

Rozwiązanie: Słowa kluczowe 

Let

 i 

Set

 nie są stosowane w języku VB.NET; wystarczy je 

usunąć z kodu i wszystko powinno być w porządku.  

Problem: 

The name 'N' is not declared.

 (Nazwa ‘N’ nie została zadeklarowana) Nawet 

pomimo faktu, Ŝe ją deklarowałeś. 

Opis: Deklaracja zmiennej z jednej części strony nie jest dostępna w innej części tej samej strony. 

Rozwiązanie: W języku VBScript zmienne deklarowane wewnątrz instrukcji blokowych (czyli 
dowolnych instrukcji kończących się słowami kluczowymi 

End

Next

 bądź 

Loop

) były widoczne 

poza blokiem, w którym zostały zadeklarowane. Na przykład, wykonanie poniŜszego fragmentu 
kodu spowoduj wyświetlenie w przeglądarce liczby 11: 

dim I as integer 
For I = 1 To 10 
Dim N as Double 
N = N + I 
Next 
Response.Write(N) 
 

background image

W języku VB.NET zmienna 

N

 będzie widoczna wyłącznie w bloku, w jakim została 

zadeklarowana — poza nim nie będzie dostępna (co oznacza Ŝe będzie niedostępna poza pętlą 

For

). Właśnie z tego powodu powyŜszy fragment kodu umieszczony na stronie ASP.NET nie 

będzie poprawny. Aby rozwiązać powyŜszy problem wystarczy zadeklarować zmienną poza pętlą. 

Problem: 

Optional parameters must always specify a default value.

 (Parametry 

opcjonalne zawsze muszą określać wartość domyślną) 

Opis: Zadeklarowałeś funkcję wykorzystującą słowo kluczowe 

optional

, określające Ŝe dany 

parametr jest opcjonalny. 

Rozwiązanie: W języku VB.NET parametry opcjonalne muszą określać domyślną wartość. Na 
przykład, poniŜszy fragment kodu zapisany w języku VBScript: 

sub MySub(Optional mParametr as String) 

naleŜy zmienić na: 

sub MySub(Optional mParametr as String = "Witam!") 

Warto takŜe widzieć, Ŝe funkcja IsMissing, słuŜąc w języku VBScript do określania czy dany 
została podana wartość określonego parametru opcjonalnego, w języku VB.NET nie jest dostępna. 

Problem: 

Argument lists in all call statements must now be enclosed in 

parentheses.

 (Teraz, listy argumentów we wszystkich wywołaniach muszą być zapisywane w 

nawiasach) 

Opis: Została podjęta próba wywołania funkcji lub procedury, której argumenty wywołania nie 
zostały zapisane w nawiasach. Na przykład: 

Response.Write "Witaj 

Ś

wiecie!" 

Rozwiązanie: W języku VB.NET argumenty podawane w wywołaniach wszystkich funkcji lub 
procedur muszą być zapisywane w nawiasach, niezaleŜnie od tego czy dana funkcja zwraca 
wartość czy nie. Oznacza to, Ŝe zamiast powyŜszy fragment kodu naleŜy zmienić w następujący 
sposób: 

Response.Write("Witaj 

Ś

wiecie!") 

Problem: 

Type-declaration character & does not match declared data type 

typ.

 (Znak deklaracyjny & nie odpowiada deklarowanemu typowi danych typ

Opis: Znak & został wykorzystany do konkatenacji łańcuchów znaków. 

Rozwiązanie: W języku VBScript moŜliwe było łączenie łańcuchów przy wykorzystaniu operatora 

&

 bez umieszczania odstępów pomiędzy operatorem a nazwami zmiennych. Na przykład, 

wykonanie poniŜszego fragmentu kodu napisanego w języku VBScript spowodowałoby 
wyświetlenie w przeglądarce napis „

Witaj pi

ę

kny 

Ś

wiecie!

”: 

dim a as string = "Witaj " 
dim b as string = "pi

ę

kny " 

dim c as string = "

Ś

wiecie!" 

Response.Write(a&b&c) 
 

W ASP.NET powyŜszy fragment kodu spowoduje zgłoszenie błędu. Aby rozwiązać problem 
naleŜy zmienić ostatni wiersz powyŜszego przykładu w następujący sposób: 

Response.Write(a & b & c) 

Problemy z klasycznymi stronami ASP 

Problem: 

Syntax Error or Expected variable, constant, Enum, Type or 

procedural declaration.

 (Błąd syntaktyczny lub oczekiwana zmienna, stała, typ 

wyliczeniowy, typ lub deklaracja proceduralna) 

Opis: Deklaracja metody lub zmiennej globalnej nie jest prawidłowa. Została podjęta próba 
zadeklarowania zmiennej lub metody wewnątrz bloku generowania kodu. Na przykład: 

<% 
   dim I as Integer 
   sub Powitanie 
      ... 
   end sub 

background image

%> 
 

Rozwiązanie: W języku VB.NET wszystkie deklaracje metod i zmiennych globalnych muszą być 
umieszczane w blokach deklarowania kodu (czyli pomiędzy znacznikami 

<script>

). Co więcej, 

wszystkie instrukcje, które nie są przypisaniami, muszą być umieszczane wewnątrz metod, takich 
jak 

Page_Load

Problem: Obiekt 

Request

 nie zwraca oczekiwanych danych. 

Opis: Została podjęta próba uŜycia obiektu Request do zwrócenia danych z Ŝądania HTTP; na 
przykład 

Request.Form

 lub 

Request.QueryString

Rozwiązanie: W klasycznej technologii ASP, obiekt Request zwracał łańcuch znaków zawierający 
całą kolekcję zmiennych. Na przykład, zakładając, Ŝe klasyczna strona ASP została wywołana 
przy uŜyciu adresu URL: 

http://localhost/test/Test.asp?val=45&val=453

, to poniŜsze wywołanie: 

Response.Write(Request.Querystring(val)) 
 

spowodowałoby wyświetlenie w przeglądarce jednego łańcucha znaków 

45, 453

. W ASP.NET 

obiekt Request zwraca tablicę łańcuchów znaków a nie jeden połączony łańcuch. Na przykład, 
gdyby przy uŜyciu powyŜszego adresu URL została wywołana strona ASP.NET, to wywołanie 

Response.Write(Request.Querystring(val)(0)) 
 

spowodowałoby wyświetlenie liczy 

45

, natomiast wywołanie  

Response.Write(Request.Querystring(val)(1)) 
 

spowodowałoby wyświetlenie liczby 

453

. W powyŜszy sposób działa obiekt 

Request

, oraz 

właściwości 

Request.Querystring

 oraz 

Request.Form