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

ASP.NET 4 Performance Tips

Performance atau dalam Bahasa Indonesia disebut sebagai kinerja merupakan sebuah hal yang penting dalam sebuah aplikasi. Dalam sebuah aplikasi web terdapat beberapa faktor yang menyebabkan kinerja bagus atau buruk. Secara umum kinerja aplikasi dinyatakan bagus jika waktu tanggap (response time) dapat tercapai secepat mungkin. Untuk aplikasi web publik seperti www.facebook.com, www.kaskus.us, www.detik.com dan situs lainnya, dengan kinerja yang baik dapat membuat pengunjung betah mengunjunginya. Untuk aplikasi bisnis, kinerja yang bagus akan meningkatkan kinerja karyawan yang menjadi usernya.

Berikut akan saya utarakan beberapa tips untuk meningkatkan kinerja aplikasi ASP.NET 4. Beberapa tips juga dapat digunakan juga untuk versi ASP.NET sebelumnya.

Aplikasi ASP.NET sebelum dioptimasi.

Pertama akan saya buat aplikasi sederhana menggunakan ASP.NET tanpa optimasi apapun. Dalam contoh ini saya buat sebuah halaman yang menampilkan data tabular yang datanya saya ambil dari XML. Halaman ini menggunakan Ajax dengan UpdatePanel. Buat sebuah aplikasi web project baru dan pilih ASP.NET Web Application.

image

Puat satu class Product untuk entity data product.

namespace WebApplication1
{
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Supplier { get; set; }
        public string Category { get; set; }
        public string QuantityPerUnit { get; set; }
        public decimal UnitPrice { get; set; }
        public decimal UnitsInStock { get; set; }
        public decimal UnitsOnOrder { get; set; }
        public decimal ReorderLevel { get; set; }
    }
}

Buat file XML yang berisi data berikut dan tempatkan dalam folder App_Data. Beri nama file Products.xml

