Google Cloud Print, Save My Day

Today, after installing the new Google Chrome browser into version 10, I’ve found some ‘small’ utility that very useful. The Google Cloud Print can save your day by allowing printing in your office from your location, any location. You can access your printers from any smart phone or computer, review your print jobs and printer status online. You can also share and control access to your printers with any Google account.

Imagine, if you need to print some documents from home, or from your daily activity, from anywhere. Just tested it by using other PC in other office and by using my smartphone. All works like a charm! Thanks to Google. :)

1) Download the latest Chrome browser (10.0.648.151)

00

2) Go to Tools –> Options, to enable Google Cloud Print in your computer

06

I’ve been enable my Google Cloud Print. If you did not enabled your Google Cloud Print, just click on Enable Google Cloud Print

3) By clicking Enable Google Cloud Print, you will be redirected to Sign In with you Google account.

01

4) By clicking Sign In button, Google will try to resolve your printer settings in your local computer. Just wait a second, make sure Google resolve your printer list in your computer. If you have printer connected in your computer, then the registration process will be succeed. Google will give you this message:

02

5) Click Print a Test Page button to make sure your printer settings resolved correctly. This is the print test page from Google in your paper:

img327

6) You can see your printer settings in your Chrome. You can see your print jobs, and all available printers in your computer.

04

7) When you trying to print from Google account in your web page (Google Docs or other Google services), you will see like this:

05

Just choose your printer which connected in your computer, do some settings (if needed), and click on Print button.

8) That’s it. You’re now using Google Cloud Print services.

 

PS: I’ve also trying to print using my smart phone without problem. Thank you Google for saving my day.

 

- AR -

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

Goodbye VB.NET ... DotNetNuke Now Switches to C#

"So without any further ado… I am pleased to announce that we decided to switch development languages for the core platform from VB.NET to C# !!

We are already in the process of performing QA on the converted C# code base and we expect to make the new C# platform available with the upcoming DotNetNuke 6.0 release which is currently scheduled to be released sometime during the second quarter of 2011. In the coming weeks a DotNetNuke 6.0 Community Technology Preview will be published which will provide early access to the product for the purpose of cultivating open source community participation to help us ensure the stability of the C# code base.

It goes without saying that this is a very significant change for us and our ecosystem, and the decision was only made after extensive research and deliberation.", said Shaun Walker.

Why they move to C#? This is the reason:

"You will notice that none of the reasons above mention that VB.NET is inferior to C# from a technical perspective. This is a very important point, as we don’t want people to get the impression that we are switching languages because there are any technical deficiencies in VB.NET. VB.NET is just as robust and powerful as C# from a design-time, compile-time, and run-time perspective and it has served us extremely well over the past 8 years. The reasons why we are moving to C# at this juncture are 100% business related."

