Julekalender 2004 om Whidbey


18. dec 2004 00:10

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>

 



Abonnér på mit RSS feed.   Læs også de øvrige indlæg i denne Blog.