Et af de irritationsmomenter der som bruger kan være ved webapplikationer er ventetiden ved postbacks. I et af de tidligere Whidbey
tips så vi på hvorledes ASP.NET Validators kan foretage felt validering client-side. Der findes en lang række andre situationer, hvor
det som udgangspunkt kræver et postback midtvejs i udfyldelse af en formular, f.eks. når man vælger et land i en dropdown boks hvor
regioner/stater så skal fremgå i en efterfølgende dropdown boks. Løsningen på det problem hedder XMLHTTP, hvor javascript på html-siden
sender et request via XMLHTTP, får et svar retur og f.eks. udfylder regions dropdown boksen.
I ASP.NET 2.0 er der direkte support for XMLHTTP callbacks. For at udnytte dette kræver det lidt javascript på klienten samt at
aspx-siden implementerer System.Web.UI.ICallbackEventHandler - lad os set på et eksempel:
Et eksempel
Ofte bliver man bedt om at taste en adresse ind på en webside, herunder bl.a. indtastning af postnummer og by. Lad os hjælpe brugeren
lidt og spare ham/hende for at skulle taste bynavnet ind:
Denne aspx side indeholder 3 tekstfelter: txtAddress, txtPostalCode og txtCity. På txtCity er propertien ReadOnly sat til True. Når der
indtastes en værdi i txtPostalCode og feltet herefter forlades, så udfyldes txtCity på baggrund af returværdien fra et XMLHTTP Callback.
Server side
På server siden (default.aspx.vb) skal klassen implementere ICallbackEventHandler og dennes metode: RaiseCallbackEvent.
Der er kun en RaiseCallbackEvent metode pr. aspx-side, så skal siden håndterer forskellige XMLHTTP Callbacks skal vi sørge for at input strengen
(eventArgument) på en eller anden måde afspejler hvilken metode, det er vi ønsker udført på serveren.
I eksemplet herunder indikeres hvilken metode der er tale om ved at strengen starter med "PostalCode:".
I Page_Load sættes et client side event op således at der ved ændring i txtPostalCode tekstfeltet kaldes ResolveCity javascript metoden.
Ligeledes genereres en streng v.hja. GetCallbackEventReference. Denne streng skal vi bruge om et øjeblik, når vi ser på klient koden.
Partial Class Default_aspx
Implements System.Web.UI.ICallbackEventHandler
Private _callbackstr As String
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
txtPostalCode.Attributes.Add("onChange", "ResolveCity()")
_callbackstr = Page.GetCallbackEventReference(Me, "Command", "CallBackHandler", _
"context", "onError")
End Sub
Private Function RaiseCallbackevent(ByVal eventArgument As String) _
As String _
Implements ICallbackEventHandler.RaiseCallbackEvent
If eventArgument.StartsWith("PostalCode:") Then
Return PostalCodesUtil.GetCity(eventArgument.Substring("PostalCode:".Length))
Else
Return "unknown"
End If
End Function
End Class
Client side
På klient siden undgår vi ikke helt at gribe til javascript ;-), men det er dog begrænset, hvad der skal
til i dette eksempel. Funktionen ResolveCity opretter en kommando ved at aflæse indholdet af txtPostalCode og
udfører så herefter XMLHTTP Callbacket v.hja. den kode der blev genererer v.hj.a. GetCallbackEventReferencemetoden i
Form_Load. I denne funktion er det også sat op at det er CallBackHandler der kaldes, hvis XMLHTTP kaldet går godt
og OnError hvis der opstår en Exception på serveren.
Der kan også kun være en CallBackHandler metode i klienten, så har man flere forskellige XMLHTTP callbacks på samme side så
benyttes context.CommandName til at afgøre hvilken af metoderne det er der er gang i.
<%@ Page Language="VB" AutoEventWireup="false" ... %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ... >
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Callback Demo</title>
</head>
<body>
<script>
function ResolveCity()
{
var Command = "PostalCode:" +
document.forms[0].elements['txtPostalCode'].value;
var context = new Object();
context.CommandName = "ResolveCity";
<%=_callbackstr%>
}
function CallBackHandler(result, context)
{
if (context.CommandName == "ResolveCity" )
{
document.forms[0].elements['txtCity'].value = result;
}
}
}
function onError(message, context)
{
alert("Exception :\n" + message);
}
</script>
<form id="form1" runat="server">
...
</form>
</body>
</html>
|