(source: http://www.dotnetnuke.com/Resources/Blogs/tabid/825/EntryId/2978/DotNetNuke-Embraces-C.aspx)

***

Long live C#, good bye VB.NET, DotNetNuke Now Switched To C#. :)

 

DotNetNuke <3 C# !!


 

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

Pencak Silat World Championship 2010

Mari kita sukseskan Kejuaraan Pencak Silat Dunia 2010 yang bertempat di:

Padepokan Pencak Silat Taman Mini Indonesia Indah (TMII)

Pencak Silat World Championship  Undangan

Press 

 

Mari kita sukseskan!

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

Teaching C# for newbie

This is another session about teaching C# for newbie. Especially who wants to join in real development. One question that I always heard was "why we don't get something like this in our university?". I think the answer is depends on situation and condition.

Teaching about layering, teaching about services, and something more real in development will not got in the university. Students should learn from other way (eg. internet or take a private lesson).

Some of university in my area (Cirebon), teaching C# without understanding what C# is! The teacher didn't have any experience at all about C# but very brave to teach it in many classes!. The final paper of student about using C# is rejected! How stupid they are!!!

Fyuuh...

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

EF4 helping boost your application development

Today, my team just finished a newest project to developed a part of intranet system using C#. We used EF4 and I’m really happy with it’s performance. Trying to process more than 1 million record, filtering, sorting, by using their built in functionality are amazing…

ef01

ef02

The most interesting is development time can be shorten by using EF4.

If you have a nice and solid database design, then using EF4 is really easy and helpful…

cheer…

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

Nice to meet you, Raven!

Actually, this is blessing when I met a new project which produce simple (really simple, but yet huge) application in web page by using another approach in how we present data in the application.

Sometimes, we stuck in how we design a relational database to decide how many tables should we have to created. And sometimes, in the beginning of the project, creating a prototype sometimes will be different in making the implementations. For example, you can create a prototype by using MongoDB, or some of in-memory or flat database engine, and then after your client agree about your prototype, you switch back to relational database like SQL Server. This approach is common in real complex project situation.

How if we can structured an application without structuring like relational database? If you want to do that, pleas meet RavenDB and you will love it!. This is nice and very interesting indeed. This kind of database engine won't make you switch from relational to un-relational. Just use it, and feel the different taste. In a minute, you will know about the power of it.

Maybe this is one of the kind of your web page design (taken from Raven's documentation):

When you see that mockup, what is in your mind? Yes, you think about how many tables you have to created and how the relationship between them. In a relational database, you would have to touch no less than 4 tables to show the data in this single page (Posts, Comments, Tags, RelatedPosts). Using Raven, you can store all the data that you need to work with as a single document with the following format:

This format allows us to get everything that we need to display the page shown above in a single request. No need to create 4 tables, no need to choose primary key column, foreign key column, and etc. Forget it. Just represent your page in single document, and you can add anything in it. Very flexible and yet powerful in terms of simplicity. Yes, I know this is unstructured. But yet powerful.

I have successfully create one of application for my client using RavenDB. Yes, I know there are some limitation by using it. But actually, this is great and really have fun to use it.

Try it and say ... nice to meet you ... Raven!

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

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 | 2 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

Creating the new one is more easy than enhancing the existing one

Now, I’m joining with a huge and complex intranet project (a collaboration between ASP classic, ASP.NET 1.1, ASP.NET 2.0, and now ASP.NET 4.0) to creating document workflow management for intranet. I built with ASP.NET 4.0 with C# as foundation programming language.

Existing applications contains :

  • FoxPro application for complex distributed custom desktop application. Installed in more than 15 branch office in Indonesia.
  • ASP classic application using VBScript as core application for user management, core services, and a lot of custom application for running their business process..
  • ASP.NET 1.1 application using Visual Basic .NET for purchasing and HRD application
  • ASP.NET 2.0 application using Visual Basic .NET for outsourcing and payroll

and now, ASP.NET 4.0 application using C# for document workflow management (I created it). This is interesting project because of the various environment and how to collaborate and integrate with their existing apps. Some of experiences that I have found when integrating ASP.NET 4.0 into their existing environment is very interesting.

My job are about:

  • Integrating and customizing their existing ASP.NET application thus (if possible) migrating from ASP.NET 1.1/2.0 into ASP.NET 4.0.
  • Creating service layer to centralize all functionality into one door.
  • Code refactoring for existing apps built with ASP.NET 1.1/2.0 (haiyaah…) and they want to migrate to .NET 4.0
  • Upgrading application performance
  • Integrating logging for every critical process
  • and many…

Fyuuh… this is the most challenging project in my life. They give me an access for their source code and permit me to do anything.

I will share some of my experiences when dealing with that kind of project.

a) Cookies sharing. Their core intranet using ASP classic for authenticating user based on SQL Server 2000 database. Then the engine will create some of cookies. Their existing ASP.NET 1.1 and 2.0 application using client side JavaScript for retrieving cookies and then passing to ASP.NET application. I don’t know why their programmer do the tricky way like that. :) Because the easiest way it just using this code :

HttpCookie cookie = Request.Cookies[“cookieName”];

or to make it easy, just make a function in an helper class like this:

public static string GetCookieValue(string cookieName)
{    
    HttpCookieCollection cookies = HttpContext.Current.Request.Cookies;         
    string cookieValue = string.Empty;         
    for (int n = 0; n < cookies.Count; n++)        
    {            
        HttpCookie cookie = cookiesNo;            
        if (HttpUtility.UrlDecode(cookie.Name) == cookieName)            
        {                
        cookieValue = HttpUtility.UrlDecode(cookie.Value);            
    }        
    }        
    return cookieValue.Trim();
} 

and access it by calling :

string userId = Helper.GetCookieValue(“userid”);

No need to do tricky way by using JavaScript again. Cookie is a small information that sent by browser into client machine and can be accessed easily by ASP.NET by using HttpCookie class.

 

b) They don’t use CSS for styling the design! Whew… this is horrible! Even the ASP.NET server control has their own functionality in styling, but don’t use it in production! It’s better to use CSS instead. I have to refactoring ALL custom styles and put it into one single CSS for consistency. Doing this for every files is really painful. So I create a tool for extracting style tag in every server control by using HtmlAgilityPack component then grouping it by server control type. For example, if the style is in <asp:Label  … /> tag, then the tool will provide grouping :

LABEL
    font-family: Arial; font-size: 12pt; color: Blue

TEXTBOX
   font-family: Arial; font-size: 12pt; border: 1px solid Gray;

etc…etc…etc…

This is useful for me to identify every server control in every pages and put it into single CSS file and then change the style tag into class tag.

 

c) Their application using ALOT of appSettings! More than 30 tags in appSettings. And the worst is their application read and write the value in appSettings which mean they have to touch web.config every time! This is very bad in performance since touching web.config will make ASP.NET worker process recycling again.

