Wednesday, March 26, 2008

HTTP requests from the future


These days I'm working on a DotNetNuke (DNN) based Portal development. Our development env is IIS 5.1/XP while our deployment env is IIS 6/Win 2003. During our past 2 deployments we encountered a strange error on IIS 6/Win2003. Soon after the deployment every page in our portal solution spits a java script error 'Sys is undefined'. This is an error related to the ScriptManager.js which is needed in Ajax pages. There were dozens of google search results for this error pointing fingers to IIS, web.config file settings, axd file handlings, Ajax java scripts etc...but we just couldn't figure out the solution quickly enough. After a late night struggle we gave up and decided to check it the day after. When we came and check next day, the problem has got fixed by itself overnight :).

I always know when problems starts to get fixed by themselves it's a warning sign for worst things ahead. But I just could not reproduce the problem to study it that day. So we went happily in to our final deployment yesterday and here we again had the good old error 'Sys is undefined'. This time around we dig down and went in to analyzing this in depth. When we looked at the HTTP response for a page 2 requests for a ScriptResource.axd files were having HTTP 500 codes. (Read about .axd files here ). When I used fiddler to analyze the HTTP response in detail we caught up with the message
"System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: utcDate". Eureka!!!

Now we knew that the problem has to be something to do with the time. In every ScriptResource.axd request there are 2 parameters being sent. Eg : ScriptResource.axd?
d=8fBiB6-cb_63xIkOjfdl6BCL-uzAt8lEaJgT8GHfNac0VUzhoOSl_j9ebDYDA0Ao0
&t=633420390180000000
The 'd' param is relevant to data it is asking for and the other 't' reflects the time which the resource was built. (Use this tool to decrypt axd requests). The problem was that our win 2k3 servers time was not accurate and it actually resided in the past ( A few hours). Thus the axd request was seen by the server as requests coming from something which was built in the future.
After the problem was identified the root cause finding was not difficult. Our win2k3 time synchronizing service had a problem. Now we were able to think back and understand why this problem got fixed on it's own the last time :). The problem just slept over it till the server time difference was consumed. Isn't that a nice way to solve problems....just sleep over it :)

Labels:

Sunday, March 09, 2008

Continuous Documentation cont...

As it usually happens, after going through all the troubles to have a continuous documentation happening (see previous post) in my project I found out a much easier way to achieve the same. While the previous post concentrated on purely using the native sandcastle xsl files to apply several xml/xsl transforms using Nant, the new easier method will rely on the very useful tool 'Sandcastle Help File Builder' or SHFB as it's also known. You need to download and install SHFB in both your local machine and the build machine. ( It would be better to breeze through my previous post before you go through this)

Let me run through the simple steps involved in this method.
1. Open up SHFB in your local machine and configure it to generate the documentation to your project.
2. Some important steps in configuring the SHFB are,
  • Adding the assembly and the documentation xml (Generated from the Nant -doc attribute as mentioned int he previous post) for documentation
  • Adding the dependent assemblies needed to build the main assembly
  • Choose the helpfile format (I choose Help2xAndWebSite)
  • Set HtmlHelp2xCompiler Path (Where you have installed HTML Help Workshop, see previous post)
  • Set output path
3. Build the SHFB project and let the documentation to generate
Now you will have the documentation files (html, chm) in your local machine, which is not our target. We want the documentation to build periodically, automatically in our build machine. Patience....2 more steps.
4. Now save your SHFB project and you will find a SHFB configuration file. Get it copied to your build machine.
5. Now include the following task tag in to your ccnet documentation project (other project tags are not mentioned here) and you are ALL SET to have continuous documentation running in your project.

<tasks> <exec> <executable>C:Program FilesEWSoftwareSandcastle Help File BuilderSandcastleBuilderConsole.exe</executable> <baseDirectory>D:WorkDirSandcastleWorkDirSPNPortalDocumentation</baseDirectory> <buildArgs>"D:WorkDirSandcastleWorkDirSPNPortalDocumentationDocumentationSettings.shfb"</buildArgs> <buildTimeoutSeconds>10800</buildTimeoutSeconds> </exec>