<?xml version="1.0" encoding="utf-8" ?>
<Products>
  <Product ID="1" Name="Chai" Supplier="Exotic Liquids" Category="Beverages" QuantityPerUnit="10 boxes x 20 bags" UnitPrice="18.0000" UnitsInStock="39" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="2" Name="Chang" Supplier="Exotic Liquids" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="19.0000" UnitsInStock="17" UnitsOnOrder="40" ReorderLevel="25" />
  <Product ID="3" Name="Aniseed Syrup" Supplier="Exotic Liquids" Category="Condiments" QuantityPerUnit="12 - 550 ml bottles" UnitPrice="10.0000" UnitsInStock="13" UnitsOnOrder="70" ReorderLevel="25" />
  <Product ID="4" Name="Chef Anton's Cajun Seasoning" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="48 - 6 oz jars" UnitPrice="22.0000" UnitsInStock="53" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="5" Name="Chef Anton's Gumbo Mix" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="36 boxes" UnitPrice="21.3500" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="6" Name="Grandma's Boysenberry Spread" Supplier="Grandma Kelly's Homestead" Category="Condiments" QuantityPerUnit="12 - 8 oz jars" UnitPrice="25.0000" UnitsInStock="120" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="7" Name="Uncle Bob's Organic Dried Pears" Supplier="Grandma Kelly's Homestead" Category="Produce" QuantityPerUnit="12 - 1 lb pkgs." UnitPrice="30.0000" UnitsInStock="15" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="8" Name="Northwoods Cranberry Sauce" Supplier="Grandma Kelly's Homestead" Category="Condiments" QuantityPerUnit="12 - 12 oz jars" UnitPrice="40.0000" UnitsInStock="6" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="9" Name="Mishi Kobe Niku" Supplier="Tokyo Traders" Category="Meat/Poultry" QuantityPerUnit="18 - 500 g pkgs." UnitPrice="97.0000" UnitsInStock="29" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="10" Name="Ikura" Supplier="Tokyo Traders" Category="Seafood" QuantityPerUnit="12 - 200 ml jars" UnitPrice="31.0000" UnitsInStock="31" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="11" Name="Queso Cabrales" Supplier="Cooperativa de Quesos 'Las Cabras'" Category="Dairy Products" QuantityPerUnit="1 kg pkg." UnitPrice="21.0000" UnitsInStock="22" UnitsOnOrder="30" ReorderLevel="30" />
  <Product ID="12" Name="Queso Manchego La Pastora" Supplier="Cooperativa de Quesos 'Las Cabras'" Category="Dairy Products" QuantityPerUnit="10 - 500 g pkgs." UnitPrice="38.0000" UnitsInStock="86" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="13" Name="Konbu" Supplier="Mayumi's" Category="Seafood" QuantityPerUnit="2 kg box" UnitPrice="6.0000" UnitsInStock="24" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="14" Name="Tofu" Supplier="Mayumi's" Category="Produce" QuantityPerUnit="40 - 100 g pkgs." UnitPrice="23.2500" UnitsInStock="35" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="15" Name="Genen Shouyu" Supplier="Mayumi's" Category="Condiments" QuantityPerUnit="24 - 250 ml bottles" UnitPrice="15.5000" UnitsInStock="39" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="16" Name="Pavlova" Supplier="Pavlova, Ltd." Category="Confections" QuantityPerUnit="32 - 500 g boxes" UnitPrice="17.4500" UnitsInStock="29" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="17" Name="Alice Mutton" Supplier="Pavlova, Ltd." Category="Meat/Poultry" QuantityPerUnit="20 - 1 kg tins" UnitPrice="39.0000" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="18" Name="Carnarvon Tigers" Supplier="Pavlova, Ltd." Category="Seafood" QuantityPerUnit="16 kg pkg." UnitPrice="62.5000" UnitsInStock="42" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="19" Name="Teatime Chocolate Biscuits" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="10 boxes x 12 pieces" UnitPrice="9.2000" UnitsInStock="25" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="20" Name="Sir Rodney's Marmalade" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="30 gift boxes" UnitPrice="81.0000" UnitsInStock="40" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="21" Name="Sir Rodney's Scones" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="24 pkgs. x 4 pieces" UnitPrice="10.0000" UnitsInStock="3" UnitsOnOrder="40" ReorderLevel="5" />
  <Product ID="22" Name="Gustaf's Knäckebröd" Supplier="PB Knäckebröd AB" Category="Grains/Cereals" QuantityPerUnit="24 - 500 g pkgs." UnitPrice="21.0000" UnitsInStock="104" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="23" Name="Tunnbröd" Supplier="PB Knäckebröd AB" Category="Grains/Cereals" QuantityPerUnit="12 - 250 g pkgs." UnitPrice="9.0000" UnitsInStock="61" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="24" Name="Guaraná Fantástica" Supplier="Refrescos Americanas LTDA" Category="Beverages" QuantityPerUnit="12 - 355 ml cans" UnitPrice="4.5000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="25" Name="NuNuCa Nuß-Nougat-Creme" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="20 - 450 g glasses" UnitPrice="14.0000" UnitsInStock="76" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="26" Name="Gumbär Gummibärchen" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="100 - 250 g bags" UnitPrice="31.2300" UnitsInStock="15" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="27" Name="Schoggi Schokolade" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="100 - 100 g pieces" UnitPrice="43.9000" UnitsInStock="49" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="28" Name="Rössle Sauerkraut" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Produce" QuantityPerUnit="25 - 825 g cans" UnitPrice="45.6000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="29" Name="Thüringer Rostbratwurst" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Meat/Poultry" QuantityPerUnit="50 bags x 30 sausgs." UnitPrice="123.7900" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="30" Name="Nord-Ost Matjeshering" Supplier="Nord-Ost-Fisch Handelsgesellschaft mbH" Category="Seafood" QuantityPerUnit="10 - 200 g glasses" UnitPrice="25.8900" UnitsInStock="10" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="31" Name="Gorgonzola Telino" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="12 - 100 g pkgs" UnitPrice="12.5000" UnitsInStock="0" UnitsOnOrder="70" ReorderLevel="20" />
  <Product ID="32" Name="Mascarpone Fabioli" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="24 - 200 g pkgs." UnitPrice="32.0000" UnitsInStock="9" UnitsOnOrder="40" ReorderLevel="25" />
  <Product ID="33" Name="Geitost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="500 g" UnitPrice="2.5000" UnitsInStock="112" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="34" Name="Sasquatch Ale" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="14.0000" UnitsInStock="111" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="35" Name="Steeleye Stout" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="18.0000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="36" Name="Inlagd Sill" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="24 - 250 g  jars" UnitPrice="19.0000" UnitsInStock="112" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="37" Name="Gravad lax" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="12 - 500 g pkgs." UnitPrice="26.0000" UnitsInStock="11" UnitsOnOrder="50" ReorderLevel="25" />
  <Product ID="38" Name="Côte de Blaye" Supplier="Aux joyeux ecclésiastiques" Category="Beverages" QuantityPerUnit="12 - 75 cl bottles" UnitPrice="263.5000" UnitsInStock="17" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="39" Name="Chartreuse verte" Supplier="Aux joyeux ecclésiastiques" Category="Beverages" QuantityPerUnit="750 cc per bottle" UnitPrice="18.0000" UnitsInStock="69" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="40" Name="Boston Crab Meat" Supplier="New England Seafood Cannery" Category="Seafood" QuantityPerUnit="24 - 4 oz tins" UnitPrice="18.4000" UnitsInStock="123" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="41" Name="Jack's New England Clam Chowder" Supplier="New England Seafood Cannery" Category="Seafood" QuantityPerUnit="12 - 12 oz cans" UnitPrice="9.6500" UnitsInStock="85" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="42" Name="Singaporean Hokkien Fried Mee" Supplier="Leka Trading" Category="Grains/Cereals" QuantityPerUnit="32 - 1 kg pkgs." UnitPrice="14.0000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="43" Name="Ipoh Coffee" Supplier="Leka Trading" Category="Beverages" QuantityPerUnit="16 - 500 g tins" UnitPrice="46.0000" UnitsInStock="17" UnitsOnOrder="10" ReorderLevel="25" />
  <Product ID="44" Name="Gula Malacca" Supplier="Leka Trading" Category="Condiments" QuantityPerUnit="20 - 2 kg bags" UnitPrice="19.4500" UnitsInStock="27" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="45" Name="Rogede sild" Supplier="Lyngbysild" Category="Seafood" QuantityPerUnit="1k pkg." UnitPrice="9.5000" UnitsInStock="5" UnitsOnOrder="70" ReorderLevel="15" />
  <Product ID="46" Name="Spegesild" Supplier="Lyngbysild" Category="Seafood" QuantityPerUnit="4 - 450 g glasses" UnitPrice="12.0000" UnitsInStock="95" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="47" Name="Zaanse koeken" Supplier="Zaanse Snoepfabriek" Category="Confections" QuantityPerUnit="10 - 4 oz boxes" UnitPrice="9.5000" UnitsInStock="36" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="48" Name="Chocolade" Supplier="Zaanse Snoepfabriek" Category="Confections" QuantityPerUnit="10 pkgs." UnitPrice="12.7500" UnitsInStock="15" UnitsOnOrder="70" ReorderLevel="25" />
  <Product ID="49" Name="Maxilaku" Supplier="Karkki Oy" Category="Confections" QuantityPerUnit="24 - 50 g pkgs." UnitPrice="20.0000" UnitsInStock="10" UnitsOnOrder="60" ReorderLevel="15" />
  <Product ID="50" Name="Valkoinen suklaa" Supplier="Karkki Oy" Category="Confections" QuantityPerUnit="12 - 100 g bars" UnitPrice="16.2500" UnitsInStock="65" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="51" Name="Manjimup Dried Apples" Supplier="G'day, Mate" Category="Produce" QuantityPerUnit="50 - 300 g pkgs." UnitPrice="53.0000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="52" Name="Filo Mix" Supplier="G'day, Mate" Category="Grains/Cereals" QuantityPerUnit="16 - 2 kg boxes" UnitPrice="7.0000" UnitsInStock="38" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="53" Name="Perth Pasties" Supplier="G'day, Mate" Category="Meat/Poultry" QuantityPerUnit="48 pieces" UnitPrice="32.8000" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="54" Name="Tourtière" Supplier="Ma Maison" Category="Meat/Poultry" QuantityPerUnit="16 pies" UnitPrice="7.4500" UnitsInStock="21" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="55" Name="Pâté chinois" Supplier="Ma Maison" Category="Meat/Poultry" QuantityPerUnit="24 boxes x 2 pies" UnitPrice="24.0000" UnitsInStock="115" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="56" Name="Gnocchi di nonna Alice" Supplier="Pasta Buttini s.r.l." Category="Grains/Cereals" QuantityPerUnit="24 - 250 g pkgs." UnitPrice="38.0000" UnitsInStock="21" UnitsOnOrder="10" ReorderLevel="30" />
  <Product ID="57" Name="Ravioli Angelo" Supplier="Pasta Buttini s.r.l." Category="Grains/Cereals" QuantityPerUnit="24 - 250 g pkgs." UnitPrice="19.5000" UnitsInStock="36" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="58" Name="Escargots de Bourgogne" Supplier="Escargots Nouveaux" Category="Seafood" QuantityPerUnit="24 pieces" UnitPrice="13.2500" UnitsInStock="62" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="59" Name="Raclette Courdavault" Supplier="Gai pâturage" Category="Dairy Products" QuantityPerUnit="5 kg pkg." UnitPrice="55.0000" UnitsInStock="79" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="60" Name="Camembert Pierrot" Supplier="Gai pâturage" Category="Dairy Products" QuantityPerUnit="15 - 300 g rounds" UnitPrice="34.0000" UnitsInStock="19" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="61" Name="Sirop d'érable" Supplier="Forêts d'érables" Category="Condiments" QuantityPerUnit="24 - 500 ml bottles" UnitPrice="28.5000" UnitsInStock="113" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="62" Name="Tarte au sucre" Supplier="Forêts d'érables" Category="Confections" QuantityPerUnit="48 pies" UnitPrice="49.3000" UnitsInStock="17" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="63" Name="Vegie-spread" Supplier="Pavlova, Ltd." Category="Condiments" QuantityPerUnit="15 - 625 g jars" UnitPrice="43.9000" UnitsInStock="24" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="64" Name="Wimmers gute Semmelknödel" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Grains/Cereals" QuantityPerUnit="20 bags x 4 pieces" UnitPrice="33.2500" UnitsInStock="22" UnitsOnOrder="80" ReorderLevel="30" />
  <Product ID="65" Name="Louisiana Fiery Hot Pepper Sauce" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="32 - 8 oz bottles" UnitPrice="21.0500" UnitsInStock="76" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="66" Name="Louisiana Hot Spiced Okra" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="24 - 8 oz jars" UnitPrice="17.0000" UnitsInStock="4" UnitsOnOrder="100" ReorderLevel="20" />
  <Product ID="67" Name="Laughing Lumberjack Lager" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="14.0000" UnitsInStock="52" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="68" Name="Scottish Longbreads" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="10 boxes x 8 pieces" UnitPrice="12.5000" UnitsInStock="6" UnitsOnOrder="10" ReorderLevel="15" />
  <Product ID="69" Name="Gudbrandsdalsost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="10 kg pkg." UnitPrice="36.0000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="70" Name="Outback Lager" Supplier="Pavlova, Ltd." Category="Beverages" QuantityPerUnit="24 - 355 ml bottles" UnitPrice="15.0000" UnitsInStock="15" UnitsOnOrder="10" ReorderLevel="30" />
  <Product ID="71" Name="Flotemysost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="10 - 500 g pkgs." UnitPrice="21.5000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="72" Name="Mozzarella di Giovanni" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="24 - 200 g pkgs." UnitPrice="34.8000" UnitsInStock="14" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="73" Name="Röd Kaviar" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="24 - 150 g jars" UnitPrice="15.0000" UnitsInStock="101" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="74" Name="Longlife Tofu" Supplier="Tokyo Traders" Category="Produce" QuantityPerUnit="5 kg pkg." UnitPrice="10.0000" UnitsInStock="4" UnitsOnOrder="20" ReorderLevel="5" />
  <Product ID="75" Name="Rhönbräu Klosterbier" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Beverages" QuantityPerUnit="24 - 0.5 l bottles" UnitPrice="7.7500" UnitsInStock="125" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="76" Name="Lakkalikööri" Supplier="Karkki Oy" Category="Beverages" QuantityPerUnit="500 ml" UnitPrice="18.0000" UnitsInStock="57" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="77" Name="Original Frankfurter grüne Soße" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Condiments" QuantityPerUnit="12 boxes" UnitPrice="13.0000" UnitsInStock="32" UnitsOnOrder="0" ReorderLevel="15" />  
