July 2010 - Posts

I’ll be there…

kejurnas_big

Ini adalah event besar yang sangat meriah dengan pagelaran kejuaraan pada semua sisi Merpati Putih:

  1. Kejuaraan Laga (versi Merpati Putih)
  2. Kejuaraan Seni
  3. Kejuaraan Power (pematahan benda keras)
  4. Kejuaraan Getaran (tutup mata, halang rintang, deteksi warna, tulisan, dan sekaligus power)

See yaaa….

Share this post: | | | |
Posted by agung | 1 comment(s)

Feel the power of HttpModule – Part 2

This second part will explore some nice technique which maybe useful for you.

When you work with HttpModule, you can interact with ASPX Page. But the question is, how do you control your Page life time inside your HttpModule? This is interesting, since you can refer to ANY object inside your ASPX Page and manipulate it. I repeat again, yes you can manipuate it!

Let’s try it!

  1. Create a new C# website in Visual Studio 2010 and name it as default. Choose Empty ASP.NET Web Site.
  2. Add new Web Form and name it as default. (Default.aspx)
  3. Add new class and name it MyModule.cs. Let VS2010 add into App_Code for you. Just confirm that. Your class skeleton is ready.
  4. Now, open your Default.aspx file and modify like below:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gridData" runat="server"></asp:GridView>
    </div>
    </form>
</body>
</html>

I only add one gridview.

Let’s add some data into gridview. Open your code behind and type this simple code (just like the first sample):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
 
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (! IsPostBack)
        {
            gridData.DataSource = GetData();
            gridData.DataBind();
 
        }
    }
 
    private DataTable GetData()
    {
        DataTable tb = new DataTable();
        tb.Columns.Add(new DataColumn("City", typeof(string)));
        tb.Columns.Add(new DataColumn("User", typeof(string)));
        tb.Columns.Add(new DataColumn("Phone", typeof(string)));
 
        string city = "";
 
        for (int i = 0; i < 9; i++)
        {
            if (i % 2 == 1)
            {
                city = "CIREBON";
            }
            else
            {
                city = "JAKARTA";
            }
 
            DataRow row = tb.NewRow();
            row["City"] = city;
            row["User"] = "User-" + i.ToString();
            row["Phone"] = i.ToString().PadLeft(2, '0');
 
            tb.Rows.Add(row);
        }
 
        tb.DefaultView.Sort = "City ASC";
        return tb.DefaultView.Table;
 
    }
}

The result is just like this:

08

Now, let’s make the nice one. ;) Open your MyModule.cs and type this code:

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5: using System.Configuration;
   6:  
   7: /// <summary>
   8: /// Summary description for NotificationModule
   9: /// </summary>
  10: public class MyModule : IHttpModule
  11: {
  12:     public MyModule()
  13:     {
  14:         //
  15:         // TODO: Add constructor logic here
  16:         //
  17:     }
  18:  
  19:     public void Dispose()
  20:     {
  21:         // do nothing.
  22:     }
  23:  
  24:     public void Init(HttpApplication context)
  25:     {
  26:         context.PreRequestHandlerExecute += (sender, e) =>
  27:         {
  28:             var handler = context.Context.CurrentHandler;
  29:  
  30:             if (handler != null && handler is System.Web.UI.Page)
  31:             {
  32:                 System.Web.UI.Page currentPage = (System.Web.UI.Page)handler;
  33:  
  34:                 currentPage.Load += (source, args) =>
  35:                 {
  36:  
  37:                     System.Web.UI.WebControls.GridView gv = ((System.Web.UI.Page)source).FindControl("gridData") as System.Web.UI.WebControls.GridView;
  38:                     gv.Caption = "<b>This Caption injected from HttpModule!</b>";
  39:  
  40:                 };
  41:             }
  42:         };   
  43:     }
  44: }

Watch the line 34 until 40. I type the Page_Load event with Lambda expression. You can change this behavior by using event initialization as usual by pressing TAB twice after you type +=.

In the Page_Load event, I’ve got the reference ID of gridData from existing page that I want to inject some functionality. Then set the Caption property by something (this is only to show that I’ve changed the gridView). I will explain it later.

Now, save it by pressing CTRL+S.

Open your web.config file, then add new httpModule tag section inside <system.web>. This is the complete web.config:

<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0"/>
        <httpModules>
            <add name="MyModule" type="MyModule"/>
        </httpModules>
    </system.web>
</configuration>

Just beware about the type attribute of httpModule tag section. If you use Namespace, so you have to type it with this pattern:

<add name=”MyModule” type=”MyNamespace.MyModule, MyNamespace” />

Save it by pressing CTRL+S.

Just build your project, and run your Default.aspx.

The result it like below:

09

See that? :D

By using HttpModule, you can control your page based on your need. You just only have to know the ID of the control which you want to manipulate. And do it inside HttpModule. No need to recompile existing pages.

Let’s add advance scenario. Suppose your IT manager want you to add new information inside existing gridview about something (or anything), and you have to add new column in your gridview to show that information.

Ok, stop talking. Just open your MyModule.cs then modify your Init method with code at line 17:

   1: public void Init(HttpApplication context)
   2:     {
   3:         context.PreRequestHandlerExecute += (sender, e) =>
   4:         {
   5:             var handler = context.Context.CurrentHandler;
   6:  
   7:             if (handler != null && handler is System.Web.UI.Page)
   8:             {
   9:                 System.Web.UI.Page currentPage = (System.Web.UI.Page)handler;
  10:  
  11:                 currentPage.Load += (source, args) =>
  12:                 {
  13:  
  14:                     System.Web.UI.WebControls.GridView gv = ((System.Web.UI.Page)source).FindControl("gridData") as System.Web.UI.WebControls.GridView;
  15:                     gv.Caption = "<b>This Caption injected from HttpModule!</b>";
  16:  
  17:                     gv.RowCreated += new System.Web.UI.WebControls.GridViewRowEventHandler(gv_RowCreated);
  18:  
  19:                 };
  20:             }
  21:         };   
  22:     }
  23:  
  24:     void gv_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
  25:     {
  26:         if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
  27:         {
  28:             System.Web.UI.WebControls.TableCell tc = new System.Web.UI.WebControls.TableCell();
  29:  
  30:             tc.Controls.Add(new System.Web.UI.LiteralControl("<span style=\"background-color: Yellow\"><b>Inject from HttpModule.</b></style>"));
  31:  
  32:             e.Row.Controls.Add(tc);
  33:         }
  34:     }

and your implementation of RowCreated event is in line 24 until 34.

And this is all the code for MyModule.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
 
/// <summary>
/// Summary description for NotificationModule
/// </summary>
public class MyModule : IHttpModule
{
    public MyModule()
    {
        //
        // TODO: Add constructor logic here
        //
    }
 
    public void Dispose()
    {
        // do nothing.
    }
 
    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += (sender, e) =>
        {
            var handler = context.Context.CurrentHandler;
 
            if (handler != null && handler is System.Web.UI.Page)
            {
                System.Web.UI.Page currentPage = (System.Web.UI.Page)handler;
 
                currentPage.Load += (source, args) =>
                {
 
                    System.Web.UI.WebControls.GridView gv = ((System.Web.UI.Page)source).FindControl("gridData") as System.Web.UI.WebControls.GridView;
                    gv.Caption = "<b>This Caption injected from HttpModule!</b>";
 
                    gv.RowCreated += new System.Web.UI.WebControls.GridViewRowEventHandler(gv_RowCreated);
 
                };
            }
        };   
    }
 
    void gv_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
    {
        if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
        {
            System.Web.UI.WebControls.TableCell tc = new System.Web.UI.WebControls.TableCell();
 
            tc.Controls.Add(new System.Web.UI.LiteralControl("<span style=\"background-color: Yellow\"><b>Inject from HttpModule.</b></style>"));
 
            e.Row.Controls.Add(tc);
        }
    }
}

Save it by pressing CTRL+S. And hit again your browser with F5. The result will be like this:

10

Now, you have complete control of gridview in a page and manipulating using HttpHandler. You can, for example, add new rich functionality without even touching the page itself. Controlling other webcontrols, adding another service layer, etc etc…

Yes, you can add functionality by using JavaScript in your existing page. But you have to touch the page itself. But by using HttpModule, you are free to modify what you want without touch the page.

See yaaa…

Share this post: | | | |
Posted by agung | 1 comment(s)

Another Grouping Approach For ListView

