25 November 2004

ASP.NET page life cycle

Paul Wilson's article Page Events: Order and PostBack
and Dino Esposito's
The ASP.NET Page Object Model are good reminders for questions like 'When does this (server-side) Textbox validation happen?' and 'Where do I assign the regular expression for validator?'

24 November 2004

Yet another Microsoft Exam

Now I am a MCAD! This time I am taking on '070-229 Designing and Implementing Databases with Microsoft SQL Server 2000 Enterprise Edition' with the help from Professional SQL Server 2000 Programming, by R, Viera. Persnally, I don't like the book. The concepts and practices in each chapter is very loose. It is at lack of structural way of presenting idea. And it will be better if Viera is not using overly verbal language and side-tracking jokes. It will be more painless to read if it can be more concise. I found using Sql Server Book On Line offers great help.

Anyway it covers everything and it is a seriously huge book. My day bag is much lighter now.

19 November 2004

ADO.NET and SQL Server security, performance Recommendations

The typical application scenario is an internet web application located in DMZ then submits data via ADO.NET, either in-process or though middle tier.

1. Use windows authentication.
1) The web server should not be in the trusted domain. Create a local NT user account ‘Fred’ with least privileges. This account will be used as the IIS anonymous access account for the web application.
2) Enable IIS anonymous access for the web application.
3) On the Sql Server, mirror the NT account ‘Fred’ created above. Set Sql Server security login mode to be ‘Windows Only’.
4) Create a SQL Server Login for ‘Fred’. Grant ‘Fred’ to ‘Public’, ‘Deny Data Reader’ and ‘Deny Data Writer’ access.
5) Allow application access data via Store Procedures only. Grant ‘Fred’ to all user- defined store procedures exec rights.

2.When you specify a server in an ADO.NET connection string, always use IP address instead of the server's DNS name to cut the overhead on DNS resolution.

3.Specify 'Application Name' in the connection string. It makes SQL Profiler can pick up the connections quite handy, or just for trouble-shooting.

4.Do not use SQL Server application roles, it turns off connection pooling.

5.When possible, use the ExecuteNonQuery method with SQLCommand objects, as this is the most efficient way to execute queries from ADO.NET. Use output parameters with SQLCommand objects if you need to retrieve just a few values, or a single data row, instead of using more expensive techniques, such as a SQLDataAdapter, a SQLDataReader, or a strongly typed DataSet.

6.Avoid using Transact-SQL cursor at all possible, try use correlated sub-query or temporary table instead.

17 November 2004

My new soruce control client hijacks Visual Studio default soruce control provider

The default source control provider links to Visual Studio is VSS (of course!). Howerver, since I installed PVCS Dimesion client for a different project recently, the source control changed to be PVCS.
It is not in my interest to use PVCS for the .NET projects I am working on. However, there is no way you can change it back to VSS from Visual Studio(it is not the tools|option|source safe menu.)
The only way to change this is from registry:

Run regedit. Browse to 'HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\InstalledSCCProviders', it should be a list of all installed SC providers there. Copy the Data (path) of the intended used source control provider, then use it to replace data of 'HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\ProviderRegKey'.

Maybe there is a switch program around? Sure I am not the first one met this problem. I will do one if I have time. Many thanks to Nick A. to share this.

16 November 2004

Setting Up Trusted Connection between Sql Server and Web Server

Initiatives: MS Pattern and Practices recommendation: Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication:
Extranet Security and Access Security.

Scenario 1 SqlServer and Web Server are running on the same box
Likely be the home pc or standalone development environment-the configuration is quite simple:
1. IIS6 (Windows 2003 Server)
Follow this article to configurate IIS 6 access to SqlServer.
In my experiments, it shows that the IIS anonymous account setting in the web app's '(Virtual) Directory Security setting | Authentication and access control' and disable/enable integrate Windows authentication is not relevant- it will always be an IIS_WPG member account used to access SqlServer. You can run EXEC sp_who to find out which account is used.

The only exception to above is you specify <identity impersonate="true"/> in web.config. I tried to use IUSER_(Internet Guest Account). However, it failed to get access to Sql Server (SP3)mysteriously, even I have grant the correct access rights to it.

2. IIS5 (Windows 2000 Server)
If running on IIS5(Windows 2000)it is IUSER_ used as the anonymous account. I guess it will be fine to use it to access SqlServer. Will try out soon. At the end of this blog is a vbs script which shows the credentials of IIS anonymous account and ASPNET Procs account.

Scenario 2 SqlServer and Web Server are running on two machines
In short, the MS recommended way is:
1)Don't put Web server on the trusted domain, but DMZ.
2)Create a NT account that impersonate as IIS anonymous account on web server.
3)Create the exact same account(username/password) on the Sql Server machine.
4)Grant access to this account.

How to use Trusted Connection when SQL server and web Server are on two separate machines has step by step guide on this.

Following vbs script shows credentials for iis anonymous user account

Dim IIsObject
Set IIsObject = GetObject ("IIS://localhost/w3svc")
WScript.Echo "AnonymousUserName = " & IIsObject.Get("AnonymousUserName") & vbCrlf
WScript.Echo "AnonymousUserPass = " & IIsObject.Get("AnonymousUserPass") & vbCrlf
WScript.Echo "WAMUserName = " & IIsObject.Get("WAMUserName") & vbCrlf
WScript.Echo "WAMUserPass = " & IIsObject.Get("WAMUserPass")
Set IIsObject = Nothing

13 October 2004

11 October 2004

week two at MTC(Microsof Technoloy Center)

We have been here for two weeks to work with MS technologists on a Biztalk proof of concept project for our B2B system integration. I finally can spare sometime to do some brain dump.
We completed most of the development tasks for the POC. The opened issues here are around testing and some deployment setups for non-core services.
Phil (card ops), Geoff and Ade visited us on Thursday for a mid-term work check. They seemed quite satisfied about what Biztalk can do and how Biztalk can be used by the non-technologist. We even got Phil to create and test an orchestration with his own hand on the mouse.
The most interesting bit is deployment automation. Biztalk Deployment is a daunting task:
First you need to deploy .NET assemblies to GAC (these assemblies typically provide utility functions that used by orchestrations, rules engine, custom pipelines).
Then install all custom adapters if they are not previously installed on the machine. HTTP, SOAP, MSMQ etc are provided as standard, we also got a Topend adapter.
Then install the business rules engine.
Then install all Biztalk assemblies.
Then install and bind all send/receive ports Biztalk assemblies used.
Then start all orchestrations.
For our development and demo, we also need to install all web services used by Biztalk such like Smart Connectors and web sites for demonstration.