</Products>

Buat beberapa file JavaScript berikut

1. Divider.js

// Divider.js
function divider(value1, value2) {
    if (typeof (value1) == "number" && typeof (value2) == "number") {
        var result = value1 / value2;
        return result;
    } else {
        return null;
    }
}

2. Multiplier.js

// Multiplier.js
function multiplier(value1, value2) {
    if (typeof (value1) == "number" && typeof (value2) == "number") {
        var result = value1 * value2;
        return result;
    } else {
        return null;
    }
}

3. Default.js

// Default.js
$(document).ready(function () {
    $('#Multiplier').click(function () {
        var value1 = parseFloat($('#Value1').val());
        var value2 = parseFloat($('#Value2').val());
        $('#Result').val(multiplier(value1, value2));
    });
    $('#Divider').click(function () {
        var value1 = parseFloat($('#Value1').val());
        var value2 = parseFloat($('#Value2').val());
        $('#Result').val(divider(value1, value2));
    });
});

Ketiga file javascript file tersebut beserta jQuery akan digunakan dalam halaman default.aspx. Ganti halaman Default.aspx yang sudah dibuat oleh Visual Studio project template dengan code berikut.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <script type="text/javascript" src="Scripts/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="Scripts/multiplier.js"></script>
    <script type="text/javascript" src="Scripts/divider.js"></script>
    <script type="text/javascript" src="Scripts/Default.js"></script>
    <h2>
        Welcome to ASP.NET!
    </h2>
    <asp:ScriptManager runat="server" EnablePartialRendering="true">
    </asp:ScriptManager>
    <asp:Label runat="server" AssociatedControlID="PageListBox">Page:</asp:Label>
    <asp:DropDownList runat="server" ID="PageListBox" AutoPostBack="true" OnSelectedIndexChanged="PageIndexChanged" ></asp:DropDownList>
    <input type="text" name="Value1" id="Value1" value="1" />
    <input type="button" name="Muntiplier" id="Multiplier" value="x" />
    <input type="button" name="Divider" id="Divider" value="/" />
    <input type="text" name="Value2" id="Value2" value="1" />=
    <input type="text" name="Result" id="Result" value="" />
    <asp:UpdatePanel runat="server">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="PageListBox" />
        </Triggers>
        <ContentTemplate>
            <asp:GridView ID="ProductView" runat="server" AutoGenerateColumns="false" EnableSortingAndPagingCallbacks="False" AllowSorting="True">
                <Columns>
                    <asp:BoundField HeaderText="Name" DataField="Name" />
                    <asp:BoundField HeaderText="Supplier" DataField="Supplier" />
                    <asp:BoundField HeaderText="Category" DataField="Category" />
                    <asp:BoundField HeaderText="Quantity Per Unit" DataField="QuantityPerUnit" />
                    <asp:BoundField HeaderText="Unit Price" DataField="UnitPrice" />
                    <asp:BoundField HeaderText="Units In Stock" DataField="UnitsInStock" />
                    <asp:BoundField HeaderText="Units On Order" DataField="UnitsOnOrder" />
                    <asp:BoundField HeaderText="Reorder Level" DataField="ReorderLevel" />
                </Columns>
            </asp:GridView>
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Buat code behind untuk default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        private IEnumerable<Product> GetProducts()
        {
            var data = XDocument.Load(Server.MapPath("~/App_data/Products.xml"), LoadOptions.None);
            var q = from c in data.Descendants("Product")
                    select new Product
                    {
                        ID = int.Parse(c.Attribute("ID").Value),
                        Name = c.Attribute("Name").Value,
                        Supplier = c.Attribute("Supplier").Value,
                        Category = c.Attribute("Category").Value,
                        QuantityPerUnit = c.Attribute("QuantityPerUnit").Value,
                        UnitPrice = decimal.Parse(c.Attribute("UnitPrice").Value),
                        UnitsInStock = decimal.Parse(c.Attribute("UnitsInStock").Value),
                        UnitsOnOrder = decimal.Parse(c.Attribute("UnitsOnOrder").Value),
                        ReorderLevel = decimal.Parse(c.Attribute("ReorderLevel").Value)
                    };
            return q;
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                var products = GetProducts();
                PageListBox.Items.Clear();
                for (int i = 0; i < (int)(Math.Ceiling((double)products.Count() / 10)); i++)
                {
                    PageListBox.Items.Add(new ListItem((i + 1).ToString()));
                }
                ProductView.DataSource = products.Take(10);
                ProductView.DataBind();
            }
        }
        protected void PageIndexChanged(object sender, EventArgs e)
        {
            var products = GetProducts();
            int selectedPage = int.Parse(((DropDownList)sender).SelectedValue);
            ProductView.DataSource = products.Skip((selectedPage - 1) * 10).Take(10);
            ProductView.DataBind();
        }
    }
}