I believe that you already know about how to make grouping in ListView. That’s the new feature in ListView to help you grouping data which you want to present to web. But sometimes, you don’t get it and not easy to implement. I will show you another approach on how you do grouping data inside a ListView control.

Let say you have a data query like this:

City User Phone
CIREBON User-1 01
CIREBON User-2 02
CIREBON User-3 03
CIREBON User-4 04
CIREBON User-5 05
JAKARTA User-6 06
JAKARTA User-7 07
BANDUNG User-8 08
BANDUNG User-9 09

Those dummy data maybe vary and different than yours. But I believe you got my point.

Ok, let’s we make another approach for grouping in ListView.

  1. Open your Visual Studio 2010, and create a new website.
  2. Choose Empty ASP.NET Web Site. And let the default name (or change it whatever you like).
  3. Add a new web form (Default.aspx).
  4. Inside your new web form (Default.aspx) HTML editor, press F7 to go into code behind.
  5. And type this code:
protected void Page_Load(object sender, EventArgs e)
    {
        if (! IsPostBack)
        {
            lvData.DataSource = GetData();
            lvData.DataBind();
        }
    }

Then in GetData() method, type like this:

private DataTable GetData()
    {
        DataTable tb = new DataTable();
        tb.Columns.Add(new DataColumn("City", typeof(string)));
        tb.Columns.Add(new DataColumn("User", typeof(string)));
        tb.Columns.Add(new DataColumn("Phone", typeof(string)));
 
        string city = "";
 
        for (int i = 0; i < 9; i++)
        {
            if (i % 2 == 1)
            {
                city = "CIREBON";
            }
            else
            {
                city = "JAKARTA";
            }
 
            DataRow row = tb.NewRow();
            row["City"] = city;
            row["User"] = "User-" + i.ToString();
            row["Phone"] = i.ToString().PadLeft(2, '0');
 
            tb.Rows.Add(row);
        }
 
        return tb;
 
    }

I will explain it in short. First, I create a GetData() method. It’s just for getting data from your database process. I use DataTable to simulate dummy data only. The datatable consist of three columns.

I will add ten records and for every records which MOD 2 for looping variable is equal to 1, I put “CIREBON” as city, otherwise “JAKARTA”. Then add the new row into datatable. The last is I returning back into code caller in Page_Load.

Then, open your Default.aspx file. And type this code:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ListView ID="lvData" runat="server">
        <LayoutTemplate>
            <table border="1" cellpadding="4" cellspacing="0">
                <tr>
                    <th>City</th>
                    <th>User</th>
                    <th>Phone</th>
                </tr>
                <tr id="itemPlaceHolder" runat="server"></tr>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <tr>
                <td><%# Eval("City") %></td>
                <td><%# Eval("User") %></td>
                <td><%# Eval("Phone") %></td>
            </tr>
        </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

Save it by pressing CTRL+S.

Open your Default.aspx in your browser, and this is the result.

03

Watch the data. We have to sort the data in order to make a good order.

Let’s modify the code to add sort in datatable.

private DataTable GetData()
{
    DataTable tb = new DataTable();
    tb.Columns.Add(new DataColumn("City", typeof(string)));
    tb.Columns.Add(new DataColumn("User", typeof(string)));
    tb.Columns.Add(new DataColumn("Phone", typeof(string)));
 
    string city = "";
 
    for (int i = 0; i < 9; i++)
    {
        if (i % 2 == 1)
        {
            city = "CIREBON";
        }
        else
        {
            city = "JAKARTA";
        }
 
        DataRow row = tb.NewRow();
        row["City"] = city;
        row["User"] = "User-" + i.ToString();
        row["Phone"] = i.ToString().PadLeft(2, '0');
 
        tb.Rows.Add(row);
    }
 
    tb.DefaultView.Sort = "City ASC";
    return tb.DefaultView.Table;
 
}

The sort mechanism is on the the last line before returning value. Save again by pressing CTRL+S. Then hit the browser by pressing F5. The result should be like this:

04

Now, this is what we want. The City column sorted ascending. Let’s make a grouping.

Open your Default.aspx again, and then add this code below <ItemTemplate> tag:

<%# GroupingRow() %>