And of course we need a clean up script to reverse the deployment as well- it takes a whole lot to test a Biztalk orchestration.

We use command line script to automate these tasks. Some of them are provided in the SDK samples, others are not. Such like deploying business rules. Before we come to Reading, even MS are telling people ‘It is very difficult to automate this step, and you are better off to use the GUI wizard to do it’. And now we have a little command line program to do the job!

24 September 2004

BizTalk FAQ

I am working on a Biztalk POC project at the moment, here is a list of problems have occurred to me at varuious stage and the solutions. The list will keep growing as proceeding.

1. Biztalk Message Queue causes conflict with MSMQ
-- In short, you cannot run MSMQT on the same machine as MSMQ runs. What behind MSMQT is MSMQ, they are using the same port (1801). This can happen on the test/deployment machine if MSMQ already run then you configure to use MSMQT. This problem raised when you try to start Biztalk Application again.. Stop the MSMQ service (Message Queuing and Message Queuing Triger) from Service Control Console, then start the Biztalk Application will fix the problem.

2. Running an independet web service on the same development machine that has biztalk server and Sharepoint server installed. I was getting 404 'file not found' when requesting a web service.
--MS Development team suggest the stsfltr.dll ISAPI filter from sharepoint team services may cause the problem. I have tried remove this ISAP filter from IIS, problem solved. Read this KB

3. I drop the request xml into the receive port-bound dir, it has been processed but the resulted xml doc is not produced, why?
-- It is spot on that orchestration process picks up the request as it has been removed from receive port-bound dir. The first thing to check is the send port - outbound settings. Is the dir granted with appropriate write/modify access to the account that BiztalkServerApplication runs under? Is there any typo in the address URL send ports point to?
If you are using late bound, the problem is easy to rectify. Just stop the orchestration process, unlist it, correct the problem and restart the orchestration process- make sure all receive and send ports and enabled/started.
If the application is bound at the design time, there are few more things need to be done.
First on the development pc, open the source project, correct the problems and rebuild it.
Then on the deployment server, stop/unlist the problematic orchestration from the Biztalk admin console.
Then start the deploy wizard, remove the problematic biztalk assembly from the configuration database-you need to remove it from GAC as well.
Install the new compiled biztalk assembly.
Specify all late bind ports to the new orchestration process use Biztalk Explorer.
Enlist and start the orchestration process from Biztalk Admin console

Lesson learn: Always use late binding ports when permitted.

23 September 2004

ASP.NET Response.Redirect Server.Transfer Server.Execute not working

The symptom:
On completion of registration or login, I want to redirect the response to the page where user coming from, say default.aspx. I expect the QueryString ReturnUrl will be picked up and browser will be forwarded. However, the redirection is not working, working intermittently. Sometimes, the login page stayed as if not being refreshed, other times I got a blank page with url poited to the desired target. I have tried these methods Response.Redirect Server.Transfer Server.Execute and FormsAuthentication.RedirectFromLoginPage. None of them works. I was using Framework 1.1.

The solution:
1) Make sure your browser supports cookie. If you are using personal proxy, such like ZoneAlarm, check to see it will not block cookies even from localhost.
2) Check to see SmartNevigation is set to off in the web.config. If it is on, the page redirection will fail. Debug trace shows the Application_BeginRequest wouldn’t even be hit.

11 September 2004

CMS SCA Host Headers Mapping vs IIS HTTP Host Headers Mapping

MCMS Server Configuration Application (SCA) has an option to map channel names to host headers names. It can be used to allow host multiple CMS web sites with different domain names on the same CMS server.
To do this, we need to map top-level channels as the root channels for a URL with a host header name that is identical to the channel name. When CMS generates a URL pointing to an item inside the virtual site www.CMSsite1.com, it prefixes the URL with the name of the channels in which it is contained.’ See chapter 18 of book Microsoft Content Management Server 2002
There are two points need to note:
1. Names of top channels on a CMS server must match the virtual site names in IIS.
2. The virtual site names must be valid DNS name.

So a typical co-hosting configuration for three web applications on a development box can be:

In MCMS Site Manager:
We have three top channels, they sharing the same CMS database, and named as:

Install a network loopback adapter and assign IP address from