Analisis

Setelah semua kode disiapkan, buka halaman dengan browser. Saya gunakan Firefox dengan add-ons Firebug dan YSlow untuk menganalisis kinerja dari halaman yang dibuat.

image

Kita bisa lihat bahwa untuk membuka halaman untuk pertama kalinya membutuhkan waktu 6,53 detik. Kemudian saya akan cek untuk akses halaman untuk yang kedua kalinya dan seterusnya. Tekan menu Home untuk mengakses halaman itu kembali, hasilnya sebagai berikut.

image

Permintaan yang kedua jauh lebih cepat dari sebelumnya, yaitu hanya 4,16 detik. Mari kita analisis penyebab lambatnya permintaan yang pertama. Dilihat dari jumlahnya, akses yang pertama terdapat sebelas permintaan untuk membuka satu halaman; sedangkan akses yang kedua hanya ada enam permintaan. Hal ini disebabkan karena akses yang pertama akan mengambil semua file dari server. Sedangkan akses yang kedua beberapa file yang dibungkus oleh ScriptResource.axd dan WebResource.axd telah dicache di browser sehingga tidak diambil lagi.

Mari kita analisis lebih dalam dengan YSlow pada tab Components

image

Kita bisa lihat bahwa terdapat delapan (8) buah permintaan file javascript (JS) terlihat cukup lama. Browser akan mengunduh file JavaScript satu per satu karena adanya ketergantungan file JavaScript degan file JavaScript lainnya. Walaupun browser dapat mengunduh file tersebut secara bersamaan, namun server web hanya dapat melayani maksimal dua (2) permintaan dari user yang sama dalam waktu bersamaan. Ini membuat tanggapan (response) dari server menjadi lama. Pada permintaan yang kedua, sebagian dari file tersebut tidak diminta lagi pada akses yang kedua karena sudah ada di client (browser) sehingga lebih cepat.

Dengan data tersebut di atas, apa yang bisa kita lakukan? Kita bisa mencache semua file JavaScript dengan memasukkannya sebagai embeded resource sebagaimana JavaScript milik ASP.NET Ajax dan WebForms. Dengan cara tersebut dapat mempercepat permintaan yang kedua kalinya dan seterusnya, namun tetap lambat untuk permintaan yang pertama. Lalu apa yang bisa kita lakukan untuk mempercepat permintaan yang pertama? Dalam ASP.NET 4 terdapat fitur yang menarik yaitu penggabungan semua JavaScript menjadi satu file. Sebenarnya fitur ini telah ada dalam ASP.NET 3.5 SP1 namun di ASP.NET 4 terdapat pengembangan yang memungkinkan JavaScript milik WebForms diikutsertakan dalam paket kombinasi tersebut.

Tips 1: Gabungkan File-File JavaScript Menjadi Satu.

Dengan menggabungkan semua file JavaScript menjadi satu, tidak ada lagi permintaan bolak-balik dari client ke server. Kita praktekkan langsung dalam kode ASP.NET. Masukkan semua referensi JavaScript ke CompositeScript dalam ScriptManager.