So the complete code for Default.aspx will be like this:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ListView ID="lvData" runat="server">
        <LayoutTemplate>
            <table border="1" cellpadding="4" cellspacing="0">
                <tr>
                    <th>City</th>
                    <th>User</th>
                    <th>Phone</th>
                </tr>
                <tr id="itemPlaceHolder" runat="server"></tr>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <%# GroupingRow() %>
            <tr>
                <td><%# Eval("City") %></td>
                <td><%# Eval("User") %></td>
                <td><%# Eval("Phone") %></td>
            </tr>
        </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

The GroupingRow() is a method. You have to create implementation in your code behind. So open your code behind and type this code:

private string LastCity = "";
    protected string GroupingRow()
    {
        string CurrentCity = Eval("City").ToString();
 
        if (LastCity != CurrentCity)
        {
            LastCity = CurrentCity;
 
            return String.Format("<tr><td colspan=\"3\">{0}</td></tr>", CurrentCity);
        }
        else
        {
            return string.Empty;
        }
    }

Then save by pressing CTRL+S. Now, hit again your browser by pressing F5. The result will be like this:

05

Now, your grouping data is work. :)

The last is we have to make it like 'real’ grouping by removing ‘CIREBON’ and ‘JAKARTA’ string below the grouping line. It’s easy to do. Just open your Default.aspx, then remove the line which contains <%# Eval(“City”) %>. And for the next <td>, change it to <td colspan=”2”>.

The complete code for Default.aspx will be like this:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ListView ID="lvData" runat="server">
        <LayoutTemplate>
            <table border="1" cellpadding="4" cellspacing="0">
                <tr>
                    <th>City</th>
                    <th>User</th>
                    <th>Phone</th>
                </tr>
                <tr id="itemPlaceHolder" runat="server"></tr>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <%# GroupingRow() %>
            <tr>
                <td colspan="2">&nbsp;&nbsp;&nbsp;<%# Eval("User") %></td>
                <td><%# Eval("Phone") %></td>
            </tr>
        </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

06

This is exactly what we want! :)

You can change the color and layout by using CSS technique, or maybe you want to add expand-collapse button by using JavaScript code. It’s up to you now. :)

See yaaa…

Share this post: | | | |
Posted by agung | 1 comment(s)

The winner of World Soccer 2010 is ……..?

This is interesting:

  1. Brazil won 1994; before that they also won in 1970. 1970 + 1994 = 3964
  2. Argentina won 1986; before that they also won in 1978. 1978 + 1986 = 3964
  3. Germany won 1990; before that they also won in 1974. 1974 + 1990 = 3964
  4. Brazil won 2002; before that they also won in 1962. 1962 + 2002 = 3964
  5. How about 2010? Perhaps the formula is: 3964 - 2010 = 1954

The question is .. who is the winner in 1954?

Germany!

Heheehehe…

Share this post: | | | |
Posted by agung | 3 comment(s)

Feel the power of HttpModule

In my previous post, I have found something interesting when doing join project with a company and share that interesting things to you. Hopefully it can helps you in your development.

Yesterday, the IT manager want me to add notification functionality in an ASP.NET 2.0 application. Since the application contains more than 50 pages, I can’t suddenly write some code in their project and then do the recompilation. No, I won’t.

To make the notification information available in every pages, some of approaches are:

  • Make a service layer (WCF or WebService) and consume it with JavaScript code. The JavaScript code would reside IN EVERY pages. So I have to copy the JavaScript code in every pages. This is awkward and painful. :( Even if I put the code inside .JS, but the code still have to copy in every pages.
  • Modify the pages, and add custom code. I have to recompile again. This is not a good choice.

Those approaches is not good.

Because I know how ASP.NET pipeline work, then I already ‘gotcha’ that I have to create custom HttpModule. This solution is elegant, since I don’t have to touch their code and even their pages. :)

Technically, HttpModule is just a class which you can inherits from IHttpModule interface. So, let’s explore in depth.

  1. Create a new C# website in Visual Studio 2010 and name it as default. Choose Empty ASP.NET Web Site.
  2. Add new Web Form and name it as default. (Default.aspx)
  3. Add new class and name it NotificationModule.cs. Let VS2010 add into App_Code for you. Just confirm that. Your class skeleton is ready.
  4. Now, open your Default.aspx file and modify like below:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h1>This is Default.aspx</h1>
        <asp:GridView ID="gridData" runat="server"></asp:GridView>
    </div>
    </form>
