This Blog

Syndication

News

Awards

Microsoft MVP Logo
Grab this badge here!

Certificates

Transcript ID#: 6724122
Brainbench ASP.NET Certificate
 
Brainbench ASP.NET 2.0 Certificate
 
Brainbench .NET Framework 2.0 Certificate

Ahmad Masykur

var myObject = { "languages" : [ "C#", "VB.NET", "ASP.NET", "Javascript", "SDCC", "Assembler" ] }; //

May 2007 - Posts

  • 100% Smoke-Free

    Kepada: pengelola tempat-tempat umum

    Penelitian ilmiah tentang bahaya perokok pasif telah dilakukan selama lebih dari 20 tahun. Tidak ada keraguan bahwa merokok secara pasif sangat berbahaya bagi kesehatan manusia, menyebabkan kanker dan banyak penyakit pernafasan serta kardiovaskuler pada anak-anak serta orang dewasa, dan tidak jarang mempercepat kematian.

    Organisasi Kesehatan Dunia (WHO) telah berkesimpulan bahwa asap rokok, sekecil apapun jumlahnya, tetaplah berbahaya. Rekomendasi WHO tentang hal ini mengatakan bahwa satu-satunya cara untuk melindungi masyarakat dari bahaya asap rokok adalah dengan memberlakukan peraturan 100% bebas asap rokok bagi tempat-tempat umum.

    Hak untuk mendapatkan udara bersih, bebas dari asap rokok adalah hak umat manusia.

    Dengan demikian, kami meminta anda untuk melindungi kesehatan pegawai, pekerja dan masyarakat umum dengan cara menerapkan peraturan yang 100% melarang merokok di tempat-tempat umum. Kami percaya, langkah ini adalah langkah yang sangat penting untuk melindungi kesehatan kita dan anak-anak kita semua.

    Tertanda,

    Ahmad Masykur


    To: manager of public places

    Scientific research about the harms of second-hand tobacco smoke has been accumulating for over 20 years. There is no doubt that breathing second-hand tobacco smoke (SHS) is very dangerous to human health, causing cancer and many serious respiratory and cardiovascular diseases in children and adults, often leading to premature death.

    The World Health Organization (WHO) has concluded that there is no safe level of human exposure to second-hand tobacco smoke, and the upcoming WHO policy recommendations on protection from exposure to second-hand tobacco smoke clearly state that the establishment of 100% smoke-free areas is the only way to protect the public to such exposure and its consequences.

    The right to clean air, free from tobacco-smoke is a human right.

    Therefore, we ask you to defend and protect the health of employers, workers and the public by implementing the necessary legislation that will make all public indoor working places, including bars and restaurants 100% smoke-free. We think this is a critical step to protecting our health and that of our children.

    Sincerely,

    Signed by

    Ahmad Masykur

    Share this post: | | | |
  • Logging Module pada DotNetNuke

    Alhamdulillah, selesai sudah pekerjaan untuk mencatat semua aktifitas dalam modul DotNetNuke. Pekerjaan selesai lebih cepat dari jadwal, Alhamdulillah bisa pulang kampung dengan tenang.

    DotNetNuke telah memiliki mekanisme untuk mencatat semua aktifitas dan exception dengan menggunakan Log Provider. Dengan menggunakan Log Provider ini, kita dengan mudah dapat menambahkan log pada modul kita sendiri. Di DotNetNuke terdapat dua jenis log yaitu event-log dan site-log. Event-log ini lah yang akan kita gunakan untuk mencatat aktifitas modul.

    Logging DotNetNuke menggunakan tiga tabel yaitu tabel EventLogConfig (untuk menyimpan konfigurasi log), tabel EventLogTypes (untuk menyimpan daftar jenis log) dan tabel EventLog (untuk menyimpan data log). Di sini kita hanya akan mengutak atik dua tabel saja yaitu EventLog dan EventLogTypes.

    Pertama yang dilakukan adalah menambahkan beberapa baris data di tabel EventLogTypes karena ini yang akan membedakan tipe log. Untuk membedakan log tersebut adalah log yang ditulis oleh internal DotNetNuke dan modul kita, pada field LogTypeOwner kita isi dengan class modul kita. Sebagai contoh:

    INSERT INTO [directpublish_nl].[dbo].[EventLogTypes] VALUES(N'MY_CUSTOMER_CREATED', N'Customer Add', N'', N'MyModule.Logging', N'ItemCreated') INSERT INTO [directpublish_nl].[dbo].[EventLogTypes] VALUES(N'MY_CUSTOMER_UPDATED', N'Customer Edit', N'', N'MyModule.Logging', N'ItemUpdated') INSERT INTO [directpublish_nl].[dbo].[EventLogTypes] VALUES(N'MY_CUSTOMER_DELETED', N'Customer Delete', N'', N'MyModule.Logging', N'ItemDeleted')

    Setelah jenis log sudah didaftarkan, selanjutnya bikin storedprocedure dan provider untuk mengakses log yang telah disaring berdasarkan LogTypeOwner. Kita hanya butuh storedprocedure dan provider untuk mengambil log saja karena kita hanya perlu menyaring data yang nantinya akan kita tampilkan saja. Storedprocedure dan provider untuk menulis log, kita masih bisa gunakan milik DotNetNuke. Storedprocedure dan provider kita modifikasi dari storedprocedure dan provider DotNetNuke.

    Storedprocedure yang telah dimodifikasi sebagai berikut:

    /****** Object: StoredProcedure [dbo].[My_GetEventLog] Script Date: 05/30/2007 14:49:35 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF (EXISTS(SELECT NAME, TYPE FROM sysobjects WHERE (NAME = 'My_GetEventLog') AND (TYPE = 'P'))) DROP PROCEDURE [dbo].[My_GetEventLog]; GO CREATE PROCEDURE [dbo].[My_GetEventLog] @PortalID int, @LogTypeKey nvarchar(35), @PageSize int, @PageIndex int AS DECLARE @PageLowerBound int DECLARE @PageUpperBound int -- Set the page bounds SET @PageLowerBound = @PageSize * @PageIndex SET @PageUpperBound = @PageLowerBound + @PageSize + 1 CREATE TABLE #PageIndex ( IndexID int IDENTITY (1, 1) NOT NULL, LogGUID varchar(36) COLLATE database_default ) INSERT INTO #PageIndex (LogGUID) SELECT EventLog.LogGUID FROM EventLog INNER JOIN EventLogConfig ON EventLog.LogConfigID = EventLogConfig.ID INNER JOIN EventLogTypes ON EventLog.LogTypeKey = EventLogTypes.LogTypeKey WHERE (LogPortalID = @PortalID or @PortalID IS NULL) AND (EventLog.LogTypeKey = @LogTypeKey or @LogTypeKey IS NULL) AND (EventLogTypes.LogTypeOwner = 'MyModule.Logging') ORDER BY LogCreateDate DESC SELECT EventLog.* FROM EventLog INNER JOIN EventLogConfig ON EventLog.LogConfigID = EventLogConfig.ID INNER JOIN #PageIndex PageIndex ON EventLog.LogGUID = PageIndex.LogGUID WHERE PageIndex.IndexID > @PageLowerBound AND PageIndex.IndexID < @PageUpperBound ORDER BY PageIndex.IndexID SELECT COUNT(*) as TotalRecords FROM #PageIndex GO /****** Object: StoredProcedure [dbo].[My_GetEventLogType] Script Date: 05/30/2007 15:12:08 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF (EXISTS(SELECT NAME, TYPE FROM sysobjects WHERE (NAME = 'My_GetEventLogType') AND (TYPE = 'P'))) DROP PROCEDURE [dbo].[My_GetEventLogType]; GO CREATE PROCEDURE [dbo].[My_GetEventLogType] AS SELECT * FROM dbo.EventLogTypes WHERE (EventLogTypes.LogTypeOwner = 'MyModule.Logging') GO

    Selanjutnya buat provider sendiri untuk mengakses storedprocedure di atas.

    Pada DataProvider tambahkan beberapa abstraksi fungsi sebagai berikut:

    'Logging Public MustOverride Function GetLogTypeInfo() As IDataReader Public MustOverride Function GetLog() As IDataReader Public MustOverride Function GetLog(ByVal LogType As String) As IDataReader Public MustOverride Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Public MustOverride Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Public MustOverride Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Public MustOverride Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader

    Implementasi dari abstraksi fungsi di atas adalah sebagai berikut:

    Public Overloads Overrides Function GetLog() As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, DBNull.Value), IDataReader) End Function Public Overloads Overrides Function GetLog(ByVal LogType As String) As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, LogType), IDataReader) End Function Public Overloads Overrides Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, DBNull.Value, PageSize, PageIndex), IDataReader) End Function Public Overloads Overrides Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", PortalID, DBNull.Value, PageSize, PageIndex), IDataReader) End Function Public Overloads Overrides Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", PortalID, LogType, PageSize, PageIndex), IDataReader) End Function Public Overloads Overrides Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, LogType, PageSize, PageIndex), IDataReader) End Function Public Overrides Function GetLogTypeInfo() As IDataReader Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLogType"), IDataReader) End Function

    Selanjutnya bikin controller untuk menakses provider tersebut. Controller inilah yang akan berkomunikasi dengan module kita.

    Imports System.Data Imports System.Data.SqlClient Imports System.threading Imports System.Xml.Serialization Imports DotNetNuke Imports DotNetNuke.Services.Log Imports DotNetNuke.Common.Utilities Imports DotNetNuke.Entities.Users Public Class LoggingController Private Function FillLogInfo(ByVal dr As IDataReader) As DotNetNuke.Services.Log.EventLog.LogInfo Dim obj As New DotNetNuke.Services.Log.EventLog.LogInfo() Try Dim LogGUID As String LogGUID = Convert.ToString(dr("LogGUID")) obj.LogCreateDate = Convert.ToDateTime(dr("LogCreateDate")) obj.LogGUID = Convert.ToString(dr("LogGUID")) If Not IsDBNull(dr("LogPortalID")) Then obj.LogPortalID = Convert.ToInt32(dr("LogPortalID")) End If If Not IsDBNull(dr("LogPortalName")) Then obj.LogPortalName = Convert.ToString(dr("LogPortalName")) End If If Not IsDBNull(dr("LogServerName")) Then obj.LogServerName = Convert.ToString(dr("LogServerName")) End If If Not IsDBNull(dr("LogUserID")) Then obj.LogUserID = Convert.ToInt32(dr("LogUserID")) End If obj.LogTypeKey = Convert.ToString(dr("LogTypeKey")) obj.LogUserName = Convert.ToString(dr("LogUserName")) obj.LogConfigID = Convert.ToString(dr("LogConfigID")) obj.LogProperties.Deserialize(Convert.ToString(dr("LogProperties"))) Finally End Try Return obj End Function Public Overridable Function GetLog() As DotNetNuke.Services.Log.EventLog.LogInfoArray Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog() Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLog(ByVal LogType As String) As DotNetNuke.Services.Log.EventLog.LogInfoArray Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog(LogType) Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog(PageSize, PageIndex) Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While dr.NextResult() While dr.Read TotalRecords = Convert.ToInt32(dr("TotalRecords")) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray If PortalID = -1 Then Return GetLog() End If Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog(PortalID, PageSize, PageIndex) Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While dr.NextResult() While dr.Read TotalRecords = Convert.ToInt32(dr("TotalRecords")) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray If PortalID = -1 Then Return GetLog(LogType) End If Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog(PortalID, LogType, PageSize, PageIndex) Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While dr.NextResult() While dr.Read TotalRecords = Convert.ToInt32(dr("TotalRecords")) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray Dim dr As IDataReader = DataProvider.Instance.GetLog(LogType, PageSize, PageIndex) Try Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo While dr.Read objLogInfo = FillLogInfo(dr) objArr.Add(objLogInfo) End While dr.NextResult() While dr.Read TotalRecords = Convert.ToInt32(dr("TotalRecords")) End While Finally If Not dr Is Nothing Then dr.Close() End If End Try Return objArr End Function Public Overridable Function GetLogTypeInfo() As ArrayList Return CBO.FillCollection(DataProvider.Instance.GetLogTypeInfo(), GetType(DotNetNuke.Services.Log.EventLog.LogTypeInfo)) End Function End Class

    Nah, storedprocedure, provider dan controller sudah siap. Berikutnya kita siapkan UserControl untuk menampilkan custom-log kita. UserControl ini juga hasil modifikasi dari UserControl LogViewer-nya DotNetNuke. Pada UserControl tersebut, hanya beberapa baris saja yang perlu disesuaikan.

    Pada file logviewer.ascx, sesuaikan Inherits class baris directive "<%@ Control ..." menjadi class lengkap dengan namespace yang digunakan:

    <%@ Control CodeFile="ucLogViewer.ascx.vb" language="vb" AutoEventWireup="false" Explicit="true" Inherits="LogViewer" targetSchema="http://schemas.microsoft.com/intellisense/ie5"%>

    Pada codebehind-nya, sesuaikan namespace dengan namespace module, pada method BindData() ganti deklarasi object objLogController dengan controller yang dibuat sebelumnya.

    Dim objLogController As New MyModule.LoggingController

    Pada method BindLogTypeDropDown(), sesuaikan juga deklarasi object objLogController dengan controller yang dibuat seperti pada method BindData().

    Private Sub BindLogTypeDropDown() Dim objLogController As New HollandTraining.LoggingController '...

    Satu lagi, jika paging tidak berjalan dengan baik, sesuaikan link paging pada method InitializePaging.

    Original code:

    1 Private Sub InitializePaging(ByVal ctlPagingControl As DotNetNuke.UI.WebControls.PagingControl, ByVal TotalRecords As Integer, ByVal PageSize As Integer) 2 ctlPagingControl.TotalRecords = TotalRecords 3 ctlPagingControl.PageSize = PageSize 4 ctlPagingControl.CurrentPage = PageIndex 5 Dim strQuerystring As String = ""

    Ganti baris ke-5 sesuai dengan query link untuk control module kita, misalnya:

    Dim strQuerystring As String = "&ctrl=logs"

    Fasilitas logging untuk module kita telah siap digunakan, tahap akhir adalah penulisan log di tiap event module. Berikut adalah contoh code untuk menuliskan event tersebut. Buat method WriteLog sebagai berikut.

    Private Sub WriteLog(ByVal LogKeyType As String, ByVal CustomerId As Integer, ByVal CustomerName As String) 'Add module log Dim _logController As New DotNetNuke.Services.Log.EventLog.LogController Dim _logInfo As New Log.EventLog.LogInfo() _logInfo.LogCreateDate = DateTime.Now _logInfo.LogPortalID = PortalId _logInfo.LogUserID = UserController.GetCurrentUserInfo.UserID _logInfo.LogUserName = UserController.GetCurrentUserInfo.Username _logInfo.LogTypeKey = LogKeyType _logInfo.AddProperty("Module Part", "Customers") _logInfo.AddProperty("CustomerId", CustomerId.ToString()) _logInfo.AddProperty("Customer Name", CustomerName) _logController.AddLog(_logInfo) End Sub

    Pada saat event "Add", "Update" dan "Delete" customer, -- sebagai contoh -- kita tuliskan log sebagai berikut:

    Dim custId as Intenger = 0 Dim custName as String = "" 'custId = n, dimana n didapat dari data CustomerId 'custName = name, dinama name adalah nama customer untuk CustomerId 'Add customer WriteLog("MY_CUSTOMER_CREATED", custId, custName) 'Update customer WriteLog("MY_CUSTOMER_UPDATED", custId, custName) 'Delete customer WriteLog("MY_CUSTOMER_DELETED", custId, custName)

    Selesai sudah penambahan fasilitas log ke dalam module DotNetNuke. Terakhir yang harus dilakukan adalah pengujian.

    Semoga tulisan ini bisa bermanfaat.

    Share this post: | | | |
    Posted May 31 2007, 01:39 PM by cahnom with 2 comment(s)
    Filed under:
  • Ngeblog Menggunakan Microsoft Word 2007

    Satu fitur yang menarik Microsoft Office 2007 adalah dapat digunakan untuk posting blog menggunakan Microsoft Word. Fitur ini ada sejak versi Beta 2. Namun ada klaim dari Mads Kristensen (koordinator project BlogEngine.NET, http://www.codeplex.com/blogengine) bahwa ide itu merupakan curian dari idenya. Coba lihat postingan dia di http://blog.madskristensen.dk/post/Microsoft-stole-my-idea.aspx

    FYI: Tulisan ini ditulis menggunakan Microsoft Word 2007 Proffesional Edition

    Share this post: | | | |
  • 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="form1" 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="form1" 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="form1" 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.

    Share this post: | | | |
  • Release Pertama BlogEngine.NET Sudah Bisa Di-unduh

    BlogEngine.NET 1.0 telah di-release. 

    BlogEngine.NET adalah ASP.NET blog yang sangat sederhana dan sangat ringan. Beberapa fitur diantaranya:

    - Multi-author support
    - Pingbacks and trackbacks
    - Event based for plug-in writers
    - Theming directly in master pages and user controls
    - Gravatar and coComments implemented
    - Live preview on commenting
    - Full editing and creation of pages that are not posts
    - Extended search capabilities
    - Tag cloud
    - Self updating blogroll
    - Runs entirely on XML. No database needed

    Silakan download di http://www.codeplex.com/blogengine/Release/Project...

    FYI: Situs http://www.masykur.web.id dibangun menggunakan BlogEngine.NET

    Share this post: | | | |
    Posted May 28 2007, 10:36 AM by cahnom with no comments
    Filed under:
  • Gempa di Sumbawa

    Pagi ini telah terjadi gempa di daerah Sumbawa NTB pada 2007-05-24 01:06:24 GMT (atau sekitar pukul 09:06:24 WITA). Sumber http://geofon.gfz-potsdam.de/db/eqinfo.php

    Tapi yang disayangkan sampai tulisan ini dipublikasikan belum ada data dari BMG, padahal dari jaringan GEOFON sudah ada beberapa saat setelah kejadian. Apa sebenarnya yang terjadi dengan BMG kita? Apa peralatan yang dimiliki sudah terlalu usang atau orang-orangnya belum bangun dari tidur?

    Share this post: | | | |
  • JSON.org Telah Diterjemahkan dalam Bahasa Indonesia

    Situs JSON.org hari ini telah diterjamahkan dalam Bahasa Indonesia. Silakan cek di http://json.org/json-id.html

    Share this post: | | | |
    Posted May 21 2007, 10:03 PM by cahnom with no comments
    Filed under:
  • Resolving the Sys is undefined error in ASP.NET AJAX

    Pada saat mencoba ASP.NET AJAX di komputer dengan Sistem Operasi Windows Vista, saya mendapatkan pesan error "Sys is undefined" pada Internet Explorer atau "Sys is not defined" pada Error Console Firefox. Sepintas pada waktu aplikasi dijalankan, tidak ada masalah, halaman berjalan sebagaimana mestinya. Namun jika dicermati, UpdatePanel tidak melakukan partial update tapi keseluruhan halaman diambil lagi dari server.

    Saya coba membuka dokumentasi ASP.NET AJAX yang saya install di komputer lokal dengan IIS7 sebagai web server, ternyata sama juga, muncul pesan yang sama dengan aplikasi yang saya buat. Saya coba install ulang ASP.NET AJAX ternyata tidak membuahkan hasil, tetap keluar error yang sama. Setelah coba otak-atik konfigurasi ternyata saya menemukan solusinya.

    1. Error "Sys is undefined" pada ASP.NET AJAX yang berjalan di atas IIS7
      Ubah ApplicationPool menjadi DefaultAppPool atau Pipeline mode diset: Integrated
    2. Error "Sys is undefined" pada ASP.NET AJAX yang berjalan di atas Visual Studio Development Server
      Tambahkan konfigurasi berikut pada web.config di dalam tag <system.web>
    <httpHandlers> <remove verb="*" path="*.asmx"/> <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/> </httpHandlers> <httpModules> <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </httpModules>

    Alhamdulillah setelah sedikit berusaha dan berdoa, aplikasi ASP.NET AJAX yang aku buat dan dokumentasi ASP.NET AJAX bisa berjalan dengan baik.

    Share this post: | | | |
  • 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.

    Share this post: | | | |
  • 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 berbahasa, 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.

    1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml" > 4 <head> 5 <title>Retrieving JSON Data via AJAX</title> 6 <script type="text/javascript" language="javascript" src="glm-ajax.js" > 7 </script> 8 <script type="text/javascript" language="javascript"> 9 function processData(JSONData) { 10 alert(JSONData.color); 11 } 12 function ajaxCallback(content) { 13 eval(content); //eval the contents of data. 14 } 15 var ajax = new GLM.AJAX(); 16 //call json-func-data.txt and pass the contents to ajaxCallback. 17 ajax.callPage("json-func-data.txt", ajaxCallback); 18 </script> 19 </head> 20 <body> 21 </body> 22 </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).

    1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml" > 4 <head> 5 <title>Retrieving JSON Data via AJAX</title> 6 <script type="text/javascript" language="javascript" src="json.js" ></script> 7 <script type="text/javascript" language="javascript" src="glm-ajax.js" ></script> 8 <script type="text/javascript" language="javascript"> 9 function processData(JSONData) { 10 alert(JSONData.color); 11 } 12 function ajaxCallback(content) { 13 JSONData = content.parseJSON(); 14 processData(JSONData); 15 } 16 var ajax = new GLM.AJAX(); 17 //call json-func-data.txt and pass the contents to ajaxCallback. 18 ajax.callPage("json-func-data.txt", ajaxCallback); 19 </script> 20 </head> 21 <body> 22 </body> 23 </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);

    Kode di atas akan menghasilkan keluaran sebagai berikut.

    {"accounting":[{"firstName":"Ahmad","lastName":"Masykur","age":25},{"firstName":"Agung","lastName":"Riyadi","age":29}],"sales":[{"firstName":"Vianton","lastName":"Rahmat","age":23},{"firstName":"Kusuma","lastName":"Dewi","age":25}]}

    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.

    Share this post: | | | |
    Posted May 13 2007, 01:10 PM by cahnom with no comments
    Filed under: ,
  • Menguji Performance Aplikasi ASP.NET

    Terdapat fitur baru ASP.NET 2.0 untuk melihat dan mendiagnosis informasi pada sebuah request haaman ASP.NET. Fitur ini dapat diaktifkan pada sebuah halaman atau satu aplikasi. Fitur ini disebut sebagai tracing, yang memungkinkan kita untuk menulis sebuah pernyataan debug langsung pada sebuah kode tanpa harus menghapusnya ketika aplikasi sudah di-deploy pada server production. Kode tersebut tidak akan ikut dieksekusi pada aplikasi yang dideploy di server production.

    Di sini, kita akan ambil contoh performance algoritma pronounce yang ditulis oleh Mas Irwansyah (tindak lanjut atas permintaan di posting Mas Irwansyah) dengan algoritma Terbilang yang saya posting di http://semarang.netindonesia.net/blogs/cahnom.

    Pertama, buat aplikasi sederhana sebagai bahan uji. Buat halaman ASP.NET sebagai berikut.

    1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ajax_basic._Default" %> 2 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 4 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 5 6 <html xmlns="http://www.w3.org/1999/xhtml" > 7 <head runat="server"> 8 <title>Performance Test</title> 9 </head> 10 <body> 11 <form id="form1" runat="server"> 12 <div> 13 <table border="0" cellpadding="0" cellspacing="0" width="100%"> 14 <tr> 15 <td style="width: 129px"> 16 Angka</td> 17 <td> 18 &nbsp;<asp:TextBox ID="txtAngka" runat="server"></asp:TextBox> 19 <asp:Button ID="btnConvert" runat="server" Text="Convert" OnClick="btnConvert_Click" /></td> 20 </tr> 21 <tr> 22 <td> 23 Terbilang (recursive)</td> 24 <td> 25 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></td> 26 </tr> 27 <tr> 28 <td> 29 Terbilang 2</td> 30 <td> 31 <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label></td> 32 </tr> 33 </table> 34 35 </div> 36 </form> 37 </body> 38 </html>

    Dan codebehind-nya.

    1 using System; 2 using System.Data; 3 using System.Configuration; 4 using System.Collections; 5 using System.Web; 6 using System.Web.Security; 7 using System.Web.UI; 8 using System.Web.UI.WebControls; 9 using System.Web.UI.WebControls.WebParts; 10 using System.Web.UI.HtmlControls; 11 using System.Collections.Generic; 12 using System.Text; 13 14 namespace ajax_basic 15 { 16 public partial class _Default : System.Web.UI.Page 17 { 18 protected void Page_Load(object sender, EventArgs e) 19 { 20 21 } 22 23 protected void btnConvert_Click(object sender, EventArgs e) 24 { 25 Trace.Write("Terbilang", "NolTerbilang Begin Proces"); 26 Label1.Text = NolTerbilang(long.Parse(txtAngka.Text)); 27 Trace.Write("Terbilang", "NolTerbilang End Proces"); 28 Trace.Write("Terbilang", "Pronounce Begin Proces"); 29 Label2.Text = Pronounce(long.Parse(txtAngka.Text), false); 30 Trace.Write("Terbilang", "Pronounce End Proces"); 31 } 32 33 public string NolTerbilang(long x) 34 { 35 if (x == 0) 36 { 37 return "Nol"; 38 } 39 else 40 { 41 return Terbilang(x); 42 } 43 } 44 45 public string Terbilang(long x) 46 { 47 string[] ambilbil = { "", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan", "sepuluh", "sebelas" }; 48 if (x < 12) 49 { 50 return " " + ambilbil[x]; 51 } 52 else if (x < 20) 53 { 54 return Terbilang(x - 10) + " belas"; 55 } 56 else if (x < 100) 57 { 58 return Terbilang((long)x / 10) + " puluh" + Terbilang(x % 10); 59 } 60 else if (x < 200) 61 { 62 return " seratus" + Terbilang(x - 100); 63 } 64 else if (x < 1000) 65 { 66 return Terbilang((long)x / 100) + " ratus" + Terbilang(x % 100); 67 } 68 else if (x < 2000) 69 { 70 return " seribu" + Terbilang(x - 1000); 71 } 72 else if (x < 1000000) 73 { 74 return Terbilang((long)x / 1000) + " ribu" + Terbilang(x % 1000); 75 } 76 else if (x < 1000000000) 77 { 78 return Terbilang((long)x / 1000000) + " juta" + Terbilang(x % 1000000); 79 } 80 else if (x < 1000000000000) 81 { 82 return Terbilang((long)x / 1000000000) + " milyar" + Terbilang(x % 1000000000); 83 } 84 else if (x < 1000000000000000) 85 { 86 return Terbilang((long)x / 1000000000000) + " trilyun" + Terbilang(x % 1000000000000); 87 } 88 else if (x < 1000000000000000000) 89 { 90 return Terbilang((long)x / 1000000000000000) + " bilyun" + Terbilang(x % 1000000000000000); 91 } 92 else if (x <= long.MaxValue) 93 { 94 return Terbilang((long)x / 1000000000000000000) + " tetra bilyun" + Terbilang(x % 1000000000000000000); 95 } 96 else 97 { 98 return ""; 99 } 100 } 101 102 private string[] _ZeroToEleven = {"Nol", "Satu", "Dua", "Tiga", "Empat" 103 , "Lima", "Enam", "Tujuh", "Delapan" 104 , "Sembilan", "Sepuluh", "Sebelas"}; 105 private string[] _GroupSuffix = { "", "ribu", "juta", "milyar", "trilyun", "bilyun", "tetra bilyun" }; 106 public string Pronounce(long Number, bool LowerCase) 107 { 108 string numberString = Number.ToString(); 109 string result = string.Empty; 110 111 if (Number <= 11) 112 { 113 return (LowerCase ? _ZeroToEleven[Number].ToLower() : _ZeroToEleven[Number]); 114 } 115 116 //handle puluhan and belasan but starts from twelve up 117 if (numberString.Length == 2) 118 { 119 int firstDigit = Convert.ToInt32(numberString[0].ToString()); 120 int secondDigit = Convert.ToInt32(numberString[1].ToString()); 121 //belasan (12 - 19) 122 if (firstDigit == 1) 123 { 124 return Pronounce(secondDigit, LowerCase) + " belas"; 125 } 126 if (secondDigit == 0) 127 { 128 return Pronounce(firstDigit, LowerCase) + " puluh"; 129 } 130 else 131 { 132 return Pronounce(firstDigit, LowerCase) + " puluh " + Pronounce(secondDigit, true); 133 } 134 } 135 136 //handle 100 - 999 137 if (numberString.Length == 3) 138 { 139 long firstDigit = Convert.ToInt32(numberString[0].ToString()); 140 string lastTwoDigits = numberString.Substring(1); 141 long lastTwoDigitNumber = Convert.ToInt64(lastTwoDigits); 142 if (firstDigit == 1) 143 { 144 if (lastTwoDigitNumber > 0) 145 { 146 result = "Seratus " + Pronounce(lastTwoDigitNumber, true); 147 } 148 else 149 { 150 result = "Seratus"; 151 } 152 if (LowerCase) 153 { 154 result = result[0].ToString().ToLower() + result.Substring(1); 155 } 156 157 return result; 158 } 159 else 160 { 161 if (lastTwoDigitNumber > 0) 162 { 163 return Pronounce(firstDigit, LowerCase) + " ratus " + Pronounce(lastTwoDigitNumber, true); 164 } 165 else 166 { 167 return Pronounce(firstDigit, LowerCase) + " ratus"; 168 } 169 } 170 } 171 172 Stack<string> groupStack = GroupNumber(numberString); 173 if (groupStack.Count > _GroupSuffix.Length) 174 { 175 throw new InvalidOperationException("Number is too big. I don't know how to pronounce it in Bahasa."); 176 } 177 while (groupStack.Count > 0) 178 { 179 string currentGroup = groupStack.Pop(); 180 long currentGroupNumber = Convert.ToInt64(currentGroup); 181 //Print only 1000 down with 'se' e.g. Seribu 182 if (currentGroupNumber == 1 && groupStack.Count <= 1) 183 { 184 if (result.Length > 0) 185 { 186 result += " "; 187 } 188 result += "se" + _GroupSuffix[groupStack.Count]; 189 } 190 else 191 { 192 if (currentGroupNumber > 0) 193 { 194 if (result.Length > 0) 195 { 196 result += " "; 197 } 198 result += Pronounce(currentGroupNumber, true) + " " + _GroupSuffix[groupStack.Count]; 199 } 200 } 201 202 } 203 204 result = result[0].ToString().ToUpper() + result.Substring(1); 205 206 return result; 207 } 208 209 private Stack<string> GroupNumber(string NumberString) 210 { 211 Stack<string> groupStack = new Stack<string>(); 212 string currentGroup = string.Empty; 213 214 int counter = 0; 215 for (int i = NumberString.Length - 1; i >= 0; i--) 216 { 217 currentGroup = NumberStringIdea.ToString() + currentGroup; 218 counter++; 219 if (counter == 3) 220 { 221 groupStack.Push(currentGroup); 222 counter = 0; 223 currentGroup = string.Empty; 224 } 225 } 226 227 if (counter > 0) 228 { 229 groupStack.Push(currentGroup); 230 } 231 232 return groupStack; 233 } 234 } 235 }

    Untuk membuat pesan pada informasi trace, gunakan object trace untuk menulis pernyataan debug saat konfigurasi tracing diaktifkan. Pada kode di atas, informasi tracing ditulis pada baris 25 sampai dengan 30.

    Ada dua metode untuk melakukan tracing yaitu tracing perhalaman atau tracing semua halaman (level aplikasi).  Tracing perhalaman akan melakukan trace untuk halaman tertentu sedangkan trace level aplikasi akan melakukan trace untuk semua halaman dalam satu aplikasi.

    Tarcing pada halaman dapat diaktifkan dengan menambahkan atribut trace="true" pada directive @Page.

    <%@ Page Trace="true" %>

    Selain itu juga dapat ditambahkan atribut TraceMode untuk mengurutkan laporan trace berdasarkan waktu atau kategori.

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ajax_basic._Default" Trace="true" TraceMode="SortByTime" %>

    Untuk melakukan tracing aplikasi, tambahkan atribut <trace> pada file web.config

    <system.web> <trace enabled="true" localOnly="true" mostRecent="true" pageOutput="true" traceMode="SortByTime" requestLimit="10"/>

    Untuk melihat semua informasi tarcing aplikasi, buka halaman http://<alamat-aplikasi>/trace.axd atau jika atribut pageOutput="true", informasi trace akan ditampilkan di halaman.

    Berikut adalah hasil dari pengujian atas kedua algoritma di atas.

    Dengan menggunakan tracing, kita dapat mengetahui bagian mana dari program yang memiliki proses terlalu lama untuk kemudian dilakukan optimasi.

    Share this post: | | | |
    Posted May 12 2007, 10:48 PM by cahnom with no comments
    Filed under:
  • Ajax or AJAX?

    Ungkapan Ajax pertama kali dikenalkan oleh Jesse James Garrett untuk mendeskripsikan gaya aplikasi web dan teknologi-teknologi yang menyertainya, sehingga dapat membuat aplikasi web yang interaktif. Pada mulanya, ungkapan Ajax yang tersebar di web adalah sebuah akronim AJAX (Asynchronous JavaScript And XML). Saat ini kenyataannya huruf "X" pada AJAX tidak representatif untuk menunjukkan format data yang digunakan sebagai komunikasi client dengan server web semenjak banyak aplikasi Ajax yang beralih menggunakan JSON. JSON merupakan alternatif format pertukaran data yang lebih sederhana dan lebih efisien. Daripada merubah akronim AJAX menjadi AJAJ pada aplikasi web yang lebih interaktif ini, ungkapan Ajax digunakan tetap dipertahankan namun bukanlah sebuah akronim AJAX.

    Share this post: | | | |
    Posted May 12 2007, 05:38 PM by cahnom with no comments
    Filed under:
  • 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.

    Share this post: | | | |
    Posted May 12 2007, 04:55 PM by cahnom with no comments
    Filed under: ,
  • ASP.NET Enter Key Problem

    Pada pembuatan sebuah halaman web, terkadang terdapat beberapa input dan beberapa tombol (button). Ketika cursor focus ke sebuah textbox dan tekan tombol Enter, akan terjadi postback ke server. Sebagai contoh bila dalam halaman terdapat dua buah textbox dan dua buah tombol separti pada kode berikut:

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Button" /> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> <asp:Button ID="Button2" runat="server" Text="Button" />

    Setelah mengisi TextBox1 dan menekan tombol enter, terjadi postback ke server dan Event Click pada Button1 akan dikerjakan. Begitu *** jika TextBox2 yang diisi dan tombol Enter ditekan, Event Click pada Button1 yang dikerjakan, padahal yang diinginkan adalah Button2 yang harus dikerjakan.

    Untuk memecahkan masalah ini, pada ASP.NET 2.0 terdapat property DefaultButton pada Form dan Panel. Dalam kasus ini, digunakan Panel karena kedua TextBox tersebut berada dalam satu Form. Kelompokkan masing-masing inputan beserta default tombolnya ke dalam Panel.

    <asp:Panel ID="Panel1" runat="server" DefaultButton="Button1"> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Button" /> </asp:Panel> <asp:Panel ID="Panel2" runat="server" DefaultButton="Button2"> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> <asp:Button ID="Button2" runat="server" Text="Button" /> </asp:Panel>

    Pada ASP.NET 1.1 diperlukan trik khusus menggunakan Javascript untuk melakukan hal ini. Tambahkan code berikut pada event Load

    TextBox1.Attributes.Add("onkeydown", "if(event.which || event.keyCode)" + "{if ((event.which == 13) || (event.keyCode == 13)) " + "{document.getElementById('"+Button1.UniqueID+"').click();return false;}} " + "else {return true}; "); TextBox2.Attributes.Add("onkeydown", "if(event.which || event.keyCode)" + "{if ((event.which == 13) || (event.keyCode == 13)) " + "{document.getElementById('"+Button2.UniqueID+"').click();return false;}} " + "else {return true}; ");

    Pada kode di atas, jika saat kursor sedang berada di TextBox{n}, ketika tombol Enter ditekan (keycode untuk tombol enter adalah 13) maka akan memanggil method click pada Button{n}. Pada Firefox, event.keyCode tidak berjalan dengan baik, sebagai penggantinya digunakan event.which.

    Share this post: | | | |
    Posted May 10 2007, 01:47 PM by cahnom with 1 comment(s)
    Filed under:
  • JSON (JavaScript Object Notation)

    JSON merupakan salah satu format pertukaran data anatara browser dengan server. JSON memiliki format yang lebih sederhana dan elegan dibandingkan dengan pendahulunya, XML.

    Object

    Sebuah object dideklarasikan dengan

    var myObject = {};

    Terlihat sangat sederhana, di dalam pasangan kurungkurawal dapat berisi berbagaimacam infomasi dari yang paling sederhana hingga kompleks. Javascript menyimpan semua informasi di dalam pasangan kurungkurawal yang dapat berisi semua bentuk tipe data primitive seperti string, angka (number), array, tanggal (date) dan regular expression.

    Pembuatan sebuah Object

    Cara lama untuk membuat sebuah object adalah dengan menggunakan kata-kunci new.

    var myJSON = new Object();

    Metode ini telah diperbaiki. Sekarang untuk membuat object kosong, dapat digunakan  dengan hanya mendefinisikan pasangan kurungkurawal.

    var myJSON = {};

    Object sebagai Data

    Seperti halnya kebanyakan object dasar Javascript, format data sangatlah fleksibel yang ditulis sebagai pasangan nama dan nilai. Object memiliki nama yang terkandung dalam property object yang biasanya disebut sebagai nama object. Object juga memiliki property nilai. Lihat contoh berikut:

    var myFirstJSON = { "firstName" : "Ahmad", "lastName" : "Masykur", "age" : 25 }; document.writeln(myFirstJSON.firstName); // Outputs Ahmad document.writeln(myFirstJSON.lastName); // Outputs Masykur document.writeln(myFirstJSON.age);

    Object ini memiliki tiga property atau pasangan nama dan nilai. Nama adalah sebuah string (pada contoh di atas firstName, lastName dan age). Nilai dapat diisi dengan semua jenis object Javascript (semua di Javascript adalah object, nilai dapat diisi dengan string, angka, array, fungsi dan Object lainnya). Pada contoh di atas nilai diisi dengan Ahmad, Masykur dan 25. Ahmad dan Masykur adalah string dan 25 adalah angka. Seperti anda lihat pada contoh, nilai dapat diisi dengan berbagai macam object.

    Format data ini disebut sebagai JSON (JavaScript Object Notation). Yang menjadikan JSON tangguh adalah kemampuan nilai diisi dengan semua jenis data. Nilai dapat diisi dengan array atau object yang bertingkat dengan kedalaman yang tak terhingga. Berikut adalah salah satu contoh struktur JSON yang kompleks.

    var employees = { "accounting" : [ // accounting is an array in employyes { "firstName" : "Ahmad", // First element "lastName" : "Masykur", "age" : 25 }, { "firstName" : "Agung", // Second element "lastName" : "Riyadi", "age" : 29 } ], // End "accounting" array "sales" : [ // Sales is another array in employees. { "firstName" : "Vianton", // First element "lastName" : "Rahmat", "age" : 25 }, { "firstName" : "Kusuma", // Second element "lastName" : "Dewi", "age" : 25 } ] // End "sales" array } // End Employees

    Pada contoh di atas employees adalah sebuah object dimana object tersebut memiliki dua property atau pasangan nama dan nilai. Di dalam employeesaccounting adalah sebuah array dengan dua object JSON yang mimiliki dua employees dengan object name dan age. Seperti halnya accounting, sales adalah array yang memiliki dua object JSON. Semua data ini berada di dalam object employees.

    Pengaksesan Data pada JSON

    Cara yang paling umum untuk mengakses data JSON adalah dengan menggunakan notasi titik. Caranya dengan menuliskan nama object diikuti dengan titik dan kemudian diikuti dengan nama/property.

    var myObject = { 'color' : 'blue' }; document.writeln(myObject.color); // output blue

    Jika object mengandung object lagi di dalamnya, tinggal tambahkan titik dan nama di belakangnya.

     

    var myObject = { 'color' : 'blue', 'animal' : { 'cat' : 'friendly' } }; document.writeln(myObject.animal.cat); // output friendly

    Dengan menggunakan contoh employees sebalumnya, jika ingin mengakses orang pertama yang bekerja sebagai sales adalah sebagai berikut.

    document.writeln(employees.sales[0].firstName + ' ' + employees.sales[0].lastName);

    Untuk mengakses orang kedua yang bekerja sebagai accunting adalah.

    document.writeln(employees.accounting[1].firstName + ' ' + employees.accounting[1].lastName);

    Pada contoh di atas, employees adalah object yang memiliki dua array, masing-masing array memiliki dua object. JSON bisa memiliki struktur sekompleks apapun. Struktur JSON hanya dibatasi oleh jumlah storage dan memori yang tersedia. Hal ini dikarenakan JSON dapat berisi object dalam object dalam object dan array di dalam array di dalam array dan seterusnya.

    Mengakses JSON dengan Associative Array

    JSON juga dapat diakses dengan cara seperti associative array.

    var myFirstJSON = { "firstName" : "Ahmad", "lastName" : "Masykur", "age" : 25 }; document.writeln(myFirstJSON["firstName"]); // Outputs Ahmad document.writeln(myFirstJSON["lastName"]); // Outputs Masykur document.writeln(myFirstJSON["age"]); // Outputs 25

    Demikian paparan singkat mengenai JSON. Pada artikel berikutnya Insya Allah akan saya jelaskan implementasi JSON dengan AJAX.

    Artikel ini juga dapat dibaca di http://www.masykur.web.id

    Share this post: | | | |
    Posted May 08 2007, 03:23 PM by cahnom with 2 comment(s)
    Filed under: ,
More Posts Next page »