September 2007 - Posts

180 pertanyaan dalam RFP

Wuih, ini adalah RPF terpanjang yang pernah saya dapatkan dalam suatu project. Tidak tanggung-tanggung, 180 pertanyaan dalam satu RPF. Ini memang persyaratan dari client karena memang ada standar audit pada sistem mereka yang mengharuskan setiap calon vendor menjawab secara gamblang dan jelas setiap pertanyaan yang mereka ajukan. Mulai dari sisi profile perusahaan, keuangan, hingga teknikal. Dan menariknya, ini harus bisa dipresentasikan dalam waktu 2 jam sesi presentasi. Tantangan yang cukup menarik dan menantang. Kenapa ini menarik ? Sebab perlu kejelian untuk memilih apa yang ingin kita sajikan pada presentasi. Dari 180 pertanyaan, tidak mungkin semuanya kita buatkan presentasinya. Bisa habis waktu 2 jam. Perlu kecermatan dan kejelian untuk mengambil jenis pertanyaan kunci dan pertanyaan penting yang akan dipresentasikan. Dan alhamdulillah, ternyata presentasi kita disukai dan cocok dengan harapan client. Saya sendiri perlu waktu 2 hari untuk memilah dan menentukan jenis pertanyaan yang akan kita jawab dan kita masukkan ke dalam presentasi. Inilah yang saya maksud tantangannya.

Di sisi functional requirement saja ada banyak item yang harus dijawab dan di demonstrasikan seperti misalnya :

  • Vendor Background (22 pertanyaan) 
  • Security (7 pertanyaan)
  • Content Creation (31 pertanyaan)
  • Asset Support (2 pertanyaan)
  • Workflow Management (12 pertanyaan)
  • Administrative Reporting (6 pertanyaan)
  • Search (3 pertanyaan)
  • Content Deployment (2 pertanyaan)
  • Enterprise Integration (4 pertanyaan)
  • Hosting (12 pertanyaan)
  • Documentation (7 pertanyaan)
  • Training (3 pertanyaan)
  • Application Construction and Methodology (50 pertanyaan)
  • Pricing (11 pertanyaan)

Dan menariknya, saya jawab semua pertanyaan itu seperti halnya air mengalir menggunakan ... DotNetNuke. Ini sekali lagi membuktikan bahwa DotNetNuke cocok pada 90% skenario bisnis seperti yang di claim oleh core teamnya. Saking penasarannya, setelah kita menang, saya tanya ke si pembuat RFP, apakah dia kenal DotNetNuke ? Jawabannya sangat mengejutkan. Tim pembuat RFP hanya kenal nama "DotNetNuke" saja tanpa tahu persis apa itu DotNetNuke. Sama sekali mereka tidak pernah menggunakan DotNetNuke. Kenapa saya tanya seperti ini ? Karena saya heran, kok apa yang tertera pada pertanyaan teknikal itu benar-benar cocok dengan fitur DotNetNuke sehingga saya bahkan berasumsi pembuatnya paling tidak pernah pake atau mengenal DotNetNuke sangat dalam. Pertanyaan-pertanyaan yang diajukan ternyata adalah murni standar pertanyaan yang tertuang pada mekanisme sistem audit mereka. Jadi, mereka sendiri baru tahu kalau DotNetNuke ternyata bisa cocok dengan kebutuhan mereka. 90% skenario bisnis ditambah third party custom module itu menjadi sekitar 95% kebutuhan mereka telah tercover. Sisanya adalah custom module development internal.

Pengalaman yang menarik. Ini membuat DotNetNuke sekali lagi teruji ketangguhannya dari sisi skenario bisnis, dan membuktikan bahwa DNN tidak sekedar CMS, tetapi benar-benar telah menjadi Web Application Framework seperti yang dicita-citakan oleh core team dan komunitasnya serta pencintanya.

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

Versi 5

Di bulan depan, DNN 4.7 akan launch bersamaan dengan DNN Open Force Las Vegas. Lho, judulnya khan versi 5 ? Iya, berita versi 5-nya ada dibawah ini. :)

Bocoran untuk DNN versi 5 yang nanti akan diplanning release bareng dengan Visual Studio 2008 ! Sst, ini bukan issue loh.