</body>
</html>

Press F7 to go into code behind, and modify like below (or change the code whatever you like):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (! IsPostBack)
        {
            string[] names = { "Agung", "Akbar", "Ayu", "Bayu", "Taufan" };
 
            gridData.DataSource = names;
            gridData.DataBind();
        }
    }
}

Go to your NotificationModule.cs, and implement the Init method.

public void Init(HttpApplication context)
{
    context.BeginRequest += (sender, e) =>
    {
        context.Response.Write("BeginRequest ... executed<br />");
    };
 
    context.EndRequest += (sender, e) =>
    {
        context.Response.Write("EndRequest ... executed<br />");
    };
}

Now, we explore the BeginRequest and EndRequest method. How this method work? Just compile and run the Default.aspx. You will understand based on the result. :)

Note that I used Lambda Expression because of the simple implementation. You can use event handler by pressing TAB button twice after you type +=  to write complex codes.

Then, save it by pressing CTRL+S.

Open your web.config file and put this in <system.web> section:

<httpModules>
    <add name="NotificationModule" type="NotificationModule" />
</httpModules>

Just beware that the type attribute. The type attribute should in this format:

type=”Namespace.ClassName, Namespace”

So, if you put your class inside MyCompany namespace, then you should type like this:

type=”MyCompany.NotificationModule, MyCompany”

The last is, just open your Default.aspx in a web browser. The result will be like this (or depends on what you typed):

01

See the execution of BeginRequest and EndRequest? That’s the place where you want to put something in your application. :)

You don’t have to recompile all the pages, you don’t have to touch the pages itself.

Not only that, you can also override the Page_Load functionality or the other event in Page events by using PreRequestHandlerExecute. :)

Let’s modify it again.

Open your NotificationModule.cs and add this code inside Init method:

context.PreRequestHandlerExecute += (sender, e) =>
        {
            var handler = context.Context.CurrentHandler;
            if (handler != null && handler is System.Web.UI.Page)
            {
                System.Web.UI.Page currentPage = (System.Web.UI.Page)handler;
 
                currentPage.Load += (source, args) =>
                {
                    System.Web.UI.WebControls.Literal lit = new System.Web.UI.WebControls.Literal();
                    lit.Text = "<b>This is injecting in HttpModule</b><br /><br />";
 
                    ((System.Web.UI.Page)source).Controls.Add(lit);
 
                };
            }
        };

First, I put the CurrentHandler inside handler variable reference to make it reusable.

Then, I have to check if handler is not null and handler is Page. Yes, you can cast handler whatever you want (if any and available). The CurrentHandler will return a Page class. Look at the breakpoint below:

07

Then the handler itself I cast into System.Web.UI.Page. The last is I make the Load event available to modify by enabling currentPage.Load event.

Remember, in this event, you can’t inject web user control or user control because the PreRequestHandlerExecute would not create viewstate, so just only literal HTML (plain old HTML allowed). Yes, this is the limitation. But, you can extend it by, let say, consume another service layer like WCF or WebService.

This is the complete code inside Init method:

public void Init(HttpApplication context)
{
    context.BeginRequest += (sender, e) =>
    {
        context.Response.Write("BeginRequest ... executed<br />");
    };
 
    context.EndRequest += (sender, e) =>
    {
        context.Response.Write("EndRequest ... executed<br />");
    };
 
    context.PreRequestHandlerExecute += (sender, e) =>
    {
        var handler = context.Context.CurrentHandler;
        if (handler != null && handler is System.Web.UI.Page)
        {
            System.Web.UI.Page currentPage = (System.Web.UI.Page)handler;
 
            currentPage.Load += (source, args) =>
            {
                System.Web.UI.WebControls.Literal lit = new System.Web.UI.WebControls.Literal();
                lit.Text = "<b>This is injecting in HttpModule</b><br /><br />";
 
                ((System.Web.UI.Page)source).Controls.Add(lit);
 
            };
        }
    };
 
    context.PostRequestHandlerExecute += (sender, e) =>
    {
        context.Response.Write("PostRequestHandlerExecute ... executed<br />");
    };
 
}

Save it by pressing CTRL+S. And refresh the browser with F5. You will see the result:

02

You can put custom code and do whatever you like. :)

Hope this help.

See ya…

Share this post: | | | |
Posted by agung | 1 comment(s)

Fixing SQL query for getting last record in a table

In my last joined project, I have a responsibility for refactoring codes. And I found an interesting things of this kind of sql query for getting last record in a table who created by previous programmer:

string sql = “SELECT MAX(HistoryId) FROM tblActivityHistory WHERE RefId=” + id;

int maxId = …. execute the sql command, and returning int …

// construct again

sql = “SELECT [Action] FROM tblActivityHistory WHERE HistoryId=” + maxId.ToString();

string result = … execute the sql command, and returning string …

I think, calling twice will hit performance and no need to do that. If you created that kind of sql query, then you should replace with the simple query like below:

string sql = “SELECT TOP 1 [Action] FROM tblActivityHistory WHERE RefId=” + id + “ ORDER BY HistoryId DESC”;

You can use SqlParameter or String.Format to replace parameter for better security.

Hope this help.

Share this post: | | | |
Posted by agung | 2 comment(s)

Handling NULL value from database [is|always] tricky …

Yes, even if .NET Framework provide nullable data type, but handling the null value from database is always tricky.

The first approach is using like this:

var reader = GetDataReader();
 
if (reader.HasRows)
{
    int id = 0;
    string firstname = "";
    double sallary = "";
 
    while(reader.Read())
    {
      // since id is autonumber, so the value will not null
          id = Convert.ToInt32(reader["id"].ToString());
 
          if (reader["firstname"] != DBNull.Value) 
        firstname = Convert.ToInt32(reader["firstname"].ToString());        
 
          if (reader["sallary"] != DBNull.Value) 
        sallary = Convert.ToInt32(reader["sallary"].ToString());        
    }
}

We have to check with DBNull.Value. We can't use null because DBNull.Value != null

Another approach is by using nullable datatype. So the code above can be modified like below:

var reader = GetDataReader();
 
if (reader.HasRows)
{
    int id = 0;
    string? firstname = "";
    double? sallary = "";
 
    while(reader.Read())
    {
      // since id is autonumber, so the value will not null
          id = Convert.ToInt32(reader["id"].ToString());
 
          firstname = Convert.ToInt32(reader["firstname"].ToString());        
 
          sallary = Convert.ToInt32(reader["sallary"].ToString());        
    }
}

This nullable datatype is useful for us. But how if you don't have nullable datatype (for example, your company using old .NET Fx which doesn't provide nullable datatype?).
Then you have to write your own function. This small code will help you to provide null handling when retrieving null value in database and store it in a variabel.

public static class Null
{
   public static T Get<T>(object data)
   {
       T obj = default(T);
 
       return (data != DBNull.Value ? (T)data : obj);
   }
}
 

Let me explain in short about Null class. Get method will return T (it depends on your datatype which you declared in the method). If you declare as Null.Get<int>() then the return value will be int. If you declare as Null.Get<double>(), then the return value will be double.

Then the Get method accept one parameter with object data type.

Inside Get method, you declare a variabel with type of T (again, the T will depends on your data type which you declared). And provide default value based on your data type which you declare. So, for example, if you declare as int then the code will produce like this:

int obj = default(int);

Which means the default value of int is 0.

If you declare as string, then the code will produce like this:

string obj = default(string);

Which means the default value of string is null.

If you declare as DateTime, then the code will produce like this:

DateTime obj = default(DateTime);

Which means the default value of DateTime is 1/1/0001 (in short).

And so on.

Then the last line is for check if the object parameter is not equal to DBNull.Value. If so, then convert the parameter into T (depends on your need), otherwise just return the default value of declared data type.

That’s it. Hopefully you understand.

Call the Get method like below:

var reader = GetDataReader();
 
if (reader.HasRows)
{
    int id = 0;
    string firstname = "";
    double sallary = "";
 
    while(reader.Read())
    {
          id = Null.Get<int>(reader["id"]);
          firstname = Null.Get<string>(reader["firstname"]);        
          sallary = Null.Get<double>(reader["sallary"]);        
    }
}

You can modified that small code and make it Extension Method in your .NET class library.

Cheerss...

Share this post: | | | |
Posted by agung | with no comments