<asp:ScriptManager runat="server" EnablePartialRendering="true">
    <CompositeScript>
        <Scripts>
            <asp:ScriptReference Assembly="System.Web" Name="WebForms.js" />
            <asp:ScriptReference Assembly="System.Web" Name="Menu.js" />
            <asp:ScriptReference Assembly="System.Web" Name="MenuStandards.js" />
            <asp:ScriptReference Name="MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Path="Scripts/jquery-1.3.2.min.js" />
            <asp:ScriptReference Path="Scripts/multiplier.js" />
            <asp:ScriptReference Path="Scripts/divider.js" />
            <asp:ScriptReference Path="Scripts/Default.js" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

Sekarang kita bisa lihat bahwa hanya ada empat permintaan ke server untuk menampilkan halaman yang sama. Dikarenakan jumlah permintaan lebih sedikit, waktu yang dibutuhkan untuk menampilkan halaman juga lebih singkat yaitu 3,96 detik. Bahkan lebih cepat dari permintaan kedua sebelumnya.

image

Sekarang kita cek untuk permintaan kedua.

image

Seluruh permintaan selesai hanya dalam waktu 2,27 detik. Suatu peningkatan kinerja yang luar biasa.

Dari CompositeScript tersebut, kita kombinasikan semua JavaScript yang ada dalam embeded resource maupun yang berupa file. Untuk yang berupa file kita dengan mudah dapat mengidentifikasinya, lalu bagaimana cara mengetahui embeded JavaScript apa saja yang kita gunakan? Pertama kita harus tahu assembly apa yang kita gunakan. Karena kita menggunakan WebForm dan ScriptManager otomatis kita menggunakan assembly System.Web dan System.Web.Extensions. Assembly System.Web menggunakan WebForms.js sebagai JavaScript utama sedangkan ScriptManager meng-embed MicrosoftAjax.js. Kedua javascript tersebut harus ada sebelum kita menggunakan control yang lain.

Untuk mengetahui JavaScript yang digunakan oleh control, kita klik pada Response tab pada Firebug untuk mendapatkan isi dari javascript. Berbekal informasi isi dari javascript, kita dapat mencari embeded resource dengan menggunakan Reflector. Buka reflector dan lihat pada assembly System.Web. Cari file javascript yang berkaitan dengan control yang kita gunakan kemudian klik ganda untuk melihat isinya. Jika isinya cocok, maka file tersebut yang kita masukkan dalam CompositeScript.

image

image

Adakah yang bisa dioptimalkan lagi? Untuk permintaan terhadap default.aspx masih membutuhkan waktu lebih dari 1 detik. Ketika kita bukan halaman default.aspx dengan lihat sumber (view source), kita dapatkan banyak kode yang jumlahnya cukup besar. Mari kita optimalkan isi dari default.aspx

image

Tips 2: Gunakan ViewState Seperlunya

Karena sifat dari web adalah stateless, ViewState digunakan untuk menjaga status dari halaman untuk digunakan di server. Setiap control yang dirender ke halaman selalu memiliki ViewState padahal tidak semuanya digunakan. Kita harus jeli mana yang kita gunakan dan mana yang tidak. Jika pada waktu postback, kita tidak memerlukan nilai dari control tersebut, kita tidak perlu menyimpan ViewState. Karena pada contoh ini kita hampir tidak memerlukan ViewState, kita bisa matikan semua ViewState kecuali DropDownList yang memang diperlukan untuk menentukan halaman berapa yang dibuka. Hasil dari optimasi adalah sebagai berikut.

image

Dari local komputer, perubahan tidak begitu berarti karena tidak ada latency terhadap jaringan. Yang jadi catatan di sini adalah ukuran file default.aspx yang didownload. Semula default.aspx berukuran 9,2 kini hanya berukuran 6,7; hemat 30% dari bandwidth. Lalu apa lagi yang bisa dioptimasi?

Tips 3: Manfaatkan Microsoft CDN untuk Situs Publik

Jika situs anda untuk konsumsi publis, CDN memberikan manfaat untuk mempercepat akses dengan memanfaatkan server CDN Microsoft yang tersebar di seluruh dunia. Pengunjung akan mendapatkan server CDN terdekat dengan tempat dia akses. Jika diakses dari Indonesia, kita akan mendapatkan server CDN yang ada di Singapore, jika diakses dari US maka akan download JavaScript dari US sehingga aplikasi kita akan lebih cepat diakses oleh pengunjung manapun.

Untuk memanfaatkan Microsoft CDN, set EnableCDN menjadi true pada ScriptManager

image

Selain mengeset property EnableCDN menjadi true, kita juga perlu mengeluarkan MicrosoftAjax.js dan MicrosoftAjaxWebForms.js dari CompositeScript. Jika tidak, kedua JavaScript tesebut akan tetap diambil dari local resource dan masuk dalam CompositeScript. Dengan setting EnableCDN kedua file tersebut akan diambil dari server Microsoft CDN. Selain kedua library tersebut, kita juga bisa memanfaatkan library lain yang sudah tersedia di CDN (Baik Microsoft CDN, Google CDN maupun server lain) seperti jQuery. Caranya dengan megeset lokasi CDN di Application_Start dalam Global.asax.

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    // map a simple name to a path
    ScriptManager.ScriptResourceMapping.AddDefinition("jQuery", new ScriptResourceDefinition
    {
        Path = "~/scripts/jquery-1.3.2.min.js",
        DebugPath = "~/scripts/jquery-1.3.2.js",
        CdnPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js",
        CdnDebugPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.js"
    });
}

Kode di atas mendefinisikan jQuery untuk lokasi di lokal dan CDN baik untuk versi debug maupun release.

Definisi tersebut yang kemudian digunakan di ScriptManager.

<asp:ScriptManager runat="server" EnablePartialRendering="true" 
    EnableViewState="False" LoadScriptsBeforeUI="False" EnableCdn="True">
    <Scripts>
        <asp:ScriptReference Name="jQuery" />
    </Scripts>
    <CompositeScript>
        <Scripts>
<%--
            <asp:ScriptReference Assembly="System.Web" Name="WebForms.js" />
            <asp:ScriptReference Assembly="System.Web" Name="Menu.js" />
            <asp:ScriptReference Assembly="System.Web" Name="MenuStandards.js" />
            <asp:ScriptReference Name="MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Path="Scripts/jquery-1.3.2.min.js" />
--%>                
            <asp:ScriptReference Path="Scripts/multiplier.js" />
            <asp:ScriptReference Path="Scripts/divider.js" />
            <asp:ScriptReference Path="Scripts/Default.js" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

