Ahmad Masykur

Share your knowledge although one function!

About the author

Ahmad Masykur is a Software Architecture Engineer at PT. Freeport Indonesia Jakarta Indonesia.
In this blog, I share things of interest to me. Most topics are likely to be related to software development, but don't hold me to it.

Certificates



Awards


Powered by

Widget Prayer Time not found.

There is an error in XML document (4, 16278).X

Page List

Validators


Ahmad Masykur

Ajax Upload dengan Hidden IFrame

Salah satu permasalahan pada ASP.NET AJAX Update Panel adalah tidak dapat melakukan asynchronous communication pada proses upload file. Hal ini disebabkan karena pada dasarnya object XMLHttpRequest (XHR) tidak dapat mengirimkan sebuah file dengan alasan keamanan. Pada beberapa situs seperti Google Mail dan Community Server tetap dapat melakukan upload file tanpa me-refresh seluruh halaman.

Solusi Alternatif

Saah satu alternatif cara untuk melakukan upload tanpa harus me-refresh seluruh halaman adalah menggunakan IFrame yang tersembunyi (hidden IFrame). Pada halaman utama disisipkan sebuah iframe yang berisi sebuah halaman kosong dan pada form target halamannya diarahkan ke halaman kosong yang ada di dalam iframe tersebut. Dengan cara ini hanya bagian IFrame saya yang akan melakukan komunikasi dengan server tanpa mempengaruhi keseluruhan halaman.

Langkah langkah trik ini adalah sebagai berikut.

  1. Tambahkan hidden IFrame pada halaman dan set sembunyikan dengan style="display:none".


    <iframe name="hiddenFrame" src="blank.htm" mce_src="blank.htm" style="display:none"></iframe>

  2. Buat file blank.htm pada sollution.
    File ini dibutuhkan untuk memastikan bahwa IFrame masih dalam lingkup domain yang sama dengan halaman utama. Jika file blank.htm berada di luar domain (misal default blank.htm yang ada di komputer lokal) maka akan ada penolakan hak akses terhadap eksekusi script di luar domain.
  3. Tambahkan kontrol FileUpload ke dalam form

    <asp:FileUpload ID="fileUpload1" runat="server" />
  4. Buat fungsi submitForm yang berfungsi melakukan submit terhadap hidden IFrame.

    // Fungsi memiliki dua parameter yang berisi referensi element IFrame
    // dan element ID control FileUpload
    function submitForm(frameName,upload){
         // Diasumsikan bahwa halaman utama adalah default.aspx
         document.forms[0].action="default.aspx"
         // Inti dari trik ini adalah mengeset target form ke hidden IFrame
         document.forms[0].target=frameName;
         // setTimeout digunakan untuk mengupdate dokumen dengan thread yang terpisah,
         // jika tidak maka dokumen tidak akan baru terupdate setelah download selesai.
         window.setTimeout(function(){
             var uploadE=document.getElementById(upload);
             uploadE.parentElement.appendChild(document.createTextNode(uploadE.value));
             uploadE.parentElement.replaceChild(uploadE.cloneNode(true),uploadE);
         },100);
         document.forms[0].submit();
    }
  5. Buat tombol dan tambahkan attribute onclick untuk memanggil fungsi submitForm yang telah dibuat sebelumnya.

    <button onclick="javascript:submitForm('hiddenFrame','<%= fileUpload1.ClientID %>')">Upload</button>
  6. Tambahkan web kontrol label yang akan diisi dengan jam pertama kali halaman dimuat,

    <asp:Label ID="lblTime" runat="server" />
  7. Pada code behind, saat Page_Load set label dengan jam berjalan dan cek jika ada file yang diupload, simpan ke dalam server.

    protected void Page_Load(object sender, EventArgs e)
    {
         lblTime.Text = DateTime.Now.ToLongTimeString();
         if (fileUpload1.HasFile)
        {
             fileUpload1.SaveAs(Server.MapPath("App_Data/") + fileUpload1.FileName);
         }
    }
  8. Selesai

Dari langkah-langkah tersebut di atas, secara lengkap kode dapat dilihat sebagai berikut.

File default.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HiddenIFrameUpload._Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server">    <title>Untitled Page</title></head><body>    <asp:Label ID="lblTime" runat="server" />    <iframe name="hiddenFrame" src="blank.htm" style="display:none"></iframe>    <form id="form1" runat="server" enctype="multipart/form-data" >         <div id="uploadContainer">              <asp:FileUpload ID="fileUpload1" runat="server" />              <button onclick="javascript:submitForm('hiddenFrame','<%= fileUpload1.ClientID %>')">Upload</button>         </div>     </form>    <script type="text/javascript">         function submitForm(frameName,upload){             document.forms[0].action="Default.aspx"             document.forms[0].target=frameName;             window.setTimeout(function(){                  var uploadE=document.getElementById(upload);                  uploadE.parentElement.appendChild(document.createTextNode(uploadE.value));                  uploadE.parentElement.replaceChild(uploadE.cloneNode(true),uploadE);             },100);             document.forms[0].submit();    }    </script></body></html>

File default.aspx.cs


using System;
using System.Web;

namespace HiddenIFrameUpload
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblTime.Text = DateTime.Now.ToLongTimeString();
            if (fileUpload1.HasFile)
            {
                fileUpload1.SaveAs(Server.MapPath("App_Data/") + fileUpload1.FileName);
            }

        }
    }
}

HiddenIFrameUpload.zip (5.88 kb)


Permalink | Comments (14) | Post RSSRSS comment feed

Invoke Web Service Menggunakan XMLHttpRequest

Banyak library Ajax yang sudah gede dan banyak fiturnya seperti ASP.NET AJAX, Anthem.NET, AjaxAnywhere, ajaxCFC, AJS, Dojo, Rico dan beberapa library lainnya. Dalam tulisan ini akan saya jelaskan konsep invoke Web Service langsung menggunakan objek XMLHttpRequest (XHR). Saya asumsikan bahwa pembaca sudah memahami konsep dasar XMLHttpRequest, jika belum silakan baca tulisan saya sebelumnya di Pengenalan AJAX.

Pertama buat root object dengan nama Masykur, root object ini bisa disamakan sebagai namespace pada OOP.

if (!window.Masykur) {
    window.Masykur = {};
}

Setelah root object dibuat kemudian buat member yang berisi DOM dan Ajax. DOM digunakan untuk mendapatkan informasi DOM dan browser sedangkan Ajax adalah object yang menangani komunikasi singkron dengan Web Service.

if (!Masykur.DOM) {
    Masykur.DOM = function() {}
}
if (!Masykur.Ajax) {
    Masykur.Ajax = function() {}
}

Pada objek Masykur.DOM, tambahkan property untuk pengecekan browser. Pengecekan browser ini digunakan untuk mengecek kemampuan dari masing-masing browser karena masing-masing browser menggunakan objek yang berbeda untuk menangani XHR maupun dokumen XML.

Masykur.DOM.isInternetExplorer = (navigator.userAgent.indexOf("MSIE") >= 0);
Masykur.DOM.isMozilla = (navigator.userAgent.indexOf("Gecko") >= 0);
Masykur.DOM.isOpera = (navigator.userAgent.indexOf("Opera") >= 0);

