Miłosz Orzeł

.net, js, html, arduino, java... no rants or clickbaits.

Treść komunikatu o błędzie podczas asynchronicznego postbacka

Gdy kontrolka znajdująca się w UpdatePanelu wykonuje asynchroniczny postback skutkujący błędem po stronie serwera, użytkownik zostaje poinformowany o problemie przez komunikat JavaScript. Treść tego komunikatu jest taka sama jak właściwość Message wyjątku. Alert ukaże się jedynie wtedy, gdy witryna nie korzysta z przekierowania w przypadku błędu lub, gdy właściwość AllowCustomErrorsRedirect kontrolki ScriptManager jest ustawiona na false.

Co jeśli chciałbyś zmienić treść wiadomości wyświetlanej użytkownikowi?
Można to zrobić na dwa sposoby. Pierwszy to ustawienie odpowiedniego tekstu w propercie AsyncPostBackErrorMessage kontrolki ScriptManager. Drugi to obsługa zdarzenia AsyncPostBackError tejże kontrolki.

Druga technika daje większe możliwości, ponieważ pozwala na dostosowanie treści komunikatu do typu wyjątku. Dobrym pomysłem jest umieszczenie ogólnej informacji o błędzie we właściwości AsyncPostBackErrorMessage i modyfikowanie jej w razie potrzeby w zdarzeniu AsyncPostBackError.

Tak wygląda deklaracja ScriptManagera wyświetlającego domyślmy komunikat błędu o treści "Mamy problem!":

<asp:ScriptManager  ID="ScriptManager1" runat="server"
 AsyncPostBackErrorMessage="Mamy problem!"
 OnAsyncPostBackError="ScriptManager1_AsyncPostBackError" />

A oto przykładowy kod modyfikujący komunikat wyświetlany w alercie, jeśli błąd powstał na skutek operacji dzielenia przez zero:

protected void ScriptManager1_AsyncPostBackError(object sender,
    AsyncPostBackErrorEventArgs e)
{
    if (e.Exception is DivideByZeroException)
    {
        ScriptManager1.AsyncPostBackErrorMessage = "Nie można dzielić przez zero!";
    }
}

Dostęp do sesji z Page Methods

ASP.NET AJAX oferuje łatwy w użyciu i efektywny mechanizm wywołań metod na serwerze z poziomu JavaScript. Mowa o Page Methods. Ponieważ są one statyczne* nie możesz w kodzie takiej metody użyć dostępu do właściwości Page.Session. Nie oznacza to jednak, że musisz zrezygnować z wykorzystania sesji. Wystarczy, że zamiast Page.Session skorzystasz z HttpContext.Current.Session.

Przykładowo by zapisać i odczytać wartość ze stanu sesji wystarczy użyć kodu:

[WebMethod]
public static void ZapiszDoSession(string s)
{
    HttpContext.Current.Session["abc"] = s;
}

[WebMethod]
public static string OdczytajZSession()
{
    return (string)HttpContext.Current.Session["abc"];
}

A co gdybyś chciał np. pobrać nazwę zalogowanego użytkownika? To równie proste, skorzystaj z HttpContext.Current.User.Identity.Name.

Dostęp do danych sesji jest możliwy, ponieważ przy wysyłaniu zapytań za pośrednictwem obiektu XmlHttpRequest, cookie z identyfikatorem sesji również jest dołączone. Takie ciastko wygląda np. tak:

Cookie: ASP.NET_SessionId=kxxrwp45bhkyyhbzpijo0zj4

* Page Methods są statyczne - i dobrze! Dzięki temu, unika się tworzenia obiektu Page oraz przesyłania ViewState. Serwer ma mniej pracy (nie zachodzą zdarzenia takie jak Page_Load czy Page_PreRender) a ilość danych przesyłanych w sieci jest znacząco mniejsza.

404 dla plików ASPX na IIS 6 (Win 2003)

Przy przenoszeniu aplikacji z maszyny testowej na środowisko produkcyjne zawsze pojawiają się jakieś problemy (zwykle drobne - jak w opisywanym przypadku). Czas leci a w myślach "WTF?"...

Do testów aplikacji służyły nam komputery z XP mające IIS 5.1. Na produkcji zainstalowano jednak Windows 2003 z IIS 6.0. Po skopiowaniu wszystkiego co potrzeba i skonfigurowaniu katalogów wirtualnych okazało się, że można uzyskać dostęp jedynie do statycznych stron np. *.html. Przy próbie otwarcia strony *.aspx serwer odpowiadał kodem 404. U nas działo a tutaj nie chce... Przyczyna okazała się bardzo prosta: domyślnie po instalacji rozszerzenie IIS ASP.NET v2.0 miało status ustawiony na "Prohibited". Aby dynamiczny content ASPX mógł być serwowany to ustawienie musi zostać zmienione na "Allowed".

Kroki potrzebne do rozwiązania problemu:

  • Uruchom konsole IIS (inetmgr.exe)
  • Po lewej stronie konsoli zaznacz interesujący Cię serwer
  • Kliknij węzeł "Web Service Extensions" (po prawej stronie okna pokaże się lista dostępnych rozszerzeń)
  • Zaznacz na liście nazwę rozszerzenia odpowiedzialnego za wersję ASP.NET, z której korzysta Twoja aplikacja
  • Naciśnij przycisk "Allow"

I to tyle! Superproste (jeśli wiesz o tym).

Disabled CheckBoxa usuwa zaznaczenie!

Podczas korzystania z kontrolki CheckBox i ustawiania jej po stronie klienta jako nieaktywnej, natchnąłem się na problem, który (przeoczony) może sporo namieszać w pracy aplikacji. Otóż jeśli CheckBox jest zaznaczony i zablokujesz go ustawiając właściwość disabled w JavaScript to po postbacku zobaczysz, że właściwość Checked == false!

Ten fragment JS ustawia właściwość disabled (CheckBox staje się szary i przestaje reagować na akcje użytkownika):

document.getElementById('<%= CheckBox1.ClientID %>').disabled = true;

Po "powrocie na serwer" kontrolka CheckBox nie będzie zaznaczona. Dzieje się tak dlatego, że przeglądarka nie wysyła w requescie informacji o polu input type="checkbox" z atrybutem disabled.

Testowałem w IE6/8 i FF2 na .NET 2.0/3.5.