Dari kode di atas, kita remark semua library yang akan kita ambil dari CDN. Semua library yang ada dalam assembly Microsoft ASP.NET sudah tersedia di Microsoft CDN. Library lainnya harus dimasukkan dalam Scripts di luar CompositeScript. Hasil akses dari kode yang sudah diubah sebagai berikut.

image

Terlihat bahwa waktu yang dibutuhkan lebih lama dari kode kita sebelumnya yang menggabungkan semua script menjadi satu. Hal ini wajar karena demo ini menggunakan komputer lokal sehingga akses jaringan jauh lebih cepat dibandingkan akses ke Internet. Kecepatan akan terasa sewaktu aplikasi sudah dihost di Internet.

Tips 4: Tempatkan Referensi Script di Bawah User Interface

image

Pada property ScriptManager, set nilai LoadScriptsBeforeUI menjadi False. Hal ini akan membuat referensi Script dirender sebelum tag penutup </body>. Hal ini membuat browser akan mendownload semua UI terlebih dahulu sebelum JavaScript sehingga halaman tampak lebih cepat tampil.

Tips 5: Gunakan Browser Cache

Penggunaan cache penting untuk mengurangi beban jaringan. Dengan menggunakan cache, browser tidaka akan mengambil halaman dari server lagi melainkan dari cache selama cache belum kadaluarsa. Cache hanya berlaku untuk HTTP GET sehingga ketika kita postback tetap akan mendapatkan data yang valid. Untuk memanfaatkan cache, cukup tambahkan directive OutputCache pada tiap page yang akan di-cache seperti contoh berikut.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%@ OutputCache Duration="86400" Location="Client" VaryByParam="None" %>    

Dalam contoh di atas, cache diset masa kadaluarsa selama satu hari. Halaman akan dicache selama sehari sehingga akan mengurangi beban server. Sebenarnya fungsi cache ini sudah ada sejak ASP.NET 2.0 dan masih valid sampai ASP.NET 4.0.

Demikian beberapa tips yang bisa meningkatkan kinerja aplikasi web kita. Semoga bermanfaat.


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

How to Make Our Website to be Ready for IE8

Today, I have email from Microsoft TechNet Flash about "how to get ready for IE8". It is challenge for me to make my blog ready for IE8. My blog have already XHTML 1.0 Transitional and CSS 2.1 compliance, but still reported as not ready for IE8 (see picture below).

image

What happen with my blog? IE8 have difference standard with W3C? After following link from TechNet flash email, the problem is: my blog have not META tag to tell IE8 that the page is ready for IE8 view. After apply X-UA-Compatible META tag in my BlogEngine theme, my blog is now comply with IE8.

image

Here’s requirement to be ready for IE8.

  1. Make sure your HTML markup is comply to HTML 4, XHTML 1.0 or XHTML 1.1 defined in doctype of the page. You can validate your page with online markup validation tools at http://validator.w3.org/
  2. Make sure your CSS is use at least CSS level 2.1 compliance. You can validate your page with online CSS validation tools at http://jigsaw.w3.org/css-validator/
  3. Place the following HTML META tag into the top of the HEAD element of each Web page (before tags other than TITLE or META):
    <meta http-equiv="X-UA-Compatible" content="IE=8"/>
    This will tell Windows Internet Explorer 8 to render each page using CSS 2.1 standards.

After HTML, CSS and HTML META has been applied, the page will ready for IE8.

References:

http://msdn.microsoft.com/en-us/ie/cc405106.aspx
http://msdn.microsoft.com/id-id/library/cc817570(en-us).aspx
http://msdn.microsoft.com/id-id/library/dd433047(en-us,VS.85).aspx
http://msdn.microsoft.com/id-id/library/cc817572(en-us).aspx


Categories: Tips | IE
Permalink | Comments (3) | Post RSSRSS comment feed

Parsing Array Parameter in SQL Server Stored Procedure

If we develop application to select multiple data in grid and selected data to be process in stored procedure at same time, we need to pass the values of keys to stored procedure parameters. The problem is SQL Server has not array parameter. Here is some ways to resolve the problem.

  1. Use EXEC to execute dynamic query and passing the stored procedure parameter in WHERE clause.
  2. 2. Use XML as parameter and using OPENXML keyword to convert it to table.

First option is vary simple but it bad practice to use dynamic query. SQL Server can’t save statistic of dynamic query. Second option is better way but more complicated. We need simplest way to passing an array to stored procedure parameter.

Other option we can create table function to parse delimited string to table. Here is sample function to do that.

CREATE FUNCTION [dbo].[fn_ParseDelimitedStrings](@String nvarchar(MAX), @Delimiter char(1))
RETURNS @Values TABLE
(
     RowId int Not Null IDENTITY(1,1) PRIMARY KEY
    ,Value nvarchar(255) Not Null
)
AS
BEGIN
    DECLARE  @startPos smallint
            ,@endPos smallint

    IF (RIGHT(@String, 1) != @Delimiter)
        SET @String = @String + @Delimiter
    SET @startPos = 1
    SET @endPos = CharIndex(@Delimiter, @String)
    WHILE @endPos > 0
        BEGIN
            INSERT @Values(Value)
            SELECT LTRIM(RTRIM(SUBSTRING(@String, @startPos, @endPos - @startPos)))
            -- remove the delimiter just used
            SET @String = STUFF(@String, @endPos, 1, '')
            -- move string pointer to next delimiter
            SET @startPos = @endPos
            SET @endPos = CHARINDEX(@Delimiter, @String)
    END
    RETURN
END

This function can be used in sample stored procedure below.

CREATE PROCEDURE GetCustomers 
    @customerIDs AS nvarchar
AS
BEGIN
    DECLARE @custIDs AS table (Value nvarchar(255) Not Null)
    INSERT INTO @custIDs
        SELECT Value FROM [fn_ParseDelimitedStrings](@customerIDs, ',') 
    SELECT * FROM Orders WHERE CustomerID IN (SELECT Value FROM @custIDs)
END

It very simple query. Just declare memory table and parse the delimited string into table to be used in select criteria.

I hope this tips is helpful for you.