Pada objek Masykur.Ajax, buat variabel nameSpace yang digunakan sebagai namespace pada Envelope SOAP. Selain variabel juga tambahkan fungsi set dan get namespace.

Masykur.Ajax = function() {
    var nameSpace = "http://tempuri.org/";
    this.setNameSpace = function(ns){
        nameSpace = ns;
    }//end setNameSpace()
    
    this.getNameSpace = function(){
        return nameSpace;
    }//end getNameSpace()
}

Buat objek XHR lintas browser dengan mencoba semua metode dari create XMLHttpRequest dari JavaScript object, ActiveX dan SOAPCall object. Ini dimaksudkan supaya semua library tidak tergantung dengan browser yang digunakan, dapat berjalan baik IE, Firefox maupun Opera.

Masykur.Ajax = function(){
    // ...
    var ajaxObject = function(){
        try{return new XMLHttpRequest();}catch(ex){};
        try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(ex){};
        try{return new SOAPCall();}catch(ex){};
    }//end ajaxObject()
}

Buat fungsi penanganan error yang kemudian dapat di-override dengan fungsi sendiri saat digunakan.

Masykur.Ajax = function(){
    // ...
    this.onError = function(error){
        alert(error);
    }//end onError()
}

Setelah semua persiapan objek XHR selesai, sekarang tinggal buat fungsi callService untuk invoke ke Web Service.

Masykur.Ajax = function(){
    // ...
    this.callService = function(serviceUrl, soapMethod, callbackFunction /*, unlimited params */){
        // code
    }
}

Pertama yang perlu disiapkan adalah URL web service. Tambahkan "?WSDL" dibelakang URL.

if(serviceUrl.indexOf("http://") < 0)
    serviceUrl = "http://" + serviceUrl;
serviceUrl += "?WSDL";

Hal penting yang harus disiapkan adalah envelope untuk membungkus data yang akan dikirimkan ke server. Envelope berisi semua parameter yang dibutuhkan oleh web service method. Parameter dibungkus dalam tag <soap:Body>, nama parameter merupakan sebuah elemen child <soap:Body> dan valuenya dimasukkan sebagai text element parameter.

var soapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
soapEnvelope += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
soapEnvelope += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
soapEnvelope += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
soapEnvelope += "<soap:Body>";
soapEnvelope += "<" + soapMethod + " xmlns=\"" + nameSpace + "\">";

if(arguments.length > 3){
    for (var i = 3; i < arguments.length; i++)
    {
        var params = [];
        var arg = arguments[i];
        var ieq = arg.indexOf('=');
        params[0] = arg.substr(0, ieq);
        params[1] = arg.substr(ieq + 1);
        soapEnvelope += "<" + params[0] + ">";
        soapEnvelope += params[1];
        soapEnvelope += "</" + params[0] + ">";
    }//end for
}//end if

soapEnvelope += "</" + soapMethod + ">";
soapEnvelope += "</soap:Body>";
soapEnvelope += "</soap:Envelope>";

Set event onreadystate pada objek XHR dan kembalikan hasil respon web service dalam format string setelah semua data lengkap diterima.

Terakhir buka sambungan dengan server menggunakan mode POST dan set header content-type menjadi "text/xml" dan tambahkan juga header "soapaction" dengan data namespace diikuti dengan soap method. Kirimkan soap envelope pada request body seperti pada kode berikut.

ao.open("POST", serviceUrl, true);
ao.setRequestHeader("Content-Type", "text/xml");
ao.setRequestHeader("soapaction", nameSpace + soapMethod);
ao.send(soapEnvelope);

Script lengkap dapat dilihat pada kode berikut.

if (!window.Masykur) {
    window.Masykur = {};
}
if (!Masykur.DOM) {
    Masykur.DOM = function() {}
}
if (!Masykur.Ajax) {
    Masykur.Ajax = function() {}
}
Masykur.DOM.isInternetExplorer = (navigator.userAgent.indexOf("MSIE") >= 0);
Masykur.DOM.isMozilla = (navigator.userAgent.indexOf("Gecko") >= 0);
Masykur.DOM.isOpera = (navigator.userAgent.indexOf("Opera") >= 0);