Awalnya adalah pembicaraan dengan core team mengenai custom authentication, workflow, dan UDT. Tapi akhirnya malah merembet ke 'curi start' informasi DNN versi 5 yang akan datang. Workflow Foundation tampaknya tidak akan diintegrasikan ke DNN sebelum versi 5. Jadi berita bagusnya adalah versi 5 yang akan datang sudah support workflow foundation. Ada 3 subject yang nanti akan di release-kan langsung, yakni :

  1. Versioning
  2. Content Localization
  3. Workflow

Jadi, intinya ada 3 major changes di versi 5 tersebut. Selain itu, installer versi yang akan datang sudah support versioning dan rollback ! Jadi artinya, kalau kita salah install, tinggal uninstall, dan rollback saja. Nanti akan ada 1 macam installer untuk semua (modules, skin, container, scheduler, providers, dll). Semua akan lewat UI. Dari struktur foldernya akan cukup berbeda secara signifikan dengan versi sebelumnya. Di versi sebelumnya, struktur folder instalasi DNN adalah sebagai berikut :

  • admin
  • App_Browser
  • App_Code
  • App_Data
  • App_GlobalResources
  • bin
  • Components
  • Config
  • controls
  • documentation
  • images
  • Install
  • js
  • Portals
  • Providers
  • Resources

Nah di versi yang akan datang, akan lebih sederhana. Banyak yang protes kenapa root folder DNN harus diberikan hak akses Modify untuk aspnet user account. Nah, di versi 5 yang akan hal itu sudah disolving. Di versi 5 yang akan datang, hak akses Modify hanya diberikan untuk 3 folder saja, yakni bin, desktopmodules, dan portals. Ada cukup banyak penambahan fitur pada versi tersebut. Yang jelas, fitur yang ada pada .NET Framework 3.5 akan dipakai nanti. Integrasi Workflow Foundation di dalam core framework akan membawa fleksibilitas yang lebih baik.

Custom authentication provider yang dibuat juga memungkinkan Anda untuk mengganti model authentication standar DNN menjadi versi Anda sendiri dengan mudah. Saya masih ingat ketika mendevelop satu project di Belanda untuk mengganti model authentication DNN menjadi ini : http://www.diginotar.com/Default.aspx?tabid=90 harus menggunakan trik tertentu agar berjalan mulus (or you just can call it "hack"). Nah, di versi yang akan datang proses penggantian itu akan lebih mudah lagi.

Sekian dulu penjelasan mengenai 'bocoran' DNN versi 5 yang akan datang. Informasi lain menyusul seiring dengan informasi yang diterima.

;)

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

DNN Module Development Technique, Another Approach

We know that there are some technique when developing custom module in DotNetNuke. You can use some technique from the simplest to the complex one. For me, i'm usually using this technique. I will explain it like below.

First, in every module, i create a file which called Injector.ascx. This file will act as injector for other user control. It only contains one PlaceHolder object. This is the file that you have to registered inside DotNetNuke framework. The complete code for Injector.ascx is below :

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using DotNetNuke.Entities.Modules;

namespace DemoDNNUserControlNavigator {
    public partial class Injector : PortalModuleBawrap glyph
se {
        
        private string m_ControlToLoad = string.Emwrap glyph
pty;

        protected void Page_Init(object sender, Evwrap glyph
entArgs e) {
            ReadQueryString();
            LoadControlType();
        }

        private void ReadQueryString() {
            string qs = string.Empty;
            if(Request.QueryString["ControlType"wrap glyph
!= null) {
                qs = Request.QueryString["ControlTwrap glyph
ype"
].ToString();
            }
            if(qs != string.Empty) {
                switch(qs.ToLower()) {
                    case "p1":
                    m_ControlToLoad = "page1.ascx"wrap glyph
;
                    break;
                    case "p2":
                    m_ControlToLoad = "page2.ascx"wrap glyph
;
                    break;
                    default:
                    m_ControlToLoad = "page1.ascx"wrap glyph
;
                    break;
                }
            } else {
                m_ControlToLoad = "page1.ascx";
            }
        }

        private void LoadControlType() {
            PortalModuleBase objPMB = (PortalModulwrap glyph
eBase)this.LoadControl(m_ControlToLoad);
            if(objPMB != null) {
                objPMB.ModuleConfiguration = this.wrap glyph
ModuleConfiguration;
                objPMB.ID = System.IO.Path.GetFilewrap glyph
NameWithoutExtension(m_ControlToLoad);
                plhControl.Controls.Add(objPMB);
            }


        }
    }
}

 