In IIS Manger, create three web applications named and assign IP address as:
www.CMSsite1.com (
www.CMSsite2.com (
www.CMSsite3.com (

Open %Winnt%\system32\drivers\etc\host with notepad and add following entries: www.CMSsite1.com www.CMSsite2.com www.CMSsite3.com

So you may ask how will this related to HTTP host header mapping in IIS?
Not a lot. IIS HTTP host header mapping is used to provide multiple-hosting. The HTTP host headers identify multiple virtual web sites that reside on one physical server and all sites shares same IP address.
However, you need to configure the HTPP host headers on the IIS site if a single IP address is used for multiple CMS sites.

06 September 2004

Pass another MCP exam

I passed the 70-320 MCP exam today, which is on Remoting, Serviced component, COM+, Windows services and XML web services. For the last 4 weeks or so, I totally enjoyed the pleasure of discovery. Ingo Rammer's Advanced .NET Remoting is inspiring and fun to read. I got the book off my boss and gave him back with some coffee stains ;-).
I reckon 70-320 is hardest one or at least it should be the hardest one to take, given the weight on each branch it tries cover. In a sense, Remoting and serviced component are the same hierarchy of .NET technology tack, like ASP.NET. However, 70-320 covers far more than that, which dilutes the depth it can accommodate in a two hours session.
Serviced Component, the .Net version of COM+ is still the toughest part. I used Juval Lowy’s Programming .NET Components and Chapter 10 of his COM and .NET Component Services as introductory.
If I were not heading for exam, I can probably explore more in-depth rather than board coverage. This is particular important to COM+ bit, which is hard to pick-up yet easy to drop-off.
Now the challenge is: will I utilise these knowledge and skills and keep them sharp?

04 September 2004

Should I use SetAbort()/SetComplete() or DisableCommit()/EnableCommit()?

It was originally from a MCP vendor exercise question. I have it modified slightly:

You are creating a serviced component named UserManager. UserManager adds user
accounts to multiple transactional data sources.
The UserManager class includes the following code segment:

[ObjectPooling(true, MinPoolSize=1, MaxPoolSize=50)]
public class UserManager : ServicedComponent {
public void AddUser(string TestKname, string TestKpassword)
// Code to add the user to data sources goes here.

You must ensure that the AddUser method reliably saves the new user to either all data
sources or no data sources. What should you do?
A. To AddUser, add the following attribute:
B. To UserManager, add the following attribute:
C. To the end of AddUser, add the following line of code:
D. To the end of AddUser, add the following line of code:
E. To the end of AddUser, add the following line of code:
ContextUtil.MyTransactionVote = true;

IMHO, there are two issues need to be addressed here:
1. Object activation and pooling. .NET 247 : object persistence across client method calls discusses this issue. Basically, the ‘done’ flag decide whether an object is ‘done’ and can be deactivated.
2. MyTransactionVote or consistent flag.

The SDK Doc says, ‘When MyTransactionVote is set to Commit, the COM+ consistent bit is set to true and the COM+ context votes to commit the transaction. If MyTransactionVote is set to Abort, the consistent bit is set to false and the COM+ context votes to abort the transaction.’

And here is matrix of the four methods:

The question is about when and how to do 1) ‘all or not’ transaction; 2) object activation and pooling.
EnableCommit() cast a 'go' vote for transaction yet maintain the object as activated so C will be the best answer.

05 August 2004

CV Crap

I heard this term from a friend who worked as a recruitment agent. The term is referring to those people put in all buzz words in their CV, such like C/C++/C#/JAVA/VB, UNIX/WINDOWS etc.
Unfortunately, I am sliding to the edge of a CV crap. Our employer decided to abandon .NET technology for some period and asked all engineers to pick up a second skill set from existing system – which sound to me like pre-emptive notice of another round of ‘reorganisation’- anyway, I am doing Java J2EE migration now.
That would not stop me on the journey to .NET though. I still plan to take the other four MCSD exams before end of the year- maybe right time when we will find out what our employer wants.
I now read in the morning journey to office, then spend a little time on exercises before crack into Java work. Occasionally I advise people on middleware development which is on C/C++. I do some ASP .NET application in the evening at the moment.

Til the end it is how you think not languages mattered.

03 August 2004

Asynchronous call for Web Forms

Call back function is useful in catch asynchronous result arrival event. It works fine on those known sockets/connection such like WIN FORM, Web Services. However, it is not applicable for Web form. There is simply no easy, reliable way for server to notify client browser.

WaitOne, WaitAny and WaitAll provides a mechanism allowing a Web form to multi-task background processes and collect result after they have completed. Read this Optimizing Web service calls from Web Forms

This pattern is not that helpful when comes to UI, however.
Image there is a long run process, I want to display a progress bar one the call has been made. Then a few ten seconds later, I want to collect the result and update the UI accordingly- just show the progress bar if the result is not ready. You have to use script to refresh browser.

(5/03/2005)Just found this discussion that suggests implementing System.Web.IHttpAsyncHandler interface in the page behind class which sloves the problem.

27 July 2004

Remoting Basic

MarshalByRef executes remote method calls on the server side. Only ObjRef-networked object pointer is passed around. Client doesn't have the complied object, but the interface or base class to the object.

ByValue - class need to be serializable. Object is serialized to binary or string(xml) and transport between server/client. It then restored to a copy of the original object at the other end. Which means client and server both need the complied class prototype. State info is preserved.

Basic Architecture
At least three three assemblies are needed for a .net remoting project:
1. Shared Assembly: Client and server both need to have access to the same interface definition (MarshalByRef), serializable objects(ByValue)
2. Server
3. Client

Implement remoting project: Life Cycle
1. Implement SharedAssembly
1.1 Define the remote interface
1.2 Define data class that will be passed around in the shared

2. Implement Server
2.1 Implement the interface by Server.
2.2 Create a new channel and register it to the remoting service.
2.3 Register the server service as "RegisterWellKnownServiceType"

3. Implement client
3.1 Registering client channel
3.2 create local proxt object to forward calls to server

12 July 2004

A dose of anti-depression

Having been feeling nothing exciting to do on the techie bits- well, in fact not many things to do at work at all for a while, I doubt I got the Clinic Depression after taking a 10 minutes quiz online*.

Clinic Depression is not a work-avoidance excuse or can be taken lightly. As the reference material says, you need to take counselling and some pills for a really long time. It is a mood in that, you loss interests on everything and don’t want to get in with those even most fascinating things before. You tell yourself to ‘I need to put everything together’, but you just can’t’.

Instead of loss in this hollow, I booked a Microsoft ASP.NET exam (70-315) bluntly. It costs about 100 pounds for about two hours. I decided to pay it myself instead of ask my boss to sign the bill- just to full load the pressure on myself.

Thought I have done some ASP.NET for about a year so far, I never have a proper or well scheduled learning period before. Got three weeks to prepare for it at that time. At some points I start to think ‘should I re-schedule the exam?’ I didn’t.

Instead, I told everyone in the team about it three days before the exam, so the pressure is at the explosive point. (Actually, it is quite silly to do that, not even leave a fail-back place.)

I took the exam this morning.

And I passed! With a score 906 out of 1000. The pass mark is 700.

It is really good news in any sense. I did learn a lot of new ASP.NET stuff, and lights shed on to those corners in normal developer’s lives will probably missed, such like deployment or security configuration. And I got out from the depression mood completely and feeling fully charged and in control now.

I wouldn’t say it is the end/top of the ASP.NET skills I will have. It wouldn’t stop there. I take it as a bench mark which means I can progress further.

And overall, I just proofed MCSD exams are most effective anti-depression drugs money can buy.

*As Nick pointed out, the online quiz is targeting female audience. I reckon it should work for both.

11 July 2004

Debug JavaScript in ASP.NET Apps

Debug JavaScript in ASP.NET Appstells how to debug client script:
Assuming we 'inject' following code snippets to create client side script

<script language="javascript">
function DoSomething()

//in the code behind test.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
btnClick.Attributes.Add("OnClick","JavaScript:return DoSomething();");

We can set break point at DoSomething() by:
1) Open Internet Explorer, choose Tools | Internet Options. Click the Advanced tab and find Disable script debugging. Clear the checkbox.
2) In VS.NET IDE, press F5 to launch process in debug mode.
3) Navigate to the web page contains the script- test.aspx
4) Open 'Running Ducuments' window on IDE by selecting Debug | Windows | Running Documents, Running Ducuments Window launch and give a tree list of all document;
5) Double click test.aspx to load it into IDE browser window.
6) Place break point, monitoring variables as usual.