Masykur.Ajax = function(){

    var nameSpace = "http://tempuri.org/";
    
    //private method for returning an ajax enabled
    //object specific to a browser
    var ajaxObject = function(){
        try{return new XMLHttpRequest();}catch(ex){};
        try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(ex){};
        try{return new SOAPCall();}catch(ex){};
    }//end ajaxObject()
    
    this.onError = function(error){
        alert(error);
    }//end onError()

    this.callService = function(serviceUrl, soapMethod, callbackFunction /*, unlimited params */){
        
        var callServiceError = this.onError;
        
        var ao = ajaxObject();
        
        if(!ao.encode){
            if(serviceUrl.indexOf("http://") < 0)
                serviceUrl = "http://" + serviceUrl;
            serviceUrl += "?WSDL";
            
            var soapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            soapEnvelope += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
            soapEnvelope += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
            soapEnvelope += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
            soapEnvelope += "<soap:Body>";
            soapEnvelope += "<" + soapMethod + " xmlns=\"" + nameSpace + "\">";
            
            if(arguments.length > 3){
                for (var i = 3; i < arguments.length; i++)
                {
                    var params = [];
                    var arg = arguments[i];
                    var ieq = arg.indexOf('=');
                    params[0] = arg.substr(0, ieq);
                    params[1] = arg.substr(ieq + 1);
                    soapEnvelope += "<" + params[0] + ">";
                    soapEnvelope += params[1];
                    soapEnvelope += "</" + params[0] + ">";
                }//end for
            }//end if
            
            soapEnvelope += "</" + soapMethod + ">";
            soapEnvelope += "</soap:Body>";
            soapEnvelope += "</soap:Envelope>";
            
            ao.onreadystatechange = function(){
                
                if(ao.readyState == 4){
                    
                    if(Masykur.DOM.isOpera){
                        //opera
                        var response = ao.responseXML.getElementsByTagName(soapMethod + "Result")[0];
                        if(!response)
                            response = ao.responseXML.getElementsByTagName(soapMethod + "Response")[0];
                        if(!response){
                            callServiceError("WebService does not contain a Result/Response node");
                            return;
                        }//end if
                        
                        ao.callbackFunction(ao.responseXML.getElementsByTagName(soapMethod + "Result")[0].innerHTML);
                    }
                    else if(Masykur.DOM.isInternetExplorer){
                        //IE
                        var responseXml = new ActiveXObject('Microsoft.XMLDOM');
                        responseXml.loadXML(ao.responseText);
                            
                        var responseNode = responseXml.selectSingleNode("//" + soapMethod + "Result");
                        if(!responseNode)
                            responseNode = responseXml.selectSingleNode("//" + soapMethod + "Response");
                        if(!responseNode) {
                            callServiceError("Response/Result node not found.\n\nResponse:\n" + ao.responseText);
                            return;
                        }//end if
                        var resultNode = responseNode.firstChild;
                        if (resultNode != null){
                            try{
                                callbackFunction(resultNode.xml);
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }
                        else{
                            try{
                                callbackFunction();
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }//end if
                    }
                    else if(Masykur.DOM.isMozilla){
                        //Mozilla
                        var xmlDocument = new DOMParser().parseFromString(ao.responseText, "text/xml");
                        
                        var xr = xmlDocument.evaluate("//" + soapMethod + "Result", 
                                 xmlDocument.childNodes[xmlDocument.childNodes.length-1], 
                                 null, 
                                 XPathResult.ANY_TYPE, null);
                        var responseNode = xr.iterateNext();
                        
                        if(!responseNode)
                            callServiceError("Response/Result node not found.\n\nResponse:\n" + ao.responseText);
                        
                        var resultNode = responseNode.firstChild;
                        
                        if (resultNode != null){
                            try{
                                callbackFunction(resultNode.textContent);
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }
                        else{
                            try{
                                callbackFunction();
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }//end if
                    }//end if
                }//end if
            };
            
            ao.open("POST", serviceUrl, true);            
            ao.setRequestHeader("Content-Type", "text/xml");
            ao.setRequestHeader("soapaction", nameSpace + soapMethod);
            try{
                ao.send(soapEnvelope);
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
        }
        else{
            var soapParams = new Array();
            var headers = new Array();
            var soapVersion = 0;
            var object = nameSpace;
            
            if(serviceUrl.indexOf("http://") < 0)
                serviceUrl = document.location + serviceUrl;
            
            ao.transportURI = serviceUrl;
            ao.actionURI = nameSpace + soapMethod;
            
            for(var i=3; i<arguments.length; i++){
                var params = arguments[i].split("=");
                soapParams.push( new SOAPParameter(params[1],params[0]) );
            }//end for
            
            try{
                ao.encode(soapVersion, soapMethod, object, headers.length, headers, soapParams.length, soapParams);
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
        
            try{
                netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
            } 
            catch(ex){
                return false;
            }//end tc
            
            try{
                ao.asyncInvoke(
                    function(resp,call,status){

                    if(resp.fault)
                        return callServiceError(resp.fault);
                    if(!resp.body){
                        callServiceError("Service " + call.transportURI + " not found.");
                    }
                    else{
                        try{
                            callbackFunction(resp.body.firstChild.firstChild.firstChild.data);
                        }
                        catch(ex){
                            callServiceError(ex);
                        }//end tc
                    }//end if
                }
                );
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
                        
        }//end if
        
    }//end callService()
    
    this.setNameSpace = function(ns){
        nameSpace = ns;
    }//end setNameSpace()
    
    this.getNameSpace = function(){
        return ns;
    }//end getNameSpace()
    
}//end Masykur.Ajax()

Categories: AJAX | JavaScript
Permalink | Comments (17) | Post RSSRSS comment feed

ASP.NET AJAX: UpdatePanel

UpdatePanel adalah salah satu control ASP.NET AJAX untuk melakukan partial rendering pada sebuah halaman. UpdatePanel bekerja bersama-sama dengan ScriptManager untuk membuat halaman web dengan rasa AJAX.

Partial Rendering

Partial-rendering adalah cara untuk memperbarui sebagian tampilan halaman, bukan keseluruhan halaman. Dibandingkan dengan melakukan postback dan reload keseluruhan halaman, partial-rendering memberikan banyak manfaat baik dari sisi kecepatan maupun efisiensi, karena hanya sebagian halaman saja yang diproses dan bukan keseluruhan halaman. Bagian halaman yang statis seperti logo dan beberapa teks statis lainnya tidak ikut diproses lagi.

Beberapa manfaat dari partial rendering adalah efisiensi sumberdaya (resources) baik di server maupun client dan efisiensi bandwidth yang digunakan. Di sisi server, server hanya akan memproses bagian halaman yang akan dirender, bukan keseluruhan halaman sebagaimana halaman ASP.NET konvensional. Di sisi client, browser juga hanya akan memproses sebagian dari halaman sehingga akan tampak lebih cepat dibandingkan reload keseluruhan halaman. Dari sisi bandwidth yang digunakan jelas lebih efisien karena data yang dilewatkan hanya sebagian dari halaman, sehingga menghemat bandwidth dengan tidak megirimkan data yang sama tiap kali postback.

Control UpdatePanel

UpdatePanel adalah sebuah control server yang untuk melakukan partial-rendering. Bersama dengan ScriptManager control server dan class PageRequestManager di client, UpdatePanel akan melakukan update pada daerah tertentu di halaman secara asinkron. Dengan menggunakan UpdatePanel, hanya element yang berada di dalam UpdatePanel yang akan diproses.

Gambar di bawah ini mengilustrasikan halaman yang dimuat pertama kali dan melakukan postback secara asinkron untuk mengupdate isi dari control UpdatePanel.

Untuk melakukan partial-rendering sangatlah mudah, tempatkan semua control yang akan dibuat partial-rendering ke dalam UpdatePanel Control. Jangan lupa, tempatkan satu  control ScriptManager pada halaman, UpdatePanel membutuhkan control ini untuk melakukan postback secara asinkron.

<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToLongTimeString();
}
</script>
<form id="form2" runat="server">
<div>
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:Label ID="Label2" runat="server" Text="Waktu server "></asp:Label><br />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><br />
            <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
        </ContentTemplate>
    </asp:UpdatePanel>
 </div>
</form>

Pada contoh di atas, semua control yang berada di dalam UpdatePanel bersifat partial-rendering. Semua postback dari control di dalam UpdatePanel dilakukan secara asinkron. Pada waktu Button1 di-click, dia akan memanggil method Button1_Click dan mengeset Label1.Text menjadi waktu server. Proses postback dilakukan secara asinkron, hanya control yang berada di dalam UpdatePanel yang berpengaruh.

Men-Trigger UpdatePanel dari Control di Luar UpdatePanel

Selain control yang berada di dalam UpdatePanel, UpdatePanel juga bisa di-trigger dari luar. Untuk melakukan hal ini, tambahkan element <asp:AsyncPostBackTrigger> yang ditempatkan di dalam element <Trigger> pada UpdatePanel. Set control ID dengan nama control yang akan mentrigger UpdatePanel tersebut. Element <Trigger> dapat berisi lebih dari satu element <asp:AsyncPostBackTrigger>

<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToLongTimeString();
}
</script>
<form id="form2" runat="server">
<div>
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:Label ID="Label2" runat="server" Text="Waktu server"></asp:Label><br />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><br />
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="Button1" />
        </Triggers>
    </asp:UpdatePanel>
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
 </div>
</form>

Menampilkan Status Update dengan UpdateProgress

UpdateProgress digunakan untuk menampilkan informasi status dari UpdatePanel. Layout control UpdateProgress dapat diatur untuk mendapatkan tampilan yang menarik di dalam element <ProgressTemplate>. Kita dapat menempatkan element apapun (HTML element maupun control server ASP.NET) di dalam <ProgressTemplate>.

Untuk menerapkan UpdateProgress, cukup menempelkan control UpdateProgress pada halaman.

<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(2000);
    Label1.Text = DateTime.Now.ToLongTimeString();
}
</script>
<form id="form2" runat="server">
<div>
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:Label ID="Label2" runat="server" Text="Waktu server"></asp:Label><br />
    <asp:UpdateProgress ID="UpdateProgress1" runat="server">
    <ProgressTemplate>
      An update is in progress...
    </ProgressTemplate>
    </asp:UpdateProgress>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><br />
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="Button1" />
        </Triggers>
    </asp:UpdatePanel>
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
 </div>
</form>

Pada contoh di atas, terdapat baris System.Threading.Thread.Sleep(2000) di method Button1_Click. Baris ini digunakan untuk simulasi bahwa proses update sedang berjalan dengan menghentikan sementara proses selama 2 detik. Jika baris ini dihilangkan, pesan pada UpdateProgress akan ditampilkan dalam waktu yang sangat singkat sehingga tidak dapat terlihat. Pada project nyata, baris ini sebaiknya tidak digunakan.

Control UpdateProgress juga bisa diset property AssociatedUpdatePanelID untuk menentukan UpdatePanel mana yang akan men-trigger UpdateProgress ini. Jika property ini tidak di-set, maka tiap posback asinkron akan men-trigger UpdateProgress ini.

Dengan menggunakan UpdatePanel dan UpdateProgress, kita tidak perlu mendalami JavaScript untuk membuat aplikasi AJAX. Hanya dengan menempatkan UpdatePanel, aplikasi kita sudah bisa memanfaatkan kemampuan AJAX yang ringan, cepat serasa aplikasi desktop.


Categories: AJAX | ASP.NET AJAX
Permalink | Comments (31) | Post RSSRSS comment feed

Berkenalan dengan ASP.NET AJAX

ASP.NET AJAX (dulu disebut sebagai Atlas CTP) merupakan salah satu framework AJAX untuk ASP.NET 2.0. Dengan menggunakan ASP.NET AJAX, kita dapat membuat aplikasi web lebih responsif dan interaktif. Untuk membuat aplikasi web AJAX-enabled menggunakan ASP.NET AJAX sangatlah mudah. Programmer web dengan kemampuan Javascript terbatas pun bisa membuat aplikasi web yang resonsif dan interaktif menggunakan ASP.NET AJAX. ASP.NET AJAX dapat di-download di http://ajax.asp.net.

Beberapa keunggulan aplikasi web menggunakan ASP.NET AJAX dibandingkan dengan aplikasi web yang secara penuh berbasis server antara lain.

  • Lebih efisien karena sebagian proses dilakukan di browser.
  • Elemen UI yang lebih familiar seperti indikator proses, tooltips dan jendela pop-up.
  • Update sebagaian halaman yang hanya mengganti sebagian dari halaman web (partial rendering).
  • Integrasi client dengan ASP.NET application services untuk form authentikasi dan user profiles.
  • Framework yang mudah disesuaikan dengan kebutuhan sebagaimana server-control.
  • Mendukung sebagian besar browser terkenal termasuk Microsoft Internet Explorer, Mozilla Firefox dan Apple Safari.

Arsitektur ASP.NET AJAX

ASP.NET AJAX merupakan framework yang terdiri dari pustaka script client dan komponen server yang terintegrasi. ASP.NET AJAX juga didukung dengan ASP.NET AJAX Control Toolkit dan beberapa fitur tambahan lainnya.

Ilistrasi berikut menggambarkan fungsionalitas yang ada pada pustaka client script dan komponen server ASP.NET AJAX.

Arsitektur server dan client ASP.NET AJAX

Arsitektur Server ASP.NET AJAX

Komponen server ASP.NET AJAX terdiri dari kontrol-kontrol web server ASP.NET dan komponen-komponen untuk mengatur UI dan alur aplikasi, juga mengatur serialization, validasi, pengembangan control server, dan lain sebagainya.

Control-control Server ASP.NET AJAX

Control-control server ASP.NET AJAX terdiri dari kode server dan client yang terintegrasi untuk membangun cita rasa AJAX. Berikut adalah daftar dari kontrol-kontrol server yang sering digunakan.

  1. ScriptManager
    Mengatur sumberdaya script komponen-komponen client, merender bagian dari halaman, localization, globalization, dan custom user script. Script manager dibutuhkan oleh UpdatePanel, UpdateProgress dan kontrol Timer.
  2. UpdatePanel
    Digunakan untuk membuat rendering sebagian halaman (partial rendering), bukan keseluruhan halaman.
  3. UpdateProgress
    Memberikan informasi mengenai status bagian halaman yang ter-update dalam kontrol UpdatePanel.
  4. Timer
    Melakukan postback ke server berdasarkan interval waktu yang telah ditentukan. Kontrol Timer dapat digunakan untuk melakukan postback keseluruhan halaman atau sebagaian halaman yang ada dalam UpdatePanel.

Web Services ASP.NET AJAX

ASP.NET AJAX menyediakan web services yang dapat digunakan oleh script client dan dapat bekerja bersama dengan application services ASP.NET. Dengan menggunakan ASP.NET AJAX, pemanggilan web service menggunakan script client dapat dilakukan dengan mudah karena telah disediakan komponen network di dalamnya.

Kemampuan Control Server ASP.NET AJAX untuk Dikembangkan

Control-control ASP.NET AJAX baru dapat dibuat sesuai dengan kebutuhan. Dengan kemampuan ini, server kontrol ASP.NET AJAX dapat terus berkembang sesuai dengan kebutuhan. Beberapa control ASP.NET AJAX yang telah siap pakai dapat ditemukan di Microsoft ASP.NET AJAX Control Toolkit.

Arsitektur Client ASP.NET AJAX

Pustaka script client ASP.NET AJAX  terdapat pada beberapa file (.js). Beberapa layer yang ada di pustaka ASP.NET AJAX antara lain:

  • Layer browser compatibility. Layer ini menyediakan kompatibilitas sebagian besar browser populer (termasuk Microsoft Internet Exploere, Mozilla Firefox, dan Apple Safari).
  • Service inti ASP.NET AJAX, yang mengandung komponen-komponen inti seperti clases, namespaces, event handling, inheritance, tipe data, dan serialisasi object.
  • Pustaka class ASP.NET AJAX, berisi komponen-komponen seperti string builder dan penanganan error tingkat lanjut.
  • Layer network yang menangani komunikasi antara service client web dengan aplikasi dan mengatur pemanggilan method secara asinkron.
  • Dukungan pustaka JavaScript yang terkandung dalam assembly atau berada dalam file (.js). Penyatuan script JavaScript ke dalam assembly dapat mempermudah pemasangan aplikasi (deployment) dan memecahkan masalah versioning.
  • Dukungan atas pengaksesan server-based forms authentication dan informasi profile dalam script client. Dukungan ini juga terdapat pada aplikasi web yang tidak dibuat dengan ASP.NET selama aplikasi tersebut menggunakan pustaka ASP.NET AJAX.
  • Dukungan atas mode release dan debug serta mendukung localization yang tertanam dalam assembly maupun terpisah dalam file JavaScript.

Debuging

Arsitektur ASP.NET AJAX menyediakan model untuk mode release dan debug. Pada mode release, pemeriksaan error dan penanganan exception telah dioptimasi untuk performance dengan script yang minimum. Pada mode debug, menyediakan lebih banyak fitur seperti pengecekan type dan argument.

Dalam class debug helper (Sys.Debug) tersedia method-method untuk menampilkan object-object ke dalam form yang mudah dibaca pada bagian bawah halaman web. Helper ini juga menampilkan pesan trace untuk melakukan assertions dan break ke debugger.

Localization dan Globalization

Pada arsitektur ASP.NET AJAX server dan client tersedia mekanisme model localization dan globalization pada script client. Dengan fitur ini, kita dapat merancang aplikasi dengan berbagai macam locale UI (bahasa dan kultur) menggunakan satu basis kode. Sebagai contoh, untuk menampilkan tanggal atau angka, ASP.NET AJAX akan memformat tampilan sesuai dengan seting culture pada browser pengguna tanpa harus melakukan postback ke server.

ASP.NET AJAX Control Toolkit

ASP.NET AJAX Control Toolkit adalah kumpulan contoh-contoh komponen kontrol yang memanfaatkan kemampuan ASP.NET AJAX. Kontrol-kontrol ini dapat di-download di situs ASP.NET AJAX.


Categories: AJAX | ASP.NET AJAX
Permalink | Comments (22) | Post RSSRSS comment feed

Parsing Data JSON

Sebagaimana telah disebutkan pada tulisan saya sebelumnya bahwa JSON memiliki kelemahan jika data yang diterima tidak diperiksa terlebih dahulu. Jika masukan data bisa dijamin bahwa tidak akan ada script yang berbahaya, issue ini bisa diabaikan. Namun jika data berasal dari situs luar seperti halnya layanan berita (RSS) atau informasi lain dari luar, risiko adanya script jahat pada data JSON cukup besar. Oleh karena itu sebelum data JSON dipanggil menggunakan fungsi eval(), terlebih dahulu data yang diterima harus diperiksa.

Pada tulisan ini, saya menggunakan library glm-ajax sebagai framework untuk mempermudah penggunaan AJAX dan json.js untuk melakukan parsing data JSON.

Penerimaan Data JSON melalui AJAX.

Sebagai contoh sedarhana, bila sebuah data json mengandung string berikut:

processData( { "color" : "green" } )

Kemudian buat halaman HTML yang berisi script untuk memanggill data JSON di atas.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Retrieving JSON Data via AJAX</title>
    <script type="text/javascript" language="javascript" src="glm-ajax.js" >
    </script>
    <script type="text/javascript" language="javascript">
        function processData(JSONData) {
            alert(JSONData.color);
        }
        function ajaxCallback(content) {
            eval(content); //eval the contents of data.
        }
        var ajax = new GLM.AJAX();
        //call json-func-data.txt and pass the contents to ajaxCallback.
        ajax.callPage("json-func-data.txt", ajaxCallback); 
    </script>
</head>
<body>
</body>
</html>

Pada contoh di atas, data JSON merupakan sebuah kode javascript. Ketika dilewatkan pada pernyataan eval() maka processData akan dieksekusi. Hal ini karena data JSON berupa kode javascript untuk memanggil fungsi processData.

Contoh berikutnya digunakan method parse. Untuk menggunakan method ini, sertakan library json.js ke dalam halaman.

Data JSON sebagai berikut.

{ "color" : "green" }

Pada HTML, sertakan library json.js dan ubah fungsi ajax Callback untuk melakukan parsing data JSON terlebih dahulu sebalum mengeksekusi fungsi processData(JSONData).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Retrieving JSON Data via AJAX</title>
    <script type="text/javascript" language="javascript" src="json.js" ></script>
    <script type="text/javascript" language="javascript" src="glm-ajax.js" ></script>
    <script type="text/javascript" language="javascript">
        function processData(JSONData) {
            alert(JSONData.color);
        }
        function ajaxCallback(content) {
            JSONData = content.parseJSON();
            processData(JSONData); 
        }
        var ajax = new GLM.AJAX();
        //call json-func-data.txt and pass the contents to ajaxCallback.
        ajax.callPage("json-func-data.txt", ajaxCallback); 
    </script>
</head>
<body>
</body>
</html>

Kode di atas, server akan mengembalikan file JSON dan akan diparsing terlebih dahulu menggunakan baris JSONData = content.parseJSON(); dan kemudian JSONData dilewatkan pada fungsi processData. Dari kedua contoh di atas, masing-masing akan menghasilkan keluaran yang sama. Namun pada beberapa kasus jika data JSON mengandung kode jahat atau data yang salah, contoh kedua lebih aman untuk menangani masalah ini.

Pengiriman Data JSON ke Server

Komunikasi pada AJAX menggunakan string yang telah disandikan (encoded). Data Javascript harus disandikan terlebih dahulu sebelum dikirim menggunakan XMLHttpRequest. Untuk merubah semua data Javascript ke dalam format JSON dapat digunakan library json.js yang dibuat oleh Douglas Crockford.

Contoh berikut menggunakan method toJSONString() untuk melakukan konversi object ke dalam string yang siap dikirimkan ke server.

var employees = { "accounting" : [  // accounting is an array in employees
                                   { "firstName" : "Ahmad",
                                     "lastName"  : "Masykur",
                                     "age"       : 25 },
                                   { "firstName" : "Agung",
                                     "lastName"  : "Riyadi",
                                     "age"       : 29 }
                                 ], // End "accounting" array
                  "sales" :      [  // Sales is another array in employees
                                   { "firstName" : "Vianton",
                                     "lastName"  : "Rahmat",
                                     "age"       : 23 },
                                   { "firstName" : "Kusuma",
                                     "lastName"  : "Dewi",
                                     "age"       : 25 }
                                 ]  // End "sales" array
                }
var toServer = employees.toJSONString();
document.writeln(toServer);

Dengan melakukan parsing data terlebih dahulu, data yang dipertukarkan antara client dan server akan lebih terjamin keamanannya. Saat ini belum ada method internal Javascript untuk membuat data JSON. Method untuk menangani JSON ini rencana akan diimplementasikan pada tahun 2007. Sebelum method tersebut belum masuk menjadi method internal javascript, kita dapat menggunakan library javascript untuk melakukan parsing dan konversi object javascript ke dalam string JSON. Untuk membuat data dengan format JSON dan melakukan parsing data sebelum diproses dapat digunakan library buatan Douglas Crockford yang dapat didownload di http://www.json.org/json.js.


Categories: Security | AJAX | JSON
Permalink | Comments (13) | Post RSSRSS comment feed

Penerimaan Data JSON melalui AJAX

Dari dua tulisan terdahulu tentang Pengantar AJAX dan JSON, kita akan padukan keduanya. Di sini saya coba untuk menjelaskan implementasi keduanya menggunakan native JavaScript supaya cara kerja keduanya bisa dipahami dengan jalas.

Pertama, buat dokumen JSON yang disimpan ke dalam file dengan nama json-data.txt.

1 { "accounting" : [ // accounting is an array in employees 2 { "firstName" : "Ahmad", 3 "lastName" : "Masykur", 4 "age" : 25 }, 5 { "firstName" : "Agung", 6 "lastName" : "Riyadi", 7 "age" : 29 } 8 ], // End "accounting" array 9 "sales" : [ // Sales is another array in employees 10 { "firstName" : "Vianton", 11 "lastName" : "Rahmat", 12 "age" : 23 }, 13 { "firstName" : "Kusuma", 14 "lastName" : "Dewi", 15 "age" : 25 } 16 ] // End "sales" array 17 } // End JSON data

File data JSON tersebut yang nantinya akan dipanggil menggunakan XMLHttpRequest. Sama seperti tulisan sebelumnya, data tersebut mengandung dua buah entity yaitu accounting dan sales. Masing-masing entity memiliki data berupa array yang isinya adalah data firstName, lastName dan age.

Selanjutnya buat object XMLHttpRequest (XHR) untuk mengambil data JSON dari server. Simpan kode berikut ke dalam file get-json.js.

1 var http_request = false; 2 var _ctrl = {}; 3 function makeRequest(url, ctrl) { 4 _ctrl = ctrl; 5 http_request = false ; 6 if (window.XMLHttpRequest) { // Mozilla, Safari ,... 7 http_request = new XMLHttpRequest(); 8 if (http_request.overrideMimeType) { 9 http_request.overrideMimeType('text/xml'); 10 // See note below about this line 11 } 12 } else if (window.ActiveXObject) { // IE 13 var aVersions = [ "MSXML2.XMLHttp.6.0", 14 "MSXML2.XMLHttp.5.0", 15 "MSXML2.XMLHttp.4.0", 16 "MSXML2.XMLHttp.3.0", 17 "Microsoft.XMLHTTP" ]; 18 for (var i = 0; i < aVersions.length; i++) { 19 try { http_request = new ActiveXObject(aVersions[i]); 20 break; 21 } 22 catch (e) 23 { 24 // Do nothing 25 } 26 } 27 } 28 if (!http_request) { 29 alert ('Giving up :( Cannot create an XMLHTTP instance'); 30 return false; 31 } 32 http_request.onreadystatechange = renderData; 33 http_request.open('GET', url, true); 34 http_request.send(null); 35 } 36 function renderData() { 37 if (http_request.readyState == 4) { 38 if (http_request.status == 200) { 39 eval("var employees = " + http_request.responseText); 40 _ctrl.innerHTML = ''; 41 for (i=0; i < employees.accounting.length; i++) { 42 _ctrl.innerHTML += '<br /><strong>Accounting #' + 43 (i+1) + '</strong>' + 44 '<br />First Name : ' + 45 employees.accounting[i].firstName + 46 '<br />Last Name : ' + 47 employees.accounting[i].lastName + 48 '<br />Age : ' + 49 employees.accounting[i].age; 50 } 51 for (i=0; i < employees.sales.length; i++) { 52 _ctrl.innerHTML += '<br /><strong>Sales #' + 53 (i+1) + '</strong>' + 54 '<br />First Name : ' + 55 employees.sales[i].firstName + 56 '<br />Last Name : ' + 57 employees.sales[i].lastName + 58 '<br />Age : ' + 59 employees.sales[i].age; 60 } 61 } else { 62 alert('There was a problem with the request.'); 63 } 64 } 65 }

Kode di atas, terdapat dua buah fungsi makeRequest dan renderData. Fungsi makeRequest digunakan untuk membuat object XHR dan melakukan request secara asynchron. Fungsi renderData adalah fungsi callback yang dipanggil setelah ada respon dari server. Fungsi ini digunakan untuk membuat tag HTML berdasarkan data JSON yang diperoleh dan menampilkan hasilnya di halaman.

Terakhir buat kode HTML untuk menampilkan hasil pengambilan data JSON.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Receiving JSON via AJAX</title> <script type="text/javascript" language="javascript" src="get-json.js" ></script> </head> <body> <input type="button" value="Click me" onclick="makeRequest('json-data.txt', document.getElementById('data'))" /> <br /> <span id="data"></span> </body> </html>

Halaman tersebut hanya akan menampilkan satu tombol [Click me]. Ketika tombol tesebut di-klik, fungsi makeRequest akan dipanggil dan melakukan request data 'json-data.txt' dari server. Data yang diambil kemudian dirender pada tag <span>.

JSON merupakan format data yang sederhana namun tangguh. Berdasarkan contoh kode di atas, kita dapat melihat bahwa untuk menampilkan data JSON ke dalam halam hanya dibutuhkan beberapa baris kode saja.

Kode di atas merupakan kode yang sangat sederhana yang masih memiliki lobang keamanan dan sangat rentan terhadap cross-site-scripting. Jika data JSON mengandung script jahat, kode tersebut juga akan dieksekusi, karena sifat JSON dapat berisi semua object Javascript termasuk function. Untuk mengatasi masalah ini diperlukan parser untuk mem-parsing semua object yang diterima melalui AJAX. Pembahasan mengenai parsing data JSON Insya Allah akan saya bahas pada tilisan saya berikutnya.  Semoga tulisan ini dapat bermanfaat untuk memulai belajar AJAX dengan format data JSON.


Categories: AJAX | JSON
Permalink | Comments (3) | Post RSSRSS comment feed

Pengantar AJAX

Pendahuluan

Banyak pertanyaan di milis dotnet@netindonesia.net mengenai apa itu AJAX. Tulisan ini adalah penyempurnaan tulisan saya di http://semarang.netindonesia.net/blogs/cahnom/. Dalam tulisan kali ini saya akan menjelaskan tentang dasar-dasar AJAX menggunakan native Javascript. Pada tulisan berikutnya Insya Allah akan saya bahas mengenai pemprograman AJAX menggunakan beberapa Framework yang sudah ada untuk mempercepat pembuatan program (RAD).

Sebelum membahas lebih jauh tentang AJAX. Apa sih sebenarnya AJAX? AJAX bukanlah barang baru dan bukan teknologi baru. AJAX merupakan paduan dari beberapa teknologi yang sudah dikenal sebalumnya yaitu HTML, DOM, XML, Javascript dan teknologi pendukung lainnya. AJAX adalah akronim dari Asynchronous JavaScript and XML,  komponen-komponen AJAX meliputi:

  • HTML (HyperText Markup Language) digunakan dalam membuat halaman web dan dokumen-dokumen lain yang dapat ditampilkan dalam browser. HTML merupakan standar internasional dengan spesifikasi yang ditetapkan oleh World Wide Web Consortium (W3C). Versi terakhir saat tulisan ini dibuat adalah HTML 4.01.
  • XHTML (Extensible HyperText Markup Language), adalah bahasa markup sebagaimana HTML, tetapi dengan gaya bahasa lebih baik. Versi terakhir saat tulisan ini dibuat adalah XHTML 2.0.
  • CSS (Cascading Style Sheets ) adalah sebuah mekanisme sederhana untuk memberikan style (seperti font, warna, jarak spasi, dll) kepada dokumen web yang ditulis dalam HTML atau XML (termasuk beberapa variasi bahasa XML seperti XHTML dan SVG).
  • JavaScript adalah bahasa scripting kecil, ringan, berorientasi-objek dan lintas platform. JavaScript tidak dapat berjalan dengan baik sebagai bahasa mandiri, melainkan dirancang untuk ditanamkan pada produk dan aplikasi lain seperti peramban web.
  • DOM (Document Object Model) adalah sebuah API (Application Program Interface) untuk dokumen HTML dan XML. DOM menyediakan representasi dokumen secara terstruktur, dimungkinkan untuk  merubah isi dan presentasi visual. Pada dasarnya, DOM menghubungkan halaman web dengan script atau bahasa pemprograman.
  • XML (Extensible Markup Language) adalah bahasa markup untuk keperluan umum yang disarankan oleh W3C untuk membuat dokumen markup keperluan khusus. Keperluan utama XML adalah untuk pertukaran data antar sistem yang beraneka ragam.
  • XSLT (Extensible Stylesheet Language Transformations ) adalah sebuah bahasa berbasis-XML untuk transformasi dokumen XML. Walaupun proses merujuk pada transformasi, dokumen asli tidak berubah melainkan dokumen XML baru dibuat dengan basis isi dokumen yang sudah ada. XSLT biasanya digunakan untuk merubah skema XML ke halaman web atau dokumen PDF.
  • Objek XMLHttpRequest untuk melakukan pertukaran data secara asinkron dengan peladen (server) web. Beberapa kerangka-kerja Ahax dan dalam beberapa situasi, objek IFrame digunakan selain objek XMLHttpRequest untuk melakukan pertukaran data dengan peladen web.
  • JSON (JavaScript Object Notation) yaitu format pertukaran data komputer yang ringan dan mudah. Keuntungan JSON dibandingkan dengan XML adalah pada proses penterjemahan data menggunakan Javascript. Javascript dapat menterjemahkan JSON menggunakan built-in procedure eval().

Dalam penerapannya, tidak semua teknologi di atas digunakan. Terdapat beberapa teknik komunikasi yang digunakan untuk implementasi AJAX. Teknik yang umum digunakan adalah dengan menggunakan:

  • Hidden Frame
    Metode ini memanfaatkan frame yang tersembunyi. Biasanya salah satu frame diset dengan ukuran tinggi/lebar 0 sehingga tidak terlihat di halaman. Frame tersembunyi inilah yang sebenarnya melakukan request ke dan menerima respon dari server, sehingga frame yang tampil kelihatan tidak melakukan postback ke server. Javascript digunakan untuk mengambil data dan mengisi data yang ada di frame tersembunyi ini.
  • Hidden IFrame
    Metode ini hampir sama dengan hidden frame, perbedaannya hanya pada elemen yang digunakan yaitu IFrame, bukan Frame.
  • Objek XMLHttpRequest
    Metode yang satu ini memanfaatkan ActiveX Objek (IE) atau objek javascript XMLHttpRequest (Mozilla/Firefox, Safari, Opera). Objek ini yang akan melakukan postback ke server dan menerima respon balik berupa data (bukan halaman). Data yang didapat dari server kemudian diolah di klien untuk ditampilkan ke halaman.

Teknik pemprosesan halaman secara umum ada dua:

  • Pemprosesan halam dengan pembuatan/manipulasi objek dokumen menggunakan javascript.
    Klien mengirimkan data dalam format XML/JSON kepada server dan mendapatkan data dari server berupa XML/JSON. Data XML/JSON kemudian diolah untuk memanipulasi objek dokumen menggunakan DOM dan javascript.
  • Parsial rendering.
    Pada teknik ini UI dan behaviour tidak diproses di klien melainkan diproses di server. Klien menerima UI dan behaviour kemudian melakukan rendering pada bagian halaman tertentu.

Perpaduan teknologi-teknologi tersebut dapat meningkatkan kinerja aplikasi web dan lebih responsif terhadap aksi pengguna. Dengan AJAX pertukaran data antara klien dan server lebih ringan karena hanya data yang dipertukarkan (bukan halaman) sehingga aplikasi web dapat berjalan lebih cepat.

Penggunaan Dasar

Dua keistimewaan Ajax adalah dapat:

  • Membuat permintaan kepada server tanpa memuat kembali (reload) halaman.
  • Mengurai (parse) dan bekerja dengan dokumen XML dan atau JSON.

1. Membuat Permintaan HTTP (HTTP Request)

Untuk membuat permintaan HTTP kepada server menggunakan JavaScript, diperlukan sebuah class yang menyediakan fungsi-fungsi ini. Pada Internet Explorer tersedia objek ActiveX yang disebut XMLHTTP. Pada Mozilla, Safari, Opera dan beberapa peramban lain, menerapkan sebuah class Javascript objek XMLHttpRequest yang mendukung method dan properties objek Microsoft ActiveX.

Untuk membuat instance (objek) class lintas-browser (cross-browser), dapat dilakukan dengan:

if (window.XMLHttpRequest) {       // Mozilla, Safari, ...
    http_request = new XMLHttpRequest ();
} else if (window.ActiveXObject) { // IE
    http_request = new ActiveXObject("Microsoft.XMLHTTP");
}

Catatan: kode di atas hanya sebagai ilustrasi saja. Kode tersebut merupakan versi paling sederhana untuk membuat instance XMLHttp. Untuk penggunaan secara nyata dapat lihat di bagian 3 artikel ini.

Beberapa versi browser Mozilla tidak bekerja dengan baik jika respon dari server tidak mengandung header mime-type XML. Untuk memenuhi kebutuhan ini, panggil method untuk mengganti/menambahkan header yang dikirim oleh server.

http_request = new XMLHttpRequest();
http_request overrideMimeType('text/xml');

Setelah itu, buat fungsi untuk mengolah setelah data diterima dari server berdasarkan permintaan yang dibuat sebelumnya. Tahap ini, daftarkan fungsi JavaScript yang menangani respon dari server. Setting properties onreadystatechange objek dengan nama fungsi Javascript yang disiapkan untuk mengerjakan proses respon.

http_request.onreadystatechange = namaFungsi;

Perlu dicatat bahwa tidak ada tanda kurung setelah nama fungsi dan tanpa parameter yang dilewatkan. Selain memberikan nama fungsi, dapat juga digunakan teknik JavaScript dalam pendefinisian fungsi (tanpa nama) saat program berjalan (run-time) -- yang disebut fungsi anonymous -- dan mendefinisikan tindakan untuk melakukan proses, seperti berikut:

http_request.onreadystatechange = function() {
    // do the thing
}; 

Selanjutnya, setelah deklarasi dan segera setelah menerima respon, kemudian buat permintaan. Panggil
method open() dan send() dari klas permintaan HTTP seperti kode berikut:

http_request.open('GET', 'http://www.example.org/somefile', true);
http_request.send(null);
  • Parameter panggil pertama dari open() adalah method permintaan HTTP GET, POST, HEAD atau method lain yang didukung oleh server. Gunakan huruf kapital sebagaimana standar HTTP. Untuk informasi lebih lanjut mengenai method permintaan HTTP dapat dilihat pada spesifikasi W3C.
  • Parameter kedua adalah URL dari halaman yang diminta. Demi keamanan, panggilan tidak dapat dilakukan pada halaman domain pihak ketiga. Pastikan untuk menggunakan nama domain yang pasti pada semua halaman jika tidak ingin mendapat error 'permision denied' ketika melakukan panggilan open().
  • Parameter ketiga diset ketika permintaan adalah asinkron. Jika diset TRUE, eksekusi fungsi JavaScript akan berlanjut walau tanggapan dari peladen belum sampai. Ini adalah A dalam AJAX.

Parameter untuk method send() dapat berupa sembarang data untuk dikirim ke server saat mengirimkan permintaan POST. Data harus dalam format query string, seperti:

name=value&anothername=othervalue&so=on

Catatan bahwa jika ingin mengirim (POST) data, ganti tipe MIME permintaan menggunakan bari berikut:

http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 

Bila tidak, server akan mengabaikan data yang dikirim.

2. Penanganan Respon Server

Ingat bahwa ketika permintaan dikirim, fungsi JavaScript harus telah disediakan untuk menangani respon.

http_request.onreadystatechange = namaFungsi;

Apa yang seharusnya dikerjakan oleh fungsi ini. Pertama, fungsi untuk memeriksa status tanggapan. Jika status memiliki nilai 4, berarti bahwa seluruh tanggapan peladen telah diterima dan siap dilanjutkan proses berikutnya.

if (http_request.readyState == 4) {
    // everything is good, the response is received
} else {
    // still not ready
}

Berikut adalah daftar nilai status readyState

  • 0 (tidak diinisialisasi)
  • 1 (dalam proses memuat)
  • 2 (telah dimuat)
  • 3 (interaktif)
  • 4 (lengkap)

Berikutnya adalah pemeriksaan kode status dari respon HTTP server. Daftar kode status respon HTTP dapat dilihat di situs W3C. Pada contoh kali ini hanya digunakan status 200 yaitu respon OK.

if (httpRequest.status == 200) {
    // perfect! 
} else {
    // there was a problem with the request,
    // for example the response may be a 404 (Not Found)
    // or 500 (Internal Server Error) response codes 
}

Setelah semua status permintaan diperiksa dan kode status HTTP telah ada respon, data respon dari server dapat diolah. Terdapat dua pilihan untuk mengakses data.

  • httpRequest.responseText -- akan mengembalikan respon berupa teks string
  • httpRequest.responseXML -- akan mengembalikan respon berupa objek XMLDocument object yang dapat diakses dengan fungsi DOM JavaScript

3. Contoh Sederhana

Tulis bagian program menjadi satu permintaan HTTP sederhana. JavaScript akan meminta sebuah dokumen HTML yaitu test.html yang hanya mengandung tulisan "I'm a test" dan kemudian memanggil alert() dengan isi dari berkas test.html

<script type="text/javascript" language="javascript">
    var http_request = false;
    function makeRequest(url) {
        http_request = false ;
        if (window.XMLHttpRequest) { // Mozilla, Safari ,...
            http_request = new XMLHttpRequest();
            if (http_request.overrideMimeType) {
                http_request.overrideMimeType('text/xml');
                // See note below about this line
            }
        } else if (window.ActiveXObject) { // IE
            var aVersions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "Microsoft.XMLHTTP" ];
            for (var i = 0; i < aVersions.length; i++) {
                try { http_request = new ActiveXObject(aVersions[i]);
                    break;
                }
                catch (e)
                {
                // Do nothing 
                } 
            }
        }
        if (!http_request) {
            alert ('Giving up :( Cannot create an XMLHTTP instance');
            return false;
        }
        http_request.onreadystatechange = alertContents;
        http_request.open('GET', url, true);
        http_request.send(null);
    }
    function alertContents() {
        if (http_request.readyState == 4) {
            if (http_request.status == 200) {
                alert(http_request.responseText);
            } else {
                alert('There was a problem with the request.');
            }
        }
    }
</script>
<span style="cursor: pointer; text-decoration: underline" onclick ="makeRequest('test.html')">Make a request
</span > 

Pada contoh di atas:

  • Ketika pengguna menekan klik pada link &quote;Make a request&quote; maka fungsi makeRequent dipanggil dengan parameter nama file HTML test.html dalam direktori yang sama.
  • Permintaan dibuat dan kemudian event onreadystatechange melakukan eksekusi alertContents()
  • alertContents() memeriksa jika tanggapan telah diterima dalam keadaan baik dan kemudian tampilkan isi berkas test.html menggunakan fungsi alert()

Contoh di atas dapat diuji dengan klik di sini dan juga berkas test dapat dilihat di sini. Catatan: baris http_request.overrideMimeType('text/xml'); di atas mengakibatkan error Console pada Firefox 1.5b seperti tercantum dalam dokumen pada https://bugzilla.mozilla.org/show_bug.cgi?id=311724 jika halaman yang dipanggil dengan XMLHttpRequestbukan XML yang valid (seperti plaintext).

4. Bekerja dengan Respon XML

Pada contoh sebelumnya, setelah tanggapan dari permintaan HTTP diterima, digunakan sifat responseText dari objek permintaan yang mengandung isi file test.html. Sekarang, coba gunakan sifat responseXML Buat dokumen XML yang valid dengan nama test.xml seperti contoh di bawah:

<?xml version ="1.0" ?>
<root>
    I'm a test.
</root>

Ganti baris permintaan pada script untuk melakukan request dengan:

...
onclick ="makeRequest('test.xml')">
...

Kemudian pada alertContents() ganti pada baris alert(http_request.responseText); diganti dengan:

var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data); 

Perintah tersebut untuk mengambil objek XMLDocument yang diberikan oleh responseXML dengan menggunakan method DOM untuk mengakses data dalam dokumen XML.

4. Petukaran data menggunakan JSON

Telah di sebutkan di atas bahwa JSON merupakan salah satu format pertukaran data yang dapat secara langsung diterjemahkan ke dalam objek Javascript. Pada contoh berikut akan dijelaskan bagaimana implementasi JSON pada AJAX dibandingkan dengan XML.

Pertama, buat data JSON dalam sebuah file dengan nama test.txt yang isinya:

{ "FirstName" : "Ahmad", "LastName" : "Masykur" } 

Ganti baris perintah pada script untuk melakukan request dengan:

...
onclick ="makeRequest('test.txt')">
...

Kemudian pada alertContents() ganti pada baris alert(http_request.responseText); diganti dengan:

eval("jsonObj="+http_request.responseText+";"); 
alert(jsonObj.FirstName + ' ' + jsonObj.LastName); 

Dari contoh di atas terlihat bahwa JSON lebih sederhana dan ringan dibandingkan dengan XML. Jumlah data yang terkandung lebih banyak dan total byte yang dikirim lebih kecil. Juga pada penulisan di javascript lebih sederhana karena notasi data dapat langsung diterjemahkan menjadi objek Javascript dengan fungsi eval().

Pada implementasi di projek nyata, data (baik XML maupun JSON) biasanya diambil dari application server atau webservice. Demikian tulisan singkat dan contoh sederhana mengenai AJAX. Semoga dapat membuka wawasan mengenai AJAX untuk dapat memulai mengembangkan aplikasi web yang AJAX-enabled.


Tags:
Categories: AJAX
Permalink | Comments (77) | Post RSSRSS comment feed