 You see from the code above. I have two method and one private member. The first method is ReadQueryString(). This method is responsible to change the user control inside module based on querystring that we passed. The querystring will targetting to specific user control (.ascx) inside your module. The next method is LoadControlType(). This method is responsible to cast your desired user control into PortalModuleBase then put it inside PlaceHolder. To redirect to other user control, you can use Globals.NavigateUrl() method like below :

Response.Redirect(Globals.NavigateUrl(PortalSettings.ActiveTab.TabId, "", "ControlType=p2"));

Why i like this approach? Since i only have to register one control inside DNN. If i want to add new control, i just open my Injector.ascx.cs then add my new control. That's it. This solution is suitable in most of my cases.

But then i come into problem in a client. The problem is, i have to recompile my solution every time i have to add new user control. I think, it's time to make it dynamic. So, it's time to create a simple framework for navigation. My proof of concept is like this :

  1. All user controls are registered via configuration file inside DNN module (or maybe in root with a specific name)
  2. The DNN module (.ascx) should inherits from my custom class (not from PortalModuleBase again). At this time, I name it PageFlowLight.
  3. The page navigation mechanism should be simple like this : PageFlowLight.Next(), or PageFlowLight.Prev(), or to specific page like PageFlowLight.Go("StageTwo"). So i have create a adapter between Globals.NavigateUrl() and my new method.

Hey, sounds like Workflow Foundation Page Flow sample. :) Yep, i borrow some approach from the sample of ASPNETWFPageFlow from Microsoft.

1. All user controls are registered via configuration file inside DNN module (or maybe in root with a specific name)

First, my POC configuration file will be like this (i called it navigation.xml) :

<?xml version="1.0" encoding="utf-8" ?>
<modules>
    <module name="PF" startStage="start">
        <stages>
               <add name="start" transition="stagetwo" />
               <add name="stagetwo" transition="finish" />
        </stages>
        <pageflow stage="start" pageUrl="Page1.ascx" />
        <pageflow stage="stagetwo" pageUrl="Page2.ascx" />
        <pageflow stage="finish" pageUrl="Finish.ascx" />
    </module>
    <module name="Report" startStage="start">
        <stages>
               <add name="start" transition="stagetwo" />
               <add name="stagetwo" transition="finish" />
        </stages>
        <pageflow stage="start" pageUrl="Page1.ascx" />
        <pageflow stage="stagetwo" pageUrl="Page2.ascx" />
        <pageflow stage="finish" pageUrl="Finish.ascx" />
    </module>
    <module name="Dashboard" startStage="start">
        <stages>
               <add name="start" transition="stagetwo" />
               <add name="stagetwo" transition="finish" />
        </stages>
        <pageflow stage="start" pageUrl="Page1.ascx" />
        <pageflow stage="stagetwo" pageUrl="Page2.ascx" />
        <pageflow stage="finish" pageUrl="Finish.ascx" />
    </module>
</modules>

As you can see above, we just register our module and also your user control. Stage attribute will give you direction to do Next(), Prev(), or Go() method inside PageFlowLight class. Then, the injection will be dynamically did inside PageFlowLight. To traverse inside navigation.xml file, i'm using System.XML.XMLDocument with XPath query syntax. The structure of XML should be validate before to make sure the integrity of the data.

For example, this code will traverse the xml file :

        XmlDocument doc = new XmlDocument();
        doc.Load(Server.MapPath("navigation.xml"));
        XmlNodeList nodes = doc.SelectNodes("//module"); // get all modules tag
        string result = "";
        foreach(XmlNode node in nodes) {
            result += "<br />&lt;" + node.Name + " " + node.Attributes[0].Name + "=" + node.Attributes[0].InnerText;
            if(node.HasChildNodes) {
                foreach(XmlNode childnode in node.ChildNodes) {
                    result += "<br />&lt;" + childnode.Name +
                            " " +
                            childnode.Attributes[0].Name + "=" +
                            childnode.Attributes[0].InnerText +
                            " " +
                            childnode.Attributes[1].Name + "=" +
                            childnode.Attributes[1].InnerText +
                            " /&gt;";
                }
            }
        } 