The solution is moving ALL appSettings configuration tags  into external files by using this technique:

<appSettings configSource=”customAppSettings.config” />

The customAppSettings.config files contains existing appSettings tags. This kind of technique would prevent ASP.NET application touching web.config again and again and also boost the performance.

 

d) Their existing ASP.NET application using Page and ALWAYS page. No base page, no web user control, and always based on Page. For checking authenticating, they copied the same code between page again and again. And guess, there are more than 500 pages!! Walaahh… No reusability. This is a big refactoring…!

After analyzing, the solution is by create a base class which contains shared functionality between pages (authentication checking, authorization checking, language detecting, currency detecting, etc etc) into one library. And make it available to others by referencing the library and recompile. Yes, there is no other way to do except recompile. :( Using IoC or dependency injection is no use here because of their application is unstructured. :(

 

d) Their application sending mail a lot. And use Persist component for ASP classic and ASP.NET. But the code is the same as before. Copied in every page again and again. Another refactoring again … :( Their process is synchronous, so every time a user click Send button, then the browser will ‘hang’ for a second (or sometimes for a minute, especially if the mail server is down) because of waiting for sending email process.

After doing meeting with their executive, they want me to make a mechanism for sending email as ‘fire and forget’. So no need to trap the error message. Just send the email, and just like that (notification only).

Solution: I create a custom function to utilize asynchronous. This feature exist in ASP.NET 2.0, so the existing ASP.NET 1.1 apps can’t utilize this function. In my helper class, I wrote the code like this:

public static void SendEmailNotification(string to, string template, string subject)
        {
            MailMessage message = new MailMessage();
 
            message.From = new MailAddress(ConfigurationManager.AppSettings["EmailNotifier"].ToString());  // no-reply@domain.com
 
            message.To.Add(new MailAddress(to));
            message.Subject = subject;
            message.Body = template;
            message.IsBodyHtml = true;
 
            using (new SynchronizationContextSwitcher())
            {
                var smtpClient = new SmtpClient();
 
                smtpClient.SendCompleted += (sender, e) =>
                    {
                        // do nothing
                    };
 
                smtpClient.SendAsync(message, null);
            }
        }

Sending email asynchronously STILL waiting for UI thread for updating, so we have to use ANOTHER thread (not ASP.NET thread). So, I utilize a class which named “SynchronizationContextSwitcher” as you can see above.

This class is useful to change the process context. So, the sending email process would not use ASP.NET thread.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
 
namespace docflow
{
    public class SynchronizationContextSwitcher : IDisposable
    {
        private ExecutionContext _executionContext;
        private readonly SynchronizationContext _oldContext;
        private readonly SynchronizationContext _newContext;
 
        public SynchronizationContextSwitcher()
            : this(new SynchronizationContext())
        {
        }
 
        public SynchronizationContextSwitcher(SynchronizationContext context)
        {
            _newContext = context;
            _executionContext = Thread.CurrentThread.ExecutionContext;
            _oldContext = SynchronizationContext.Current;
            SynchronizationContext.SetSynchronizationContext(context);
        }
 
        public void Dispose()
        {
            if (null != _executionContext)
            {
                if (_executionContext != Thread.CurrentThread.ExecutionContext)
                    throw new InvalidOperationException("Dispose called on wrong thread.");
 
                if (_newContext != SynchronizationContext.Current)
                    throw new InvalidOperationException("The SynchronizationContext has changed.");
 
                SynchronizationContext.SetSynchronizationContext(_oldContext);
                _executionContext = null;
            }
        }
    }
 
}

You can use it in your project to make email sending become ‘fire and forget’. But just do it IF and ONLY IF that suited your requirements.

Stay tune for the next update from me.

Hopefully helpful for you.

Cheers…

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

Foto-foto Seminar Nasional IT di Universitas Kuningan

Suasana peserta saat hadir pagi hari. Meski gerimis mengundang, tetapi tidak mengurangi minat peserta untuk hadir.

Photo0543   Photo0546

Panitia seminar mulai sibuk

 Photo0545  

Ruangan saat masih ‘sepi’

Photo0547

Spanduknya kekecilan kayaknya :)

Photo0548

Acara pembukaan oleh panitia dan sambutan-sambutan oleh undangan khusus

Photo0558 Photo0560 Photo0561 Photo0562 Photo0564 Photo0566

Peresmian MUGI Kuningan yang ditandatangani oleh perwakilan dari Univ. Kuningan dan perwakilan MUGI Nasional.

Photo0567

Seribu lebih peserta memadati ruangan :) Sayang fotonya dari satu sudut saja euy :(

Photo0569 Photo0570 Photo0571

Pemberian hadiah dan Door Prize bagi para penanya dan penjawab.

Photo0572 Photo0573

Foto lain menyusul :)

Share this post: | | | |
Posted by agung | with no comments
More Posts Next page »