Categories: SQL Server | Tips
Permalink | Comments (7) | Post RSSRSS comment feed

Resolving SQL BPA Command Line Problem when Running SQL Server 2005 Upgrade Advisor

Currently, I want to upgrade our SQL Server 2000 databases to SQL Server 2005. The first step is running Microsoft SQL Server Upgrade Advisor. I was installed this tool on my computer and no error in installation. When I running this tool and try to analyze database engine, it returning error message:

"SQL BPA command line has encountered a problem and needs to close. We are sorry for the inconvenience."

I confused about this error because I was use this tool a few year ago without any problems. What is the problem, my database, my account or the tool problem? I'm forget that used SQL Server 2005 Upgrade Advisor with Service Pack 1 that different with previous version that was used. I think it the tool problem. I'm try to look at the forum that any suggestions. One of the suggestions is to registering BPAClient.dll to the GAC. It resolve the problem for me.

To resolve this problem, follow the instructions below.

  1. Open Visual Studio 2005/2008 Command Prompt
  2. Change directory to C:\Program Files\Microsoft SQL Server\90\Setup Bootstrap\BPA\bin or based on your software installation path.
  3. Type following command:
    C:\Program Files\Microsoft SQL Server\90\Setup Bootstrap\BPA\bin>gacutil /i BPAClient.dll

I hope this information is helpful.


Categories: SQL Server | Tips
Permalink | Comments (4) | Post RSSRSS comment feed

Google Talk is Crashing when Changing Status to “Show current music track” using Winamp 5.5

Winamp is my favorite music player with classic theme. Winamp is very simple music player. I’m using winamp for MP3 and online radio streaming player. I wanna share my winamp track status in GTalk but it getting hang. Please follow the steps below to resolve the issue:

  1. Exit Winamp and Google Talk
  2. Open notepad, keep blank document. Note: you must run notepad in administrator mode (right click and run as administrator in Windows Vista).
  3. Save the blank file to %PROGRAMFILES%\Winamp\winamp.m3u or %PROGRAMFILES(X86)%\Winamp\winamp.m3u for x64 OS.
  4. Open Winamp and Google Talk again.

Now, you can change your GTalk status to “Show current music track” without causing hang.


Categories: Tips
Permalink | Comments (1) | Post RSSRSS comment feed

Change ComputerName Value on TFS Workspace Setting

A workspace, according to the VSTS help "Represents a client-side copy of the files in the repository that you want to work in." What that means is that the TFS server needs to know where to put the files on your local drive when you perform a Get operation; and you have to specify it, there are no defaults and the server will not guess the location. Notice that I said 'server', this information is tracked on the server.

Since workspace point to computer name, changing computer name on local PC will impact to workspace setting. 

image

Computer name value can't be change from the client software. The dialog was disabled on computer name as shown in picture below.

image

To change computer name in workspace setting, connect to TFS database (contact TFS administrator to do this if you are not an administrator). Please follow this steps:

  • Open TfsVersionControl database.
  • Execute query below to make sure workspace which to be updated.
    SELECT * FROM tbl_Workspace
    WHERE WorkspaceName='AMASYKUR'

    The result might be like picture below
    image
  • Update Computer field to new computer name.
  • UPDATE tbl_Workspace
    SET computer='NEWCOMPUTER'
    WHERE WorkspaceName='AMASYKUR'

I hope this trick is useful

 

Disclaimer : please be very careful when conducting this procedure. I am not responsible if your TFS data is messed up


Categories: Tips | TFS
Permalink | Comments (28) | Post RSSRSS comment feed

Membuat LivePath Effect dengan Inkscape

LivePath effect merupakan sebuah effect dari paduan banyak path sehingga menghasilkan garis-garis halus yang berjajar. Salah satu contoh LivePath effect seperti pada gambar berikut

image

Kita dapat membuat effect tersebut dengan berbagai macam tools pembuat graphic vector seperti Corel Draw. Dalam hal ini saya akan gunakan tools gratis yaitu InkScape (www.inkscape.org). InkScape sebenarnya adalah sebuah tool untuk menggambar graphic vektor SVG. Selain SVG dokumen yang dibuat dengan tool ini juga dapat disimpan dalam format XAML (Silverlight), PostScript, Enhanced Metafile (EMF), OpenDocument Drawing (ODG), dll.

Untuk membuat gambar seperti di atas, langkah pertama adalah membuat background. Background terdiri dari dua persegi empat dengan degradasi kuning keemasan. Kita buat kotak pertama dengan ukuran 620px x 70px. Isi kotak warna gradient dari atas ke bawah dengan gradient stop #fbf49eff (atas) dan #e0a71dff (bawah).

image

Kotak kedua dibuat dengan ukuran 620px x 15px yang diletakkan persis di bawah kotak pertama. Gradient untuk kotak kedua terdiri dari tiga gradient stop dari atas ke bawah #edcd5dff (posisi 0% / atas), #eddd5dff (posisi 20% / tengah) dan #fbf49eff (posisi 100% / bawah). Untuk membuat pemisah tipis antara kedua kotak, dibuat stroke thickness sebesar 0.5px dengan warna putih. Hasil dari kedua kotak tersebut seperti terlihat pada gambar berikut.

image

Langkah berikutnya adalah membuat livepath effect itu sendiri. Untuk pemisahkan antara background dengan livepath effect dibuat layer baru di atas background dengan nama LifePath. Selanjutnya buat dua garis sinus menggunakan freehand line tool dengan warna merah dan putih yang saling memotong satu sama lain. Buat tebal stroke untuk dua garis ini sebesar 0.5px dan opacity 0.5.

image 

Langkah terakhir membuat effect livepath dengan menggunakan efek interpolasi path. Pilih (select) kedua path, pada menu Effect, Generate from Path, pilih Interpolate.

image

Pada jendela Interpolate, isi Exponent = 0.0, Interpolation steps = 128, Interpolation method = 2, Duplicate endpaths = unchecked, Interpolate style = checked. Setelah semua nilai diisi, tekan tombol Apply.

image

Hasil akhir dari langkah-langkah di atas adalah seperti terlihat pada gambar berikut.

image

Anda bisa menggunakan metode ini untuk membuat header sebuah halaman web atau untuk pemanis di dalam halaman.

Source file Inkscape SVG dari tutorial ini dapat didownload di merdeka.zip (28.49 kb).

Semoga bermanfaat.


Permalink | Comments (5) | Post RSSRSS comment feed

JSON Serializer & Deserializer

Saya ingin berbagi sedikit tips mengenai JSON serializer dan deserializer yang ada di ASP.NET AJAX. Dengan menggunakan ASP.NET Ajax pertukaran data antara client (JavaScript) dengan server menjadi gampang banget. Kita tidak perlu lagi pake XMLyang rumit. Dengan JSON data mudah banget di-parse.

Contoh code di client (JS):

function getFilterData() { var dateFormat = '<%= HelpdeskSystem.DateFormat %>'; var filter = { instance: $get('<%= instanceList.ClientID %>').value, requestNo: $get('<%= requestNoTextBox.ClientID %>').value, category: $get('<%= categoryList.ClientID %>').value, itemCategory: $get('<%= itemAffectedList.ClientID %>').value, ticketGroup: $get('<%= ticketGroupList.ClientID %>').value, status: $get('<%= statusList.ClientID %>').value, requestType: $get('<%= typeList.ClientID %>').value, startDate: Date.parseLocale($get('<%= dateFromTextBox.ClientID %>').value, dateFormat), finishDate: Date.parseLocale($get('<%= dateToTextBox.ClientID %>').value, dateFormat), requestedFor: $get('requestedForEmployeeId').value, assigneeId: ($get('<%= assigneeForEmployeeId.ClientID %>') != null) ? $get('<%= assigneeForEmployeeId.ClientID %>').value : $get('<%= assigneeForEmployeeIdLabel.ClientID %>').innerHTML }; return Sys.Serialization.JavaScriptSerializer.serialize(filter); // Serialize object to JSON string }

Di server side (C#), tinggal di-deserialize. Dalam hal ini saya pake data JSON tersebut pada event CallBack Janus Grid:

protected void GridEX1_CustomCallBack(object sender, Janus.Web.Common.CustomCallBackEventArgs e) { System.Web.Script.Serialization.JavaScriptSerializer jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var edata = System.Web.HttpUtility.UrlDecode(e.EventData.ToString()); var data = jsSerializer.DeserializeObject(edata); // data selanjutnya di prosess di sini }

Simple banget.

Hasil deserialize object ketika debugging tersebut dapat dilihat seperti gambar di bawah.

image

Dari gambar tersebut, string JSON telah di-deserialize menjadi object (string, Date, dll). Mudah bukan?

Semoga bermanfaat.


Categories: ASP.NET AJAX | JavaScript | JSON | Tips
Permalink | Comments (4) | Post RSSRSS comment feed

Mencegah Print Screen Halaman Web

Hak Atas Kekayaan Intelektual (HAKI) dan Hak Cipta merupakan suatu hak yang harus ditegakkan. Susah-susah membuat tulisan berdasarkan hasil pemikiran sendiri, dengan mudah dalam sekejap dijiplak orang lain dan diaku sebagai hasil karya sendiri.
Sering kali dijumpai beberapa situs tidak bisa disalin halaman web-nya. Orang yang memang punya niat mencuri dengan berbagai cara tetep bisa menyalin isinya dengan cara print-screen, baik dengan tombol yang ada di keyboard maupun dengan software. Dalam tulisan ini akan saya akan membagi trik untuk mencegah tindakan print-screen terhadap halaman web yang kita buat.
Untuk mencegah tindakan print-scrint salah satunya adalah dengan cara menghilangkan isi clipboard secara berkala. Cara tersebut dapat dilakukan dengan script berikut.


function clearImage()
{
    r = window.clipboardData.clearData("Image");
}
ci = setInterval("clearImage()", 10);

Code tersebut akan menghapus data clipboard dengan type Image karena hasil print-screen akan disimpan di clipboard dalam bentuk image.
Catatan: Script ini hanya berjalan di Internet Explorer.
Untuk memastikan bahwa ini berjalan di IE dan tidak menimbulkan error di browser lain perlu adanya pengecekan terlebih dahulu. Script di atas dapat diubah menjadi.

function clearImage() {
    if (window.clipboardData) {
        r = window.clipboardData.clearData("Image");
    }
}
ci = setInterval("clearImage()", 10);

Script di atas saya dapatkan dari dendy=at=ins.co.id di milis PHPUG.
Semoga bermanfaat.


Categories: JavaScript | Tips
Permalink | Comments (27) | Post RSSRSS comment feed

Menambahkan Daftar Assembly Supaya Tampil di Dialog Add References Visual Studio

GACUTIL merupakan sebuah tool untuk mendaftarkan assembly ke Global Assembly Cache (GAC). Untuk mendaftarkannya ketik gacutil /i <nama file dll> seperti pada gambar berikut.

image

Dengan menambahkan assembly ke dalam GAC, dll tersebut dapat diakses oleh seluruh aplikasi yang ada dalam satu mesin. Jadi tidak perlu menyalin ke semua folder aplikasi yang dibuat.

Ada sedikit permasalahan ketika membuat aplikasi dengan reference ke GAC, dengan menggunakan GACUTIL assembly yang didaftarkan tidak otomatis muncul ke dalam dialog Add Reference Visual Studio seperti terlihat pada gambar berikut.

image

Berdasarkan informasi dari Mario -- teman satu kantor -- bahwa untuk memunculkan assembly yang didaftarkan di GAC di dialog Add Reference Visual Studio perlu menambahkan registry key. Buka registry editor dan tambahkan key di dalam HKLM\Software\Microsoft\.NETFramework\AssemblyFolders\ dengan nama sesuai dengan nama Assembly dengan value path assembly yang bersangkutan.

Contoh: Untuk menambahkan sebuah 3rd party library Kamoro.Library.ServerControlsLibrary, tambahkan key di dalam HKLM\Software\Microsoft\.NETFramework\AssemblyFolders\

Name: Kamoro Server Controls Library

Value: C:\Program Files\Kamoro\Controls\

image

Setelah key ditambahkan, restart Visual Studio dan assembly yang baru didaftarkan dapat dilihat di daftar assembly pada dialog Add Reference Visual Studio seperti yang terlihat pada gambar di bawah.

image 

Semoga bermanfaat.


Permalink | Comments (2) | Post RSSRSS comment feed