To get specific module name, you can use this XPath query syntax :

//modules[@name='PF']/pageflow

To get pageflow element with specific attribute stage, you can use this XPath query syntax :

//modules[@name='PF']/pageflow[@stage='start']

To get pageflow element with specific attribute pageUrl, you can use this XPath query syntax :

//modules[@name='PF']/pageflow[@pageUrl='Page1.ascx']

2 and 3. The DNN module (.ascx) should inherits from my custom class (not from PortalModuleBase again). At this time, I name it PageFlowLight. And provide simple mechanisme to call next user control.

The PageFlowLight framework should provide mechanism to get TabId from active Url then it can injects right user control inside the right module. I do it by creating Initialize() method with ModuleId as parameter. The ModuleId then will be translated into ModuleName to find correct tag inside navigation.xml file.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using DotNetNuke.Common;
using DotNetNuke.Entities.Modules;

namespace DemoDNNUserControlNavigator {
    public partial class page2 : PageFlowLight {

        protected void Page_Init(object sender, Evwrap glyph
entArgs e) {
            Intialize(this.ModuleId); // this came from PageFlowLight framework 
        }

        protected void btnNextPage_Click(object sewrap glyph
nder, EventArgs e) {
            PageFlowLight.Next();
        }

        protected void btnLastPage_Click(object sewrap glyph
nder, EventArgs e) {
            PageFlowLight.Last();
        }
    
        protected void btnNextPage_Click(object sewrap glyph
nder, EventArgs e) {
            PageFlowLight.Go("StageThree");
        }
    
    }
}

 

In the Page_Init, we have to call Initialize() method with ModuleId parameter. This will register our user control (page2.ascx) into PageFlowLight system so you can use Next(), Prev(), Last(), Go() navigation method.

This is my proof of concept that successfull to implement in my client. I will post complete source code for PageFlowLight framework in my next article.

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

DotNetNuke 4.6 released !

Yes, this baby is coming. :)

You can download it here : http://sourceforge.net/project/showfiles.php?group_id=77052

For complete list for bug fixing and enhancement, you can see it here : http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryID/1554/Default.aspx

DotNetNuke version 4.6 is the best released yet !!

Outstanding issues in DNN Core Framework 4.6.0

 
Show Stopper

Major

Minor

Trivial

Total
PDF Report
Bugs
1
73
104
34
212
 
Tasks
0
8
34
26
68
 
Enhancements
1
100
261
199
561
 
New Features
0
21
55
27
103
 
Total
2
202
454
286
944

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

Opening new position

BataviaSoft Indonesia is looking for new colleagues....! We have 3 open positions.

1. We are looking for a Senior ASP.NET developer who also has the ability and/or experiences in leading a development team for our international projects.

He/she should match the following profile:

  • Min. 2 years experience in software development with Microsoft .NET
  • Min. 2 years experience in web application development with ASP.NET: VB.NET / C#
  • Min. 2 years development and design experience in Microsoft SQL Server
  • Excellent Object Oriented programming skills
  • Good communication skills
  • Fluent in English both spoken and written
  • Microsoft Sharepoint development experience is an advantage
  • DotNetNuke development experience is an advantage
  • Microsoft .NET Certification is an advantage

2. We are looking for an experienced ASP.NET

He/she should match the following profile:

  • Min. 2 years experience in web application development with ASP.NET: VB.NET / C#
  • Min. 2 years development and design experience in Microsoft SQL Server
  • Good communication skills
  • Proper English. (Ability to understand English documentation properly)
  • DotNetNuke development experience is an advantage

3. We are looking for an DotNetNuke developers

He/she should match the following profile:

  • Min. 2 years experience in DotNetNuke development with Visual Basic or Visual C#
  • Knowing the architecture of DotNetNuke web application framework
  • Knowing the architecture and implementation of DotNetNuke module

We will offer you:

  • Competitive benefits
  • Microsoft .NET certification
  • International projects for big companies in Europe
  • Working with the latest technologies
  • Dynamic environment
  • Great atmosphere
  • And of course nice colleagues

Working Time
We have 2 choices of working shift that you can choose between:
The first is a normal working shift from 09.00 till 17.00
The second is an afternoon shift from 13.00 till 21.00

Please send your motivation letter, sallary expected, and/or resume to agung.riyadi@bataviasoft.com

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