</tasks>

Pay attention to the 'buildArgs' element where you specify where the shfb configuration file can be found.

Labels: ,

Friday, January 18, 2008

Continuous Documentation















Continous Integration (CI) is not a new topic anymore. It has been a proven method to make sure your code works as expected every single time you do a change to it. Usually a CI process focused on building a project (Deployment might involve more steps) involves steps like,

1. Detect changes to the source
2. Download the updated source from source control to the build machine
3. Compile the source and build the binaries
4. Run the unit test suite
5. Publish the result to relevant people

The additional step I'm going to focus in this posting is documentation. i.e To generate the documentation for the complete source automatically using the CI tool, which I prefer to call 'Continuous Documentation'. My focus will be on ways and technologies to achieve this in the Microsoft technology domain.

The most popular documentation generation tool for .Net is Sandcastle. The way to achieve our target is to write a Nant target which produces the documentation in either html or chm format and to call this Nant target at an appropriate time from CruiseControl.Net (CruiseControl.Net is the build scheduler while Nant is the actual builder).

Most of the learnings on how exactly to do this is from this article on code project. There were some discrepancies in that article with respect to latest SandCastle version and I'd like to emphasize on those points. (To keep the post short only important nant extracts are mentioned in the post it self. The complete Nant target will be attached for your convinience)

1. Compile your source with the additional 'doc' attribute to 'csc' (C-Sharp compile) nant target.
Eg:

<csc target="library" debug="${debug}" output="${foo.dll.dir}\foo.dll" doc="${foo.dll.dir}\SPN.PredatorAPIDoc.xml" >

2. Copy a Sandcaslte configuration file from the default configurations that comes with Sandcastle. You just have to replace the default documentations comments xml with your own doc xml 'fooDoc.xml' generated from previous step. Sandcastle comes with 3 default configurations hana, vs2005 & prototype. I'm using vs2005 here. (Instead you can have the required sandcastle config file in your source and refer it as well)


3. Run the MrefBuilder to generate a basic reflection XML by introspecting on the assemply

<exec program="${sandcastle.mrefbuilder.exe}" workingdir="${sandcastle.workingdir}">
<arg value="..\${foo.dll.dir}/foo.dll" />
<arg value="/out:reflection.org1.xml" />
<arg value="/dep:..\foo.Lib/*.dll" />
</exec>



4. Next step is to run a step of xmltransformations (using xsl) on this basic reflection xml from the preivious step
<exec program="${sandcastle.xsltransform.exe}" workingdir="${sandcastle.workingdir}">
<arg value="reflection.org1.xml" />
<arg value="/xsl:"{sandcastle.applyvsdocmodel.xsl}" />
<arg value="/out:reflection.org2.xml" />
</exec>

Similar to above you need to run a few more transformations and you can also run some additional transformations as you wish. (Eg : FriendlyFileNames.xsl). There are many presentation transformations in ProductionTransforms subfolder in Sandcastle installation directory. I faced some difficulties getting all these transformation mentioned in the code project article to work. My approach was to refer the example MS Build script (<SandCastle_Install_dir>\Examples\sandcastle\build.proj) which was shipped with Sandcastle and to convert the transformations mentioned there to Nant.

This step (or series of steps) should result from a final reflection file called the reflection.xml

5. Now copy the other presentation helper directories (scripts, icons, styles) from Sandcastle_installation_dir/Presentation/vs2005 in to a subdir inside ${sandcastle.workingdir}.

6. Next you need to create some source files for Help compiler which generates a chm file. These files are

* hhp file - Html Help Project file
* toc.xml - Table of Contents file
* hhc file - Chm contents file out of toc
* hhk file - Chm index file from the final reflection xml

For all the above you will be using some kind of xml transformation (xsl) which comes with sandcastle.

7. And the grand final step is to use Html Help Workshop's hhc.exe help compiler to compile all above files in to a single chm file


<exec program="${hhc.exe}"
commandline=".\test.hhp"
workingdir="${sandcastle.output.dir}"
failonerror="false"/$gt;