30 June 2004

Server Side ViewState

Server Side ViewState: I will have a closer look at this later

29 June 2004

Documenting Exceptional Developers

Documenting Exceptional Developers seemed gives some pragamatic arguements on use try-catch wisely.

If Matt insists to make 'user login failure' kind of things as exceptions, I will show him this article and call him 'exceptional coder' ;-)

Also from Peter Bromberg, Build a Really Useful ASP.NET Exception Engine is more interesting to try out.

OnError and [Page]_Error

Aspx Page have two event methods: [Page]_Error and OnError. They are different. OnError hands control to a private HandleError method. HandleError checks whether web.config:customErrors is turned on and redirects request accordingly.
The base implementation on OnError: checks whether tracing is turned on and adds its own bit about the exception just raised. The main reason to override OnError is to replace this behavior with your own implementation. There is no good reason to put other code there. If <customErrors> turned on, code in OnError will fire first then redirect request to customized error page. In this case code in Page_Error will not fire, as OnError fires first.
To do error-handling at the Page level, use Page_Error.

Create an aspx page ManMadeError with both event handling methods:

private void ManMadeError_Error(object sender, System.EventArgs e)
Exception ex = Server.GetLastError();
// System.Diagnostics.Trace.WriteLine(ex.ToString(), "Error");
if (Trace.IsEnabled)
Response.Write("Trace on");

Session["Error"] = ex;
protected override void OnError(EventArgs e)
Response.Write("<h1> We have a problem </H1>");

in Web.config, we have

<customErrors mode="On" defaultRedirect="./Errors/500.aspx" >
<error statusCode="401" redirect="./Chp8Security/Authen_2.aspx" />
<error statusCode="500" redirect="./Errors/500.aspx" />
<error statusCode="404" redirect="./Errors/404.aspx" />

Fires the exception, and watch the implantation in ManMadeError_Error is ignored entirely.

Customised application error page

We can specify error pages to intercept HTTP errors using Web.config file.
To display a specific error handling page for HTTP status code such like 404(NotFound), 500(InternalServerError), 401(Unauthorized)etc we can add the following element to the web app’s web.config file:

<customErrors mode="On" defaultRedirect="./Errors/wehaveaproblem.aspx" >
<error statusCode="401" redirect="login.aspx" />
<error statusCode="500" redirect="./Errors/wehaveaproblem.aspx " />
<!-- redirect to the 404 page only valid for URLs that end with aspx.
Need to config IIS to take other page types -->
<error statusCode="404" redirect="./Errors/404.aspx" />

To the 404 error, by default it only works for .aspx and .asp pages. Requesting pages like .htm or .html will still fail back to default MS 404 page. To enable our IIS App handling .htm, you need to map .htm/.html request so it could be handled by aspnet_isapi.dll.
Open IIS manager, click ‘(Application) configuration…’ and in ‘(‘Application mapping’ tab, add htm extension. Map it to ‘((install_drive) \WINNT\Microsoft.NET\Framework\(version)\aspnet_isapi.dll.

Once this is done, you may notice the app is giving back a 500 at default home page (http://www.mySite.com/), if you use a default.aspx page. This is because the default document retrieval order is set to default.htm-default.asp-iistart.asp-default.aspx. Add a dummy default.htm page to redirect the request to default.aspx as following(need client side to enable scripting):

<script language=javascript>

The other way to do display customised error page is by configuring IIS in Custom Errors Setting.

28 June 2004

ASMX serialization vs. binary serialization with remoting

Remoting is useful for crossing app domains, but not for crossing machine boundaries. Check

24 June 2004


Issue: Form Based authentication, authenticated state cannot be kept between pages navigation in a web application.
The sample web app has been tested on a w2k svr which is a domain member and worked fine.
Moving to a stand alone w2k- my home PC, it failed. Trace file indicates the credentials has been authenticated (FormsAuthentication.Authenticate). On page redirection (FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);), the authenticated state lost.
Having run the IIS authentication diagnostic tool (http://www.iisfaq.net/), I found it point to the fact the IIS Web Server needs to be a domain member.

28 May 2004

403 error when accessing a CMS site for the first time

It is worth to check SCA and set 'Map Channel Names to Host Header Names' has set to 'YES' first. In my case, I configurate IIS to use host header mapping and hence this also need to be set accordingly

18 May 2004

Wireless web reaches into paradise

Firstly, they miss the whole point of Maldives. People come here just to escape the world for a few days. They don't care whether US has pulled out from Iraq when they are having sun bath or swimming with dolphins, they don't care whether FTSE has gone up another 100 points- at least just for a few days. We have been there once and the only TV on the island broadcasts CNN news twice a day. It is not surprise that nobody cares to sit in the lobby.

Secondly, erect an antenna that ‘must taller than above the line of the palm trees’ is not going to do any good to promote the resort. The owners may want take a few photos reserved for postcard before the antenna has been installed.

The only valid bit is guests can ‘send electronic postcard to their friends and family in seconds’ instead of posts for weeks. But, I would rather prefer the post. You got the salty feeling of some real paper, hand-writing and stamps. That is a real piece of souvenir. An electronic postcard in seconds is just some show-off.

Technically possible doesn’t mean you should do it.

I hope they will fail and leave a paradise as it named.

Read more Wireless web reaches into paradise

17 May 2004

Missed train this morning

Had been leaving late this morning, but managed to get there 2 minutes before the train arrival time. I normally wait in car until seeing the train pulls into platform before getting out. 30 seconds is enough to board it.

The guy to my left glimpsed at me, his wife just got out of the car. The lady is a daily commuter on this journey. I parked my car into the bay next to his.

A golden Peugeot briskly stopped at the far left parking lot - a space enough to accommodate three cars. How could she parked like this? She took middle position unevenly, so it will be quite difficult for the one parks to the right. The lady owner jumped out and rushed to the platform. There was still plenty of time.

The driver at the left eye-escorted his wife onto the platform, reversed out and gone.

I should shift a slot to left so make more space for other people. The gap between my car and the far left one is more than one car space now.

Just noticed another lady commuter briskly stopped and jumped onto the platform. People are moving fast these days.

I reversed out the car then parked again. Perfect.

Train still not arrived. I decided to come out, wait at the platform and enjoy some morning breeze. Walked to the platform, on time.


A train was slowly pulling off before I could possibly reach the edge of the platform.

Damn it!

It turned out that the train has arrived earlier and wait at the platform for awhile, just the bush blocked the view from the car park to the rail track.

It was 2 minutes to 7. Get back to car and have to wait for an hour.

Lesson learnt: Never assume, not even the most familiar bit known to you. Make sure you actually see them.

14 May 2004

Remember to Map CMS Vitual Directory

Here is the story:
VS.NET by default uses localhost:80 (default web application/VS.Net Solution Host) to publish CMS App, say http://localhost:80/myCmsApp1. I create a Web app using a different IP address which maps to http://localhost:80/myCmsApp1. However, I forgot to create a CMS VD from within
myCmsApp because it has IIS root with mapping to CMS already - multi web apps sharing one IP.
It looked like this:

Now it needs a http://MyIIS/myCmsApp1/cms that maps to (...)\Program Files\Microsoft Content Management Server\Server\IIS_CMS to work correctly from within localhost, otherwise you may get some funny client broswer script errors like the following:

Line : 447
Char :4
Error : Type mismatch: "Initialize Toolbar"
URL: http://myCmsApp1/NR/exeres/[Guid],frameless.htm?NRMODE=Unpublished&NRTEMPLATEVERSION=CheckedOut&WBCMODE=AuthoringReedit

placeholder icons may not be displayed correctly as well as Web Author console not functioning.

Create an CMS VD in myCmsApp1 to solve the problem.

13 May 2004

ASP.NET Impersonation

I met problems on trying to run ASP.NET Web App on a Windows domain controller earlier on and here is why this happened.
First let’s have a look at the ASP.NET Impersonation model.
With IIS anonymous access enabled, depends on whether ASP.NET impersonation is enabled, an impersonated account is used. In machine.config file:

// impersonation enabled, will impersonate using account pass by IIS
<identity impersonate="true"/>
// authentication enabled and user account specified
<identity impersonate="true" name="domain\user" password="pwd"/>
// authentication disabled
<identity impersonate="false" />

1)If it is not, requests are made using the system-level process account. This account is configured in the element of the machine.config file.
2)If ASP.NET impersonation is enabled, requests are made either using the IIS anonymous access account (localmachine\IUSR_machinename by default) or using a user account specified in the element of the section. In addition, if no account is specified in the element of the section, then permissions for user accounts may be specified in the element of the section.
All accounts on a domain controller are domain accounts and local accounts- localmachinename\(accountName) does not exist. Therefore ASP.NET cannot be started. To overcome this, you can use the system account or you will need to explicitly define an account configured in the element of the machine.config file.

07 May 2004

CMS, work with template gallery in VS.NET

Symptom 1: On Loading Woodgrovenet.sln to VS.NET, there is complain: "Could not get the root template gallery"

Error message: The windows credentials provided could not be validated.

Reason: The user running Microsoft Visual Studio .NET is not in a Template Designer role or their role does not have access to the root template gallery. So need to run Site manager to add the current logon account as a Template Designer.

Symptom 2: Cannot modify Template Gallery Item
I am logon to NT and start a new CMS Web project with VS.NET. The NT logon I used was granted as Template Designer. I can see the whole project but cannot add/modify template gallery items.
Double check the Template Designer rights, found there isn’t Group rights granted to the project-top channel-http host header (same name).
After grant the rights explicitly, I can now Add/modify TGI in VS.NET.

06 May 2004

Accessing CMS sites off a root URL by sharing IP address and port number

In this scenario, we have a root IIS site and multiple CMS web application off this root on a development environment. Instead of configuring each into their own CMS environments, they share a same CMS db, users/roles scheme. So developers can easily switch between sites

The site structure looked like this:
http://mycms --IIS root
--WoodgroveNet --CMS –enable web app 1
--PetshopCom --CMS –enable web app 2
--WoodwidgetOrg --CMS –enable web app 3

Instead of accessing each by:

We want:

Here is how to achieve this:
Step 1. Make mycms CMS enabled
You can use MCMS SCA tool to assign read/write rights or manually map these virtual directories:
- NR((MCMS installation drive)\Program Files\Server\IIS_NR)
- MCMS((MCMS installation drive)\Program Files\Server\MCMS)
Copy ASP.NET Client API by run:
aspnet_regiis –c from the appropriate .Net framework directory. for v1.1 this is C:\WINNT\Microsoft.NET\Framework\v1.1.4322

You need to manually map IE Web Control API, SCA wouldn’t do it for you:
Create a virtual directory mycms/Webctrl_client that map to (IIS installation drive)\Inetpub\wwwroot\ webctrl_client

Step 2. Check and remove mycms Host Header Name if there is one.
In IIS Manager, mycms|properties(right click)|Web Site Tab Web Site Identification, click “Advanced”. Now into Advanced Multiple Web Site Configuration.
To remove it, select the entry then click “Edit”.

Step 3. Add multiple website.
Into Advanced Multiple Web Site Configuration, click on “Add”. Use the same IP address and Port you assign to mycms for WoodgroveNet, PetshopCom and WoodwidgetOrg.

Step 4. Update DNS hosts file
notepad c:\winnt\system32\drivers\etc\hosts
add this: mycms woodgrovenet PetshopCom WoodwidgetOrg
you should use the IP address you assign to mycms.

You are done.

30 April 2004

Microsoft CMS2002 installation notes

Install on Windows 2000 with .Net Framework 1.1 and VS.Net 2003

• To install CMS2002 SP1A you need to install CMS2002.
• If CMS dev tool (VS.NET client) is desired, you cannot just install CMS2002 on top of VS.NET 2003. It complains ‘VS.NET is not found’, you need to install VS.NET, including ‘Windows Component Update’.
• Followed the CMS2002 installation guide.
• Apply SP1A.

Install on Windows 2003 Server
• Remember to check IIS and Server side includes have been installed.
• Apply high security template if you haven’t have .Net Framework or VS.NET install. This is the best opportunities to do so.
• No need for IIS LockDown, that is build-in to IIS 6 on Win2k3.
• Install VS.Net(2002) including ‘Windows Component Update’, if CMS 2002 DEV tool is desired. The dev plug-in only workes on VS.Net 2002.
There is a known issue that you need to enable ASP and FPSE on IIS. Follow this:
• Framework 1.1 is installed when installing Win2k3.

If loop-back adapter is used and MCMS SCA, Public, Authoring sites are configured to use a non-default IP address,i.e. localhost, remember to update your DNS host file, and set internet connection option to bypass local address.

Install sample site Woodgrove Bank
Installation gone through OK but I have problems on hitting the site.

The first problem is about running ASP.NET on a Domain Controller
The server I use is configured as a Domain Controller (with Active Directory) -- Windows 2000 Advanced Server, .NET 1.1. Error page like this:

Access to the path "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\Woodgrove\9c4ac7bd\97d3c1c0\global.asax.xml" is denied.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

This doc offers a solution:
FIX: ASP.NET Does Not Work with the Default ASPNET Account on a Domain Controller

In practice, I use IWAM_(MachineName), instead of ASPNET. All security policies (Domain Controller Security Policy, Domain Security Policy, Local Security Policy) needed to be update to include IWAM_(MachineName) for Log on as a batch job as pointed out in the above.
Then add IWAM_(MachineName) with full control to physical directory C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files

Run iisreset.

Now I am getting a different error: missing SeImpersonatePrivilege

[COMException (0x80041b58)]
Microsoft.ContentManagement.Interop.Publishing.CmsHttpContextClass.Initialize(String currentUrl, String httpHostName, Int32 serverPort, Boolean isSecureServer, Int32 iisInstanceId, String remoteMachineAddress, String authenticationType, String authenticationToken, Int32 windowsUserHandle, String ClientAccountName) +0
Microsoft.ContentManagement.Publishing.CmsHttpContext.initialize(IntPtr windowsToken, String cmsAuthToken, String clientUserName, String clientAccountType) +297
Microsoft.ContentManagement.Publishing.CmsHttpContext.getCmsHttpContextFromIdentity(HttpContext httpContext) +1088
Microsoft.ContentManagement.Publishing.CmsHttpContext.get_Current() +57

As documented in CMS2002 SP1 MCMS 2002 - Debugging FAQ

The Account (IWAM_(MachineName) running the ASPNET_WP worker process is missing the SeImpersonatePrivilege privilege when Windows 2000 SP4 is installed.
There are two steps to resolve this problem:
1) Adding impersonation privileges to IWAM_(MachineName) or any account (such like ASPNET) that runs ASPNET_WP worker process. This can be done by adding ‘Impersonate a client after authentication’ to the account in Local Security Settings. Check Microsoft Content Management Server 2002 Service Pack 1 Documentation.

2) Update Machine.config and/or web.config
(c:\WINNT\Microsoft.NET\Framework\{version number}\CONFIG\Machine.config)
As I am running .NET Framework 1.1 for this, I use version v1.1.4322.
Find the ProcessModel node and update the username, password attribute to be
<processModel [other attributes] userName="<domain Name>\IWAM_(machineName)" password="(actual password)"

Wahoo, this problem gone. Now I can see the Woodgrove initial login page, which prompts me for login credentials-a bit strange. It says:
You are using an insecure connection. If you click Continue it will be possible for others to view information you send or receive.

I try to login using a few different identity CMS_SYSTEM, NT accounts that has been grant Author role. I also use IIS console manager to check the properties- directory security to be anonymous/window authentication--seemed fine.
Then I look up the Web.config – notice the authentication mode has been set to ‘forms’ like this:

<authentication mode="Forms">
<forms name="WoodgroveNet" path="/" loginUrl="/WoodgroveNet/Templates/ManualLogin.aspx"
protection="All" timeout="30" >
<allow users="*" />

I quickly comment out this and uncomment the Windows authentication mode
<authentication mode="Windows">

Finally got the site working!

19 April 2004

Code optimization

Newcomer has a very good essay on code optimization
In short:
1) The only valid path to optimization is by measuring the performance.
2) Be pragmatic, trivial performance gain doesn’t worth the risk of months work on complicated algorithm, danger of introducing new bugs and code maintenance difficulty.
3) Some looked ‘poor’ algorithm may have magnitude faster than ‘superior’ algorithm, depends on how a particular kernel works (memory paging, allocation method etc). Again, this will only known by benchmark.
4) Don’t bother with GUI code optimisation.

Executive summary: forget performance & optimisation as a developer.

13 April 2004

what does it try to authenticate?

It is a common practice to send user an email containing links to a dynamic generated page which challenges user for credentials. However, it becomes suspicious when the job only done half-way.

MPS online is a nice public service that enables one to register not to receive unsolicited posts. At the end of the registration, it asks for an email address which contains a link that will be required. I click the link; a page opens and acknowledges me registration completed.

All look fine. Wait a minute, what is the purpose of asking user to submit an email address? It only validates 'I' own the email account. If I want to, I can deregister my neighbour John Smith with my email, which may upset him if he loves those ‘bargain hunt’ kind of thing.

A second thought over it, I reckon, MPS probably just want to snap my email address as well -on top of the postal address I surrender for deregister. Ouch!

