Számtalanszor előfordul, hogy egy oldal feldolgozása során a felhasználót át kell irányítanunk egy másik oldalra. Erre vannak jól bevált megoldások, a Response.Redirect, a Server.Transfer vagy a Server.Execute. Mindegyiknek megvan a maga előnye és hátránya, van azonban egy közös nagy hátrányuk, amit hajlamosak vagyunk elfelejteni.
Gyakran kell például Cancel jellegű gombot készítenünk, ami visszairányítja a felhasználót az előző oldalra, ilyenkor általában ezt a megoldást látom:
<asp:Button ID="btnGo" runat="server" OnClick="btnGo_Click" Text="Vissza a Kezdőlapra" />
protected void btnGo_Click( object sender, EventArgs e )
{
this.Response.Redirect( "Default.aspx" );
}
Azaz egy szerver oldali gomb, szerver oldali eseménykezelővel. Érdemes megfigyelni, hogy nincs benne semmi olyan, ami szerver oldali feldolgozást igényelne. Az ilyen jellegű átirányításra lehetne egyszerű HTML <a> taget használni, de amikor ezt felvetem, általában azt a választ kapom, hogy a Cancel mellett van egy OK gomb is, ami viszont igenis igényli a szerver oldali logikát és hogy nézne ki, ha az egyik link, a másik pedig gomb lenne.
A Response.Redirectnek azonban van egy közismerten rossz tulajdonsága: kliens oldali átirányítást végez, azaz visszaküld egy HTTP Error 302-t (Object moved), mire a böngésző egy másik HTTP requestben kéri le a hivatkozott oldalt. Felesleges roundtrip, ami bizonyos esetekben elfogadható, a fentiben azonban semmiképpen.
Nosza, készítsünk egy egyszerű gombot, ami kliens oldalon irányít át! Ennyi az egész, csupasz HTML, semmi szerver oldali kód nincs benne:
<input type="button" value="Vissza" onclick="window.location='Default.aspx';" />
Ja, hogy ilyen vezérlő nincs a Toolboxon? “És akkor mi van, ember?!”
Csak egy kis JavaScript kell és még barátságosabb lesz a gombunk:
<input type="button" value="Vissza" onclick="if( confirm('Biztosan?') ) window.location='Default.aspx';" />
Sőt, ha csak egy Vissza gombra van szükségünk, akkor talán a history-val is próbálkozhatunk, hátha a böngésző kivágja az oldalt a gyorsítótárból és a szerverünk nem is kap kérést:
<input type="button" value="Vissza" onclick="history.back()" />
Ez a megoldás nem csak akkor működik, ha Cancel funkcióra van szükségünk, hanem akkor is, ha master-detail jellegű oldalakat készítünk, ahol az egyik listáz minden elemet, a másik oldal pedig egy kiválasztott elem részleteit mutatja. A részletes oldalt gyakran úgy oldjuk meg, hogy a kiválasztott elem azonosítóját query stringben adjuk át, tehát a lista oldalon úgy kell átirányítanunk, hogy az azonosító bekerüljön az URL-be. Ehhez sem kell szerver oldali kód, adakötéssel ez is megoldható:
<asp:ListView runat="server" DataSourceID="sdsCustomers">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<%# Eval( "CompanyName" ) %> - <%# Eval( "ContactName" ) %>
<input type="button" value="Részletek"
onclick="<%# Eval( "CustomerID", "window.location='Customer.aspx?Id={0}';" ) %>" />
</ItemTemplate>
<ItemSeparatorTemplate>
<br />
</ItemSeparatorTemplate>
</asp:ListView>
<asp:SqlDataSource ID="sdsCustomers" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CustomerID], [CompanyName], [ContactName] FROM [Customers] ORDER BY [CompanyName]">
</asp:SqlDataSource>
Itt sem használok szerver oldali kódot, az adatkötés ugyanis runat=”server” nélkül is tud működni. Az aláhúzott kifejezésben az az érdekes, hogy az idézőjelek párosítása szemmel láthatóan rossz, mégis működik :)
Adott tehát a lehetőség: lustán és gyorsan olyan kódot írni, amely feleslegesen terheli a szervert és várakoztatja a felhasználót vagy némi kézimunkával mindenkinek a kedvére tenni.
Te melyik utat szoktad választani?