Finally you will have a chm file which is the compiled help file which can be distributed with your application.

Since documentation generations is usually a time-taking process I suggest you run this nant target as a nightly task. So you have the documentation getting updated each day as opposed to each check-in. Use the <triggger> block of CC.Net to schedule this documentation task as a separate CC.Net project which runs every night.


Having the documentation up-to-date like this helps your project in several ways.

1. You have a ready to pack deliverable without any extra effort at the end of the project
2. You can send the documentation for review very early
3. The development team can readily refer the documentation as and when new parts are added to the system
4. Encourages developers to document as and when they code

PS : The complete Nant script can be found here.

Labels: , , , ,

Thursday, January 03, 2008

Visit to Sandefjord, Norway

As per a request by one of our clients in Norway, me together with 3 other engineers had to travel to Southern Norway to a small city called Sandefjord. We stayed there for a period of 4 weeks during the month of September. This was my first exposure to winter like weather and it was luckily not the fully fledged winter but the autumn.

We were working on a potential Portal project for our customer 'System Partner Norge AS' (SPN). SPN is a Software Product vendor for a very popular credit management system called 'Predator'. The initial study of their requirements together with the knowledge about their internal systems were acquired during our stay.

The working conditions in Norway is much different to what we have here in Sri Lanka. It's kind of small office based arrangements as opposed to tiny cubicles we have at Sri Lanka. The people are somewhat reserved but once you get to know them they seem to be friendly and kind. The facilities you find in SPN is of very high quality as oppose to an normal Sri Lankan software firm. Also the outside environment close to the harbor and protected camping area make it much more pleasing to the eye compared to the busy, smoking cities like Colombo & Bangalore. All in all Norway is a pretty good country to live & work if not for the cold weather.

During this visit I was able to travel briefly to some other European cities as well like Amsterdam, Fedrickshavn (Denmark), Stromstaud (Sweden). It was a really novel experience for me to travel on a ferry and the overnight journey to Denmark will never be forgotten.



SPN Office near the harbor


Overlooking SPN from the sea


Our customer Hans with me & my co-engineer Chatura

Powered by ScribeFire.

Labels: ,

Friday, August 03, 2007

DNN Schedulers

Writing scheduled tasks in ASP.Net is not a trivial thing. For a start, I haven't written any. So when we had to design a scheduler for Dot Net Nuke (DNN) it appeared even more daunting. DNN is a portal framework built on top of ASP.Net and its the underneath framework being used for the current project I'm working on.

The problem with ASP.Net scheduling is the fact that the ASP.Net worker process gets recycled every now and then. So once the worker process goes down (shutting down any schedulers with it) it will not be up again until someone hits the web site again.  Someone had also suggested writing windows services which operates independent of ASP.Net as schedulers. The recycling of the worker process is a very important feature in ASP.net which enables the server not to be taken down by runaway applications.  But one downside of this is the impact to the scheduler. But as long as someone is visiting your web site the scheduler will keep on running.

Lucky for me DNN had an inbuilt scheduling engine.  This had almost all the features you would want from a scheduler. It has a easy to implement interface for me write my own scheduling tasks (DotNetNuke.Services.Scheduling.Scheduler interface in DotNetNuke.DNNScheduler.DLL), It has easy to use interfaces for me to configure it and it also provides history views for me to check how my scheduler was performing its tasks.

It was pretty easy for me to implement a simple test scheduler according to DNN documentation. I just have to wait and see what kind of complications could arrive when I implement the real scheduler which is to migrate potential DNN users from a legacy system to the DNN portal on a daily basis.

Labels:

Wednesday, May 23, 2007

Re-Learning java scripts