07 April 2004

Why we need test first development

Here is an other classic example. I bet it will be used in some book sooner or later, like Test Driven Development. Here is the story:
"The Chinook helicopters could be a risk to fly in cloudy weather because the software which enables them to do this cannot be properly tested.
Fixing the problem will cost an estimated �£127m and the Chinooks will remain grounded until at least 2007. "Read more...

02 April 2004

Convert a string into an enum

The problem was raised in a project about use type code.

There are numerous type tables in Party etc DB schemas. Many of them used Meaningful VARCHAR2 or number as primary key, such like ECAR, BANK, FIXE or 01, 02 etc.

To use these type codes, the obvious non-brainer way is to hardcode them directly.

Or the political correct yet unpractical way: to access the type table whenever needed.

A better hardcode way is to define them in Enum type and combined with client side type tables. But in this scenario we have a problem: PKs are not natural sequential numbers and we rely on the assigned Enum value. Like this:

enum Colour
Red = 100,
Green =103,
Blue =140,

The problem arise when serialize the enum type across the wire. Client deserialisation (dominanted by MS WSDL tool) engine will construct a

enum Colour

Hence we loss the value.

We did come up with type class idea, but it was quite verbose and boring to implement.

Tim Sneath demonstrates a handy way
to convert string to Enum by using Enum.Prase(…)

Memo: Transforming Dataset to Presentation

In a recent ASP.NET project, I need to retrieve a large blocks of relational data from backend present them in a 2D table. Issue here is data relation are multi-dimensional, involving more than 5 tables. And UI got some fancy buttons kinda thing as well. Data grid is not a viable solution.

Current implementation deploys XmlReader to build the table on the fly. Don't really like it, due to the fact logic code and presentation markup are mixed to produce a massive codebehind.

I am planning to shift this into a nice xml doc and transform it using xslt.

These stuff seemed quite useful:
The initiativesBest Practices for Representing XML in the .NET Framework

CreateNavigator Method

And XSLT Transformations with the XslTransform Class

01 April 2004

use NDoc for .net project documentation

NDoc, another powerful software engineering tool in the N* series. Use the command line tool should make it really easy to integrate with Nant for web base documetation publishing.

30 March 2004

Holiday Blue

Danni and I have spent a week holiday at Maldives. One of the most beautiful islands country with jade-like islands, easy access yet well protected coral reef, vast number of colourful fishes.

And now we are back with some suntan, lots of good memories, and some holiday blue.

I will try to sort out some photos and diaries for this.

19 March 2004

Bits and bobs on authoring Web Control

1. Default Tag Prefix.
By defalt VS.NET assign 'cc1'at run time (when the control is dropped to designer canvas). You can assign a different one by modifying AssemblyInfo.cs of the WebControl. Add following lines

using System.Web.UI;

leads to

[assembly: TagPrefixAttribute("JingyeLuo.IEWebControls", "luo")]

now 'luo' is used instead of 'cc1'

2. Associating custom bitmap with a web control
This will be the bitmap display in the Toolbox for a control
1) Create a 16x16 bitmap of 16 color and set its Build Action to Embedded Resource.
2) Add the ToolboxBitmap to the control class:

public class ExpandablePanel :

I have a bitmap called JingyeLuo.IEWebControls.ExpandablePanel.bmp and located in the folder 'Resources', the name is deliberated -if the bitmap is located at the same place of the control-there is no need for 2nd parameter:

public class ExpandablePanel :

ASP.NET Controls That Take Advantage of the DHTML Object Model – the initiatives

What I want: ASP.NET Web control that takes the advantage of DHTML Object Model.
The rendering should be browser independent. For IE3 and above, it should exploit DHTML with client side scripting, otherwise may require server side scripting. Dino Esposito has an article on this.
Be more specific I want to create two web controls:
1) Expandable DIV. Expand/Collapse that response to Onclick event.
2) Drag-able Table row. Response to onmousedown and onmouseup, enabling a quick table re-ordering. Dave Massy has an article on this.
Other User requirement support VS.NET HTML designer Drag and Drop;

18 March 2004

Using Client-side Script to Focus Controls in ASP.NET

In a web page contains a large number of controls (or virtually anything), it could be quite nasty to find out where were you all about after a postback or on finishing a subroutine. This article suggests a simple way to ‘bookmark’ the interested control by injecting dynamic client-scripting, which sets the focus on page load.

Here is a little sample on the idea. A web page with five buttons, all will do a postback. Focus varied depends on the button been clicked. Extend this idea, we can effectively bookmark anything, e.g. a large table required the use of scroll bar.

<!-- FocusContorl.aspx-->
<%@ Page language="c#" Codebehind="FocusContorl.aspx.cs" AutoEventWireup="false" Inherits="WebSamples.FocusContorl" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Button id="Button1" style="Z-INDEX: 101; LEFT: 104px; POSITION: absolute; TOP: 96px" runat="server"
Text="Button 1"></asp:Button>
<asp:Button id="Button2" style="Z-INDEX: 102; LEFT: 104px; POSITION: absolute; TOP: 152px" runat="server"
Text="Button 2"></asp:Button>
<asp:Button id="Button3" style="Z-INDEX: 103; LEFT: 104px; POSITION: absolute; TOP: 200px" runat="server"
Text="Button 3"></asp:Button>
<asp:Button id="Button4" style="Z-INDEX: 104; LEFT: 104px; POSITION: absolute; TOP: 248px" runat="server"
Text="Button 4"></asp:Button>
<asp:Button id="ButtonPostBack" style="Z-INDEX: 105; LEFT: 296px; POSITION: absolute; TOP: 328px"
runat="server" Text="PostBack"></asp:Button>

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebSamples
/// demostrates using dynamic client-script to set focus to a client control after a postback

public class FocusContorl : System.Web.UI.Page
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.WebControls.Button Button2;
protected System.Web.UI.WebControls.Button Button3;
protected System.Web.UI.WebControls.Button ButtonPostBack;
protected System.Web.UI.WebControls.Button Button4;

private void Page_Load(object sender, System.EventArgs e)
if (Request["callerControl"]!=null)
Label lb = new Label();
lb.Text = Request["callerControl"];

private void SetFocusControl(string controlName)
string dynamicScript = string.Format(@"",controlName);

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)

/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.

private void InitializeComponent()
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Button2.Click += new System.EventHandler(this.Button2_Click);
this.Button3.Click += new System.EventHandler(this.Button3_Click);
this.Button4.Click += new System.EventHandler(this.Button4_Click);
this.ButtonPostBack.Click += new System.EventHandler(this.ButtonPostBack_Click);
this.Load += new System.EventHandler(this.Page_Load);


private void ButtonPostBack_Click(object sender, System.EventArgs e)
private void Button4_Click(object sender, System.EventArgs e)
private void Button3_Click(object sender, System.EventArgs e)
private void Button2_Click(object sender, System.EventArgs e)
private void Button1_Click(object sender, System.EventArgs e)
private void RedirectPage(Control caller)

16 March 2004

new RSS

new Rss, well Atom added, if use SharpReader, it needed to be at least version


- George Orwell: Nineteen Eighty-Four, Chapter 1

What a penetrative and foresight wisdom.

It is worth to take a snap of what has happened as of March 2004 (that is almost 20 years after what Orwell’s fictitious story happened.

The background: War on Iraq a year on, led by Bush Administration and echoed with Blair ministry, Spain is the only other western European country sending their troops to Iraq.
A chain of terrorism bomb attacks killed 192 commuters and wounded 1500 in morning peak hours in Madrid last Thursday (11/03/2004).
Israel was suffering another round of human bomb attacks

NATO Umbrella Could Keep Spanish Troops in Iraq BRUSSELS (Reuters) - A UN-mandated NATO presence in Iraq could be a face-saving formula for Spain's incoming Socialist prime minister as allies put pressure on him not to withdraw troops from the country, diplomats said Tuesday.

Israel Prepares to Strike Back for Bombing JERUSALEM (Reuters) - Israel's inner cabinet approved major raids into the Gaza Strip and the killing of top militants Tuesday in retaliation for a Palestinian suicide bombing at a strategic port, security sources said.

Suspected Russia Gas Blast Kills 21; 20 Missing MOSCOW (Reuters) - A suspected gas blast flattened part of a large apartment block in northern Russia early on Tuesday, killing at least 21 people, including two children, and trapping about 20 more beneath the rubble.

White House to Kerry: We Want Names
FOX News Bush administration officials on Monday continued to press Kerry to say exactly what international leaders have told the presumed Democratic presidential nominee privately that they back his candidacy to oust President Bush.

London terror attack 'inevitable'
(BBC) The police chief was speaking in central London A terror attack on London is inevitable, Metropolitan Police commissioner Sir John Stevens has said.

Do I have too much time to care about what is going on in the world?

Nikonos workshop

Nikonos workshop looked like a very good supplement to Nikonos Instruction Manual

11 March 2004

Shafting people boosts morale

It is a mind game.
Abuse your co-worker should be in subtle and different ways. To your peer, you should at least gain knowledge advance-or pretend you have-and pose yourself as a master or guru. To your boss, you should be more like a victim of his/her misbehaving. To contractors, do as you like. They are there for some reasons.
And watch your morale index rise.

10 March 2004

Game of the day

Just cann't let go on this game
Warthog Launch. Now level 11.

09 March 2004

Teach Yourself Programming in Ten Years

This reminds me what is the ultimate drive be in this career.
Teach Yourself Programming in Ten Years:

We're not here to do the decent thing

We're not here to do the decent thing, we're here to follow f***ing orders - Captain Miller, Saving Private Ryan

A week now since our .Net project got shelving. People are suffering for their low point. Matt and Gary were mostly not in the office. Lynn, Nick, Paul and myself were in but we are surfing most of the time. Not that many conversation or gossip, just been quiet. I was very quiet.

Tried to focus and do some reading so to take the advantage of the project gap, but it was hard to focus. I seemed more productive in the 20 minutes train commuting than the rest of the day. Regular monitoring Ebay for the diving gadgets as my partner and myself are going to Maldives in two weeks time.

Watched Save Private Ryan probably for the third time last Sunday. It still strikes me for the bloodiness, cruelness of war and breadth of humanity.

An elite team set off to search Private Ryan and it was the high command’s order to bring him home safely as he lost three brothers in the war. It is a difficult order. And people question the rationale of risk more people’s lives for this. To the soldiers in the team, James Ryan is just a name, while Caparzo is a brother. Without looking at the bigger map, it is hard to accept and act on it positively.

This brought me to think of the current situation of developers, management team as command officers and the company as about to change hand. You know, like selling off your car 2nd hand. You probably don’t want to add satellite navigation system but give it a full service and polish it a bit.

I told Danni I am going to cheer up and be more positive from this week. For whatever project I will be assigned to, most likely a big fix to legacy system- dark age of vi and C on Unix, I will be happily get on with it.

Like stuck in a missing boat, we don’t know where captain is going take us to. It didn’t look promising and probably it never will. And it is beyond us to influence the decision-making.

There are two things we can do if immediately work out is not an option:
1) Positively do whatever we are told and hope we will shored sometime although it may still sink by the end.
2) Passively do it with mourning until it sinks or lucky shored.

Regardless the result, I will definitely be more happy by enjoying my work.

08 March 2004

back again

Haven’t been blogged for a really long time, feel like a deep dive. This is partly due to the then on-going project had drained most of my time, partly I was enjoyed it too much to share.
Now get back to where I was been left off since last time I blogged during a project gap.
Lots of things happened in this 3-4 months time:
Got a sparking .NET Windows Form project to work on with a group of really enthusiastic people;
Brought our first house and applied eXtreme Programming methodology on DIY deco to guarantee a delivery;
the employer is up for sale (still on going);
4 weeks to live pilot and the .NET project got caned due to business interest changed--yet another one;

There are lots of thing I shall write down before they fading away. To some people, blog is a convoy to share knowledge; to some it is a place to show off; to many others, like me, it is a memory dump and natural healing at low-point.

I shall pick up my old friend for now, until another challenge arrives and I will be doing deep dive again.