For my current project of a credit management portal I had to re-visit java scripts to perform some client side validations. I have never got the chance to do JavaScripts with ASP.Net 2.0 and every simple damn thing abt those 2 technologies together was foreign to me and I had to learn from scratch. Thought I should just jot down a few things I've learnt along the way.

    1. Internationalizing the javascript messages 
      You can attach java scripts to the page at server side as oppose to writing the whole thing in the html page (or seperate java script file) it self as we use to. So at the server side u have all the localizations tools/APIs in your hand and you can pump localized content in to your javascript.     
      string javaScriptString = 'blah blah blah ' + Localization.GetString('Key',LocalResourceFile) Page.ClientScript.RegisterClientScriptBlock (this.GetType(),'NameOfScript',javaScriptString);
    2. Prevent Postback of a page                                           Again adding java scripts to client side events can be done at the server side.
      TextBox1.Attributes.Add('OnClick', 'showHelp') will call the showHelp javascript once the button is clicked by the user. But what happens by default is that the page anyway is sent to the server as a post back. In order to prevent it the attribute should be added as follows.
      TextBox1.Attributes.Add('OnClick','return showHelp').
      In this instance if the showHelp function returns false, the page will not be posted back.

Attaching the javascript to the page at server side and having event handlers bind at server side are two simple yet useful tricks I learnt. You can increse the flexibility of your event handling model (Eg: You can add and remove the attributes from a control based on server side logic) with this easily.

With the popularization of Ajax on web the importance of learning java scripts is again emphasized to the developer community.

Labels:

Friday, April 20, 2007

Debugging VC++ dlls from .Net

In my current project we have to use a legacy VC++ dll to be called from our .Net assemblies. In addition I needed to be able to debug the C++ code from my .Net assembly project.

I found out that there are certain simple steps to carry out in order to achieve this.

1. Make the necessary functions in C++ exportable.

2. Make your C++ dll debuggable. You have to build the project on DEBUG configuration in order to that. There will be debug symbol files like .pdb being generated.

3. Now declare the calling method signature in your .Net code as follows inside the class.

[DllImport ../VCPlusProject/bin/Debug/VCPlus.dll", EntryPoint = "VCPlusMethodToCall", SetLastError = true)]
public static extern bool IsMethodCalled(int param)

4. The implemented method will be a normal .Net method as follows.

bool sucess = VCPlusMethodToCall(10);

Now everything is ready to let the cat out of the bag!

5. Start the VS.Net project in debug mode and try to debug in to the "VCPlusMethodToCall" method. The VC++ code will be debuggable inside VS.Net.

Neat...huh????

Labels:

Thursday, March 22, 2007

Uninstall the Uninstallers - $NtUninstall

Recently I ran out of my C drive space. The whole Microsoft package of Windows, Office, Visual Studio, Sql Server is way too much for my space capabilities.

Anyway I needed to check how I can free some space on C since I don't have much faith in Partition Magic when I have ard 20GB of data in my C drive.

What I noticed was the existance of a lot of $NTUninstall folders in my windows directory. These contain the uninstall information for all the hotfixes that Microsoft sends out each and everyday. It has consumed nearly 500 MB of my precious disk space.  You can go ahead and change them manually as described here, but I'm too old to do that so went for this tool which does it for me.

You should know a few things before u let the tool does its magic.

  1. This removal process is one-way. It can not be undone
  2. You have to purchase the licence to remove hotfixes selectevly, otherwise all hot fixes will be removed
  3. You will not notice the space gain for some time since backup files are protected by System restore

"As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality"

- Albert Einstein

Labels:

Monday, January 29, 2007

No more back button

Browser back button is a very common problem child in many web systems. Ours is no different. A simple search turned out so many different ways to tackle this problem. Some selected simple options are explained below. The thing to keep in mind here is that a determined user can still get around the solutions pretty easily. So while being simple these methods do not provide a 100% gurantee.

Almost all of this methods tackle the problem by disabling or nullifying the effect of the back button by some hack.

1. Disable browser cache - This will make the browser send a response to the server to each back button request.  Found the IE way of doing it using ASP.Net page directive 'output cache', don't think this works for FF. (http://msdn2.microsoft.com/en-us/library/hdxfb6cy.aspx). Or else you can use the html meta tags to achieve the same thing.

<html>
<head>
  <meta http-equiv="Expires" content="0">
  <meta http-equiv="Cache-Control" content="no-cache">
  <meta http-equiv="Pragma" content="no-cache">
</head>

2. Disable the user returning to the previous page by always making the browser history increment by one whenever a page load. (So the previous page = current page) using the javascript windows.history.forward(1) execute in each page you don't want to add to history.

<script language="javascript" type="text/javascript">
          window.history.forward(1);
</script>

This should be added to the head of the page so that it gets executed each time the page loads. Do not perform the first option of disabling the cache if u go for this option as it makes IE confuse. This is the one which worked for me.

3. Invoke a new page using location.replace.

<a href="next.aspx" onclick="javascript:location.replace(this.href);  event.returnValue=false; event.cancelBubble=true;">
Click here to visit the next page without adding the current page to the history folder.
</a>

This will prevent the browser from adding the initial page to the history when u r navigating between pages. But if u want this to work with the postbacks then u have to use this along side window.history.forward method.

Labels:

Wednesday, December 20, 2006

Connect IIS to SQL 2005

After the initial R&D work is over in our web application we have to transfer our web site from cassiny to IIS.

The first problem we encounter is that our web app stoped talking to SQL Server with the problem, "An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections."

Due to this reason I looked at the ways a web server (IIS) can connect to SQL server and found 4 generic ways.

  1. Using windows integrated security
  2. Mapped windows domain user
  3. Using a connection string
  4. As a local user

Our web application actually uses the connection string to communicate with the SQL Server.  But in order to convince SQL server that this connection request comes from a valid party u need to have an initial access to the DB. That can be done by using impersonation.

What u need to do is to Map IIS anonymous user to a mapped domain user which is trusted by the DB server. This scenario is evident when u have the DB server and Web server in two different machines.

In the web.config put the following entry

<identity impersonate="true" userName="domain\username" password="password"/>

You also need to add this domain user to the SQL server with the necessary rights.

More info can be found in in MSDN.

 

 

Labels:

Tuesday, November 21, 2006

Modal Dialogs in Web

It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure. Basic professional ethics would instead require him to write a DestroyCity procedure, to which Baghdad could be given as a parameter.
(Nathaniel S Borenstein)

Modal dialogs are pretty common in WIN environment. These are used when u want some user input before u proceed with the main flow of the application. The basic difference between a normal dialog box and a modal dialog is that u cant do any operation in the window that opened the modal window till u complete (or close) the modal window.  There's a lot of debate on when to use modal dialogs and I found the first couple of paras of this article
useful.

As a POC for our new project which is to port a complete reporting application from WIN to WEB me & one of my colleagus got the chance to try out this modal dialog in Web.  In IE you have window.showModalDialog('url','windowName','windowProps') java script function which gives u a modal window. But in Firefox this does NOT work. You can partially achieve the modal behaviour by giving a third param to the window.open function modal=yes. This will keep the focus on the new dialog but user can still interact with the underneath parent window. Check out this blog entry by David Kasper for a detailed discussion.

There were some other requirements with this modal dialog.
1. Make sure it pops automatically after a certain postback event.
2. To be able to update backend domain objects from the modal dialog it self.
3. To inform the parent window about the operation that was performed in the modal dialog.

Since we're using ASP.Net 2.0 here's a briefing about how to do above using ASP.Net 2.0.

Popping Back automatically upon postback
You just have to include the modal dialog showing function string as a start up script using ClientScript.RegisterStartupScript function. (status = window.showModalDialog(url,'DlgName');)

Updating bkend domain objects
This was a pretty hard thing to do since the calling of the usual __postback javascript function didn't work as expected.

Communicating with the parent
This is again somewhat tricky. Specially if u've done this seamlessly with multiple browser windows, u r in for a surprise here.  Unlike with multiple browser windows u cant pass multiple value from child to parent using window.opener.... Instead you'll solely has to rely on window.returnValue to send something back to the parent. The hack of passing multiple values is to set this with an array and breaking down that array in the parent.

This is the first time I'm in a web project in my breif programming career and things seems interesting as ever.

Labels: