Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5

Working hard to enrich millions of peoples' lives



I was
Co-Founder and CTO of Pageflakes, acquired by LiveUniverse - founded by MySpace founder.

I am
Chief Architect, SaaS Platform, British Telecom

I will be
Chief Architect, Mi...

Follow omaralzabir on Twitter

My Public Page

View Omar AL Zabir's profile on LinkedIn

Read my blog on:

Omar AL Zabir


Open source projects

October 2007 - Posts Ajax under the hood secrets

I have published a new article in codeproject: Ajax under the hood secrets

You will find the following tricks on it:

  • Batch call advantages and disadvantages
  • Implement auto retry in all web method call by modifying Ajax core framework
  • Implement queue based web method call in order to prevent browser from getting stuck with too many Ajax calls
  • Caching web method response, fix bug in 2.0 cache header problem
  • How slow is Http Post, capture data transfer over the wire and see

Some of the techniques may be known to you if you have read my earlier posts. But I have converted all code to the latest Ajax Beta 2 version which is not available in the blog posts.

Please rate the article if you like it at codeproject.

Also please digg this article.


Posted: Oct 31 2007, 08:53 PM by oazabir | with no comments
Filed under: ,
Reduce large website build time in Visual Studio 2005

When you have a pretty large web site in Visual Studio 2005, the site build time grows dramatically and it becomes very difficult to change code and then hit F5 (or Ctrl+Shift+B) in order to see if the project builds properly or not. In Pageflakes, we have a giant web site. It takes so long to build the site that we generally issue the build command, go to kitchen and make a cup of tea, drink it, come back and see the site still building. Generally when we do this 20 to 30 times per day, we start feeling sick (not because of VS 2005 instead of too much tea).

Here's a cool idea we tried. You can make folders hidden by going to Windows Explorer, go to Folder properties, check mark "Hidden" and click OK and then select "Apply to current item only". This will make the folder hidden and the folder will disappear from Windows Explorer unless you have turned on the option to show hidden files and folders. You will also see the folders disappeared from Visual Studio. Now we use Total Commander instead of Windows Explorer so hidden folders are not a problem to us. Bascially none of us remember anymore how to use Windows Explorer because we are so used to Total Commander now. Try it, it will change your life.

When you make folders hidden, Visual Studio will not build them! So you can make App_Data, App_Themes, images, stylesheets, javascripts, html files hidden and Visual Studio will skip them. Around 70% of our web site is non C# code. So, we gained dramatical reduction in web site build time by trying this idea. Another idea is to move all classes from App_Code to external DLL project. Thus they will build once and VS will not build them again and again if you make some changes in some codebehind file or some .aspx or .ascx file. This will also give you significant build time reduction.

Of course you can turn off Build Website and use Build Page option. But that does not help. We want to ensure the web site code is not broken due to any change. So, we need Build Website option.

Posted: Oct 31 2007, 08:48 PM by oazabir | with no comments
Filed under:
Automated website deployment using Powershell

I published an article which automates website deployment.

The Powershell script does the following for you:

· Maintains different configuration information for different deployments. For example, different connection strings for development servers and production servers (one or more production servers).

· Creates a deployment folder using the deployment date, time, and version so that you have a separate folder for each deployment and can keep track of things deployed on a day, e.g., 20061214-1.

· Copies only the change files and some predefined files to the deployment folder. So, you don't deploy the whole website every day.

· Copies the web.config and customizes the <appSettings>, <connectionString>, <assemblies> etc., as per the deployment configuration. For example, you can have different connection strings for different servers.

· Updates all JavaScript files with a version number so that in every deployment, a new file gets downloaded by client browsers.

· Updates default.aspx automatically with the modified script file name.

· Compresses all JavaScript files that gets deployed.

· Compresses all static HTML files using an Absolute HTML Optimizer.

· Creates a zip file which contains the deployment package.

· FTP the zip file to a target server.

So all you need to do is, run the script, extract the zip on server and voila!

If you like it, please vote for me.


Posted: Oct 31 2007, 08:31 PM by oazabir | with no comments
Filed under:
ASP.NET Ajax in-depth performance analysis

Let's do some ASP.NET AJAX runtime analysis on a website Those who don't know what it is, it's an open source Web Portal I made using ASP.NET Ajax, .NET 3.0 and Linq.

ASP.NET Ajax has a pretty big runtime which consists of Core Framework, scripts for UpdatePanel, Preview Script required for Drag & Drop. Additionally I need Ajax Control Toolkit (ACT). All these add up to a staggering 564 KB of download in 12 script references on the page. The download size mostly depends on the usage of extenders and Ajax features. A moderate use of extender results in the following download:

Here’s a simulation of 256kbps internet speed on 200ms network latency. I use a tool named Charles ( to capture traffic and simulate slow internet speed by throttling data transfer speed. From the durations, we see almost 20 sec is spent on downloading the runtime over a 256kbps line!

Let’s explain which script in the above list does what. I will be identifying the scripts using their file size in order of their appearance:

  • 21.64 KB – Handy script for Postbacks
  • 83.38 KB – Microsoft Ajax Core runtime
  • 30.16 KB - UpdatePanel, partial update, asynchronous postback scripts.
  • 136.38 KB – Preview version of Ajax which allows Drag & Drop script
  • 36.02 KB – The actual drag & drop script in Preview library
  • 45.25 KB – Ajax Control Toolkit
  • 4.08 KB – Timer script
  • 140.86 KB – ACT Animation framework
  • 18.05 KB – ACT Behavior base implementation. Required for Behaviors provided in the Ajax Control Toolkit project.
  • 16.48 KB – ACT Animation Behavior
  • 7.32 KB – My Custom Drag Drop behavior
  • 9.73 KB – My Custom Floating Behavior

The total payload for only the runtime is too high to accept because we cannot make a user wait for 20 sec just to download Ajax scripts before user can actually start interacting on the page. So, I took several approaches to reduce the size of the download:

  • Eliminate Preview version of Ajax completely and use ACT for Drag & Drop
  • Use IIS 6 compression to deliver compressed scripts from the client
  • Combine multiple script files into one file

ACT comes with its own DragDropManager which we need for Drag & Drop. So far I thought of using Sys.Preview.UI.DragDropManager in the ASP.NET Ajax January CTP. But just for the DragDropManager, I need to add nearly 180 KB of scripts for the entire Preview Library runtime. If I use ACT’s DrgaDropManager, I can get rid of the Preview runtime.

Without the preview scripts, the scripts downloaded are:

The following downloads are missing here:

  • 136.38 KB – Preview version of Ajax which allows Drag & Drop script
  • 36.02 KB – The actual drag & drop script in Preview library

I saved about 180 KB, nearly 7 sec from total download. So, user gets to work on the page 7 secs earlier than before.

When I enabled IIS 6 compression, the situation improved dramatically. Here’s the data transfers when compression is enabled:

The total download comes down from 448 KB to 163 KB! Total 64% download bytes reduction! This results in 3 times faster page download.

The scripts are downloaded in two steps – first the core runtimes download and then ACT and other scripts download. The content is displayed after the core runtime is downloaded. So, the time it takes to show the content on the browser reduces significantly because now it takes only 50KB to download before something is visible on the screen compared to 130 KB on non-compressed mode.

ScriptManager control has LoadScriptsBeforeUI property which you can set to “False” in order to postpone several script downloads after the content is downloaded. This adds the script references end of the <body> tag. As a result, you see the content first and then the additional scripts, exteders, ACT scripts get downloaded and initialized.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" LoadScriptsBeforeUI="false" ScriptMode="Release"> ... </asp:ScriptManager>

You can explicitly set ScriptMode=false in order to emit release mode highly optimized Ajax runtime scripts during local debugging.

Posted: Oct 27 2007, 10:37 AM by oazabir | with no comments
Filed under: ,
Safe COM: Managed Disposable Strongly Typed safe wrapper to late bound COM

There are several problems using COM from .NET:

  • You cannot implement the Dispose pattern by utilizing the "using" block in order to safely dispose COM references.
  • You cannot guaranty COM references are finalized. There's no way to implement "~Destructor()" for COM references.
  • COM reference is not released when a call to Marshal.ReleaseComObject is skipped due to an Exception.
  • When you "Add Reference..." to a COM library, the reference is version specific. So, if you add a reference to the Office 2003 COM library, it does not work properly when deployed to Office 2000.
  • The only solution to version independent COM is to use Late Bound operations but you miss all the features of a strongly typed language.

Let's solve all these problems. We want to use a Managed strongly typed approach to Late Bound COM operations and also utilize the Dispose pattern on COM objects. The solution proposed here works for any COM object which can be Microsoft Office COM libraries, IE & DHTML objects and even your own COM objects. You should use this approach whenever you are dealing with any type of COM library.

If you like this solution, please vote for me.

Posted: Oct 25 2007, 02:47 PM by oazabir | with no comments
Filed under: ,
ASP.NET Ajax Extender for multi-column widget drag & drop

My open source Ajax Start Page has an ASP.NET Ajax Extender which provides multi-column drag & drop for widgets. It allows reordering of widgets on the same column and also drag & drop between column. It also supports client side notification so that you can call web service and store the position of the widgets behind the scene without (async) postback.

I first thought of going for a plain vanilla Javascript based solution for drag & drop. It requires less code, less architectural complexity and provides better speed. Another reason was the high learning curve for making Extenders in proper way in Ajax given that there’s hardly any documentation available on the web (during the time of writing this blog). However, writing a proper extender which pushes Ajax to the limit is a very good way to learn under-the-hood secrets of Ajax framework itself. So, the two extenders I will introduce here will tell you almost everything you need to know about Ajax Extenders.

Ajax Control Toolkit comes with a DragPanel extender which I could use to provide drag & drop support to panels. It also has a ReorderList control which I could use to provide reordering of items in a single list. Widgets are basically panels that flow vertically in each column. So, it might be possible that I could create reorder list in each column and use the DragPanel to drag the widgets. But I could not use ReorderList because:

  • ReorderList strictly uses Html Table to render its items in a column. I have no table inside the columns. Only one Panel is there inside an UpdatePanel.
  • ReorderList takes a Drag Handle template and creates a drag handle for each item at runtime. I already have drag handle created inside a Widget which is the widget header. So, I cannot allow ReorderList to create another drag handle.
  • I need client side callback on drag & drop so that I can make Ajax calls and persist the widget positions. The callback must give me the Panel where the widget is dropped, which is dropped and at what position.


Next challenge is with the DragPanel extender. The default implement of Drag & Drop in Ajax Control Toolkit has some problems:

  • When you start dragging, the item becomes absolutely positioned, but when you drop it, it does not become static positioned. There's a small hack needed for restoring the original position to "static".
  • It does not put the dragging item on top of all items. As a result, when you start dragging, you see the item being dragged below other items which makes the drag get stuck especially when there's an IFRAME.

So, I have made a CustomDragDropExtender and a CustomFloatingExtender. CustomDragDropExtender is for the column containers where widgets are placed. It provides the reordering support. You can attach this extender to any Panel control.

Here's how you can attach this extender to any Panel and make that Panel support drag & drop of Widgets:  

   1: <asp:Panel ID="LeftPanel" runat="server"  class="widget_holder" columnNo="0">
   2:         <div id="DropCue1" class="widget_dropcue">
   3:         </div>
   4: </asp:Panel>
   6: <cdd:CustomDragDropExtender ID="CustomDragDropExtender1" 
   7:     runat="server" 
   8:     TargetControlID="LeftPanel"
   9:     DragItemClass="widget" 
  10:     DragItemHandleClass="widget_header" 
  11:     DropCueID="DropCue1"
  12:     OnClientDrop="onDrop" />

<cdd:CustomDragDropExtender> offers the following properties:

  • TargetControlID – ID of the Panel which becomes the Drop zone
  • DragItemClass – All child elements inside the Panel having this class will become draggable. E.g. Widget DIV has this class so that it can become draggable.
  • DragItemHandleClass – Any child element having this class inside the draggable elements will become the drag handle for the draggable element. E.g. Widget Header area has this class, so it acts as the drag handle for the Widget.
  • DropCueID – ID of an element inside the Panel which acts as Drop Cue.
  • OnClientDrop – Name of a Javascript function which is called when widget is dropped on the Panel.

LeftPanel becomes a widget container which allows widgets to be dropped on it and reordered. The DragItemClass attribute on the extender defines the items which can be ordered. This prevents from non-widget Html Divs from getting ordered. Only the DIVs with the class "widget" are ordered. Say there are 5 DIVs with the class named "widget". It will allow reordering of only these five divs: 

   1: <div id="LeftPanel" class="widget_holder" >
   2:         <div class="widget"> ... </div>
   3:         <div class="widget"> ... </div>
   5:         <div class="widget"> ... </div>
   6:         <div class="widget"> ... </div>
   7:         <div class="widget"> ... </div>
   9:         <div>This DIV will not move</div>
  10:         <div id="DropCue1" class="widget_dropcue"></div>
  11: </div>

When a widget is dropped on the panel, the extender fires the function specified in OnClientDrop. It offers standard Ajax Events. But unlike basic Ajax events where you have to programmatically bind to events, you can define property and specify the function name to call. So, instead of doing this:

   1: function pageLoad( sender, e ) {
   3:   var extender1 = $get(‘CustomDragDropExtender1’);
   4:   extender1.add_onDrop( onDrop );
   6: }

You can do this:

   1: <cdd:CustomDragDropExtender ID="CustomDragDropExtender1" 
   2:     runat="server" 
   3:     OnClientDrop="onDrop" />

When the event is raised, the function named onDrop gets fired. This is done with the help of some handy library available in ACT project.

When the event is fired, it sends the container, the widget and the position of the widget where the widget is dropped.

   1: function onDrop( sender, e )
   2: {
   3:     var container = e.get_container();
   4:     var item = e.get_droppedItem();
   5:     var position = e.get_position();
   7:     //alert( String.format( "Container: {0}, Item: {1}, Position: {2}",,, position ) );
   9:     var instanceId = parseInt(item.getAttribute("InstanceId"));
  10:     var columnNo = parseInt(container.getAttribute("columnNo"));
  11:     var row = position;
  13:     WidgetService.MoveWidgetInstance( instanceId, columnNo, row );
  14: }


The widget location is updated by calling the WidgetService.MoveWidgetInstance.

CustomDragDropExtender has 3 files:

  • CustomDragDropExtender.cs – The server side extender implementation
  • CustomDragDropDesigner.cs – Designer class for the extender
  • CustomDragDropExtender.js – Client side scriptfor the extender

Server side class CustomDragDropExtender.cs has the following code:

   1: [assembly: System.Web.UI.WebResource("CustomDragDrop.CustomDragDropBehavior.js", "text/javascript")]
   3: namespace CustomDragDrop
   4: {
   5:     [Designer(typeof(CustomDragDropDesigner))]
   6:     [ClientScriptResource("CustomDragDrop.CustomDragDropBehavior", "CustomDragDrop.CustomDragDropBehavior.js")]
   7:     [TargetControlType(typeof(WebControl))]
   8:     [RequiredScript(typeof(CustomFloatingBehaviorScript))]
   9:     [RequiredScript(typeof(DragDropScripts))]
  10:     public class CustomDragDropExtender : ExtenderControlBase
  11:     {
  12:         // TODO: Add your property accessors here.
  13:         //
  14:         [ExtenderControlProperty]
  15:         public string DragItemClass
  16:         {
  17:             get
  18:             {
  19:                 return GetPropertyValue<String>("DragItemClass", string.Empty);
  20:             }
  21:             set
  22:             {
  23:                 SetPropertyValue<String>("DragItemClass", value);
  24:             }
  25:         }
  27:         [ExtenderControlProperty]
  28:         public string DragItemHandleClass
  29:         {
  30:             get
  31:             {
  32:                 return GetPropertyValue<String>("DragItemHandleClass", string.Empty);
  33:             }
  34:             set
  35:             {
  36:                 SetPropertyValue<String>("DragItemHandleClass", value);
  37:             }
  38:         }
  40:         [ExtenderControlProperty]
  41:         [IDReferenceProperty(typeof(WebControl))]
  42:         public string DropCueID
  43:         {
  44:             get
  45:             {
  46:                 return GetPropertyValue<String>("DropCueID", string.Empty);
  47:             }
  48:             set
  49:             {
  50:                 SetPropertyValue<String>("DropCueID", value);
  51:             }
  52:         }
  54:         [ExtenderControlProperty()]
  55:         [DefaultValue("")]
  56:         [ClientPropertyName("onDrop")]
  57:         public string OnClientDrop
  58:         {
  59:             get
  60:             {
  61:                 return GetPropertyValue<String>("OnClientDrop", string.Empty);
  62:             }
  63:             set
  64:             {
  65:                 SetPropertyValue<String>("OnClientDrop", value);
  66:             }
  67:         }
  69:     }
  70: }

Most of the code in the extender defines the property. The important part is the declaration of the class:

   1: [assembly: System.Web.UI.WebResource("CustomDragDrop.CustomDragDropBehavior.js", "text/javascript")]
   3: namespace CustomDragDrop
   4: {
   5:     [Designer(typeof(CustomDragDropDesigner))]
   6:     [ClientScriptResource("CustomDragDrop.CustomDragDropBehavior", "CustomDragDrop.CustomDragDropBehavior.js")]
   7:     [TargetControlType(typeof(WebControl))]
   8:     [RequiredScript(typeof(CustomFloatingBehaviorScript))]
   9:     [RequiredScript(typeof(DragDropScripts))]
  10:     public class CustomDragDropExtender : ExtenderControlBase
  11:     {

The extender class inherits from ExtenderControlBase defined in ACT project. This base class has additional features over Ajax runtime provided Extender base class. It allows you to define RequiredScript attribute, which makes sure all the required scripts are downloaded before the extender script is downloaded and initialized. This extender has dependency over another extender named CustomFloatingBehavior. It also depends on ACT’s DragDropManager. So, the RequiredScript attribute makes sure those are downloaded before this extender’s script is downloaded. The ExtenderControlBase is a pretty big class and does a lot of work for us. It contains default implementations for discovering all the script files for the extender and rendering them properly.

The [assembly:System.Web.UI.WebResource] attribute defines the script file containing the script for extender. The script file is an embedded resource file.

[ClientScriptResource] attribute defines the scripts required for the extender. This class is also defined in ACT. ExtenderControlBase uses this attribute to find out which .js files are working for the extender and renders them properly.

The challenge is to make the client side javascript for the extender. On the js file, there’s a Javascript pseudo class:

   1: Type.registerNamespace('CustomDragDrop');
   3: CustomDragDrop.CustomDragDropBehavior = function(element) {
   5:     CustomDragDrop.CustomDragDropBehavior.initializeBase(this, [element]);
   7:     this._DragItemClassValue = null;    
   8:     this._DragItemHandleClassValue = null;
   9:     this._DropCueIDValue = null;
  10:     this._dropCue = null;
  11:     this._floatingBehaviors = [];
  12: }

During initialize, it hooks on the Panel it is attached to and the drop cue to show while drag & drop is going on over the Panel:

   1: CustomDragDrop.CustomDragDropBehavior.prototype = {
   3:     initialize : function() {
   4:         // Register ourselves as a drop target.
   5:         AjaxControlToolkit.DragDropManager.registerDropTarget(this); 
   6:         //Sys.Preview.UI.DragDropManager.registerDropTarget(this);
   8:         // Initialize drag behavior after a while
   9:         window.setTimeout( Function.createDelegate( this, this._initializeDraggableItems ), 3000 );
  11:         this._dropCue = $get(this.get_DropCueID());
  12:     },

After initializing the DragDropManager and marking the Panel as a drop target, it starts a timer to discover the dragable items inside the panel and create Floating behavior for them. Floating behavior is the one which makes a DIV draggable.

FloatingBehavior makes one DIV freely draggable on the page. But it does not offer drop functionality. DragDropBehavior offers the drop functionality which allows a freely moving DIV to rest on a fixed position.

Discovering and initializing floating behavior for the dragable items is the challenging work:

   1: // Find all items with the drag item class and make each item
   2: // draggable        
   3: _initializeDraggableItems : function() 
   4: {
   5:     this._clearFloatingBehaviors();
   7:     var el = this.get_element();
   9:     var child = el.firstChild;
  10:     while( child != null )
  11:     {
  12:         if( child.className == this._DragItemClassValue && child != this._dropCue)
  13:         {
  14:             var handle = this._findChildByClass(child, this._DragItemHandleClassValue);
  15:             if( handle )
  16:             {
  17:                 var handleId =;
  18:                 var behaviorId = + "_WidgetFloatingBehavior";
  20:                 // make the item draggable by adding floating behaviour to it                    
  21:                 var floatingBehavior = $create(CustomDragDrop.CustomFloatingBehavior, 
  22:                         {"DragHandleID":handleId, "id":behaviorId, "name": behaviorId}, {}, {}, child);
  24:                 Array.add( this._floatingBehaviors, floatingBehavior );
  25:             }
  26:         }            
  27:         child = child.nextSibling;
  28:     }
  29: },

Here’s the algorithm:

  • Run through all immediate child elements of the control where the extender is attached to
  • If the child item has the class for draggable item, then:
    • Find any element under the child item which has the class for Drag handle
    • If such item found, then attach a CustomFloatingBehavior with the child item

The _findChildByClass function recursively iterates through all the child elements and looks for an element which has the defined class. It’s an expensive function. So, it is important that the drag handle is very close to the dragable element.

   1: _findChildByClass : function(item, className)
   2: {
   3:     // First check all immediate child items
   4:     var child = item.firstChild;
   5:     while( child != null )
   6:     {
   7:         if( child.className == className ) return child;
   8:         child = child.nextSibling;
   9:     }
  11:     // Not found, recursively check all child items
  12:     child = item.firstChild;
  13:     while( child != null )
  14:     {
  15:         var found = this._findChildByClass( child, className );
  16:         if( found != null ) return found;
  17:         child = child.nextSibling;
  18:     }
  19: },

When user drags an item over the Panel where the extender is attached to, DragDropManager fires the following events:

   1: onDragEnterTarget : function(dragMode, type, data) {
   2:     this._showDropCue(data);    
   3: },
   5: onDragLeaveTarget : function(dragMode, type, data) {
   6:     this._hideDropCue(data);
   7: },
   9: onDragInTarget : function(dragMode, type, data) {
  10:     this._repositionDropCue(data);
  11: },

Here we deal with the drop cue. The challenging work is to find out the right position for the drop cue.

We need to find out where we should show the drop cue based on where user is dragging the item. The idea is to find out the widget which is immediately below the dragged item. The item is pushed down by one position and the drop cue takes its place. While dragging, the position of the drag item can be found easily. Based on that, I locate the widget below the drag item:

   1: _findItemAt : function(x,y, item)
   2:     {
   3:         var el = this.get_element();
   5:         var child = el.firstChild;
   6:         while( child != null )
   7:         {
   8:             if( child.className == this._DragItemClassValue && child != this._dropCue && child != item )
   9:             {
  10:                 var pos = Sys.UI.DomElement.getLocation(child);
  12:                 if( y <= pos.y )
  13:                 {
  14:                     return child;
  15:                 }
  16:             }
  17:             child = child.nextSibling;
  18:         }
  20:         return null;
  21:     },

This function returns the widget which is immediately under the dragged item. Now I add the drop cue immediately above the widget:

   1: _repositionDropCue : function(data)
   2:     {
   3:         var location = Sys.UI.DomElement.getLocation(data.item);
   4:         var nearestChild = this._findItemAt(location.x, location.y, data.item);
   6:         var el = this.get_element();        
   8:         if( null == nearestChild )
   9:         {
  10:             if( el.lastChild != this._dropCue )
  11:             {
  12:                 el.removeChild(this._dropCue);
  13:                 el.appendChild(this._dropCue);
  14:             }
  15:         }
  16:         else
  17:         {
  18:             if( nearestChild.previousSibling != this._dropCue )
  19:             {
  20:                 el.removeChild(this._dropCue);
  21:                 el.insertBefore(this._dropCue, nearestChild);            
  22:             }            
  23:         }
  24:     },

One exception to consider here is that there can be no widget immediately below the dragged item. It happens when user is trying to drop the widget at the bottom of column. In that case, the drop cue is shown at the bottom of the column.

When user releases the widget, it drops right on top of drop cue and the drop cue disappears. After the drop the onDrop event is raised to notify where the widget is dropped.

   1: _placeItem : function(data)
   2:     {
   3:         var el = this.get_element();
   5:         data.item.parentNode.removeChild( data.item );
   6:         el.insertBefore( data.item, this._dropCue );
   8:         // Find the position of the dropped item
   9:         var position = 0;
  10:         var item = el.firstChild;
  11:         while( item != data.item )
  12:         {  
  13:             if( item.className == this._DragItemClassValue ) position++; 
  14:             item = item.nextSibling; 
  15:         }
  16:         this._raiseDropEvent( /* Container */ el, /* droped item */ data.item, /* position */ position );
  17:     }
Generally you can make events in extenders by adding two functions in the extender:
   1: add_onDrop : function(handler) {
   2:     this.get_events().addHandler("onDrop", handler);
   3: },
   5: remove_onDrop : function(handler) {
   6:     this.get_events().removeHandler("onDrop", handler);
   7: },
But this does not give you the support for defining the event listener name in the ASP.NET declaration:
   1: <cdd:CustomDragDropExtender ID="CustomDragDropExtender1" 
   2:     runat="server" 
   3:     OnClientDrop="onDrop" />

The declaration only allows properties. In order to support such declarative assignment of events, we need to first introduce a property named OnClientDrop in the extender. Then during assignment of the property, we need to find out the function specified there and attach event notification on that function. The discovery of the function from its name is done by CommonToolkitScripts.resolveFunction which is available in ACT project.

   1: // onDrop property maps to onDrop event
   2:     get_onDrop : function() {
   3:         return this.get_events().getHandler("onDrop");
   4:     },
   6:     set_onDrop : function(value) {
   7:         if (value && (0 < value.length)) {
   8:             var func = CommonToolkitScripts.resolveFunction(value);
   9:             if (func) { 
  10:                 this.add_onDrop(func);
  11:             } else {
  12:                 throw Error.argumentType('value', typeof(value), 'Function', 'resize handler not a function, function name, or function text.');
  13:             }
  14:         }
  15:     },
Raising the event is same as basic Ajax events:
   1: _raiseEvent : function( eventName, eventArgs ) {
   2:         var handler = this.get_events().getHandler(eventName);
   3:         if( handler ) {
   4:             if( !eventArgs ) eventArgs = Sys.EventArgs.Empty;
   5:             handler(this, eventArgs);
   6:         }
   7:     },
This is all about the CustomDragDropExtender. Next challenge is to make the CustomFloatingBehavior. The server side class is declared as:
   1: [assembly: System.Web.UI.WebResource("CustomDragDrop.CustomFloatingBehavior.js", "text/javascript")]
   3: namespace CustomDragDrop
   4: {
   5:     [Designer(typeof(CustomFloatingBehaviorDesigner))]
   6:     [ClientScriptResource("CustomDragDrop.CustomFloatingBehavior", "CustomDragDrop.CustomFloatingBehavior.js")]
   7:     [TargetControlType(typeof(WebControl))]
   8:     [RequiredScript(typeof(DragDropScripts))]
   9:     public class CustomFloatingBehaviorExtender : ExtenderControlBase
  10:     {
  11:         [ExtenderControlProperty]
  12:         [IDReferenceProperty(typeof(WebControl))]
  13:         public string DragHandleID
  14:         {
  15:             get
  16:             {
  17:                 return GetPropertyValue<String>("DragHandleID", string.Empty);
  18:             }
  19:             set
  20:             {
  21:                 SetPropertyValue<String>("DragHandleID", value);
  22:             }
  23:         }
  24:     }
  25: }

There’s only one property – DragHandleID. Widget’s header works as the drag handle. So, the header ID is specified here.

This extender has dependency on DragDropManager so the [RequiredScript(typeof(DragDropScripts))] attribute is there.

Besides the designer class, there’s one more class which CustomDragDropExtender need in order to specify its dependency over this floating behavior:

   1: [ClientScriptResource(null, "CustomDragDrop.CustomFloatingBehavior.js")]
   2:   public static class CustomFloatingBehaviorScript
   3:   {
   4:   }

This class can be used inside RequiredScript attribute. It only defines which script file contains the client side code for the extender.

The client side Javascript is same as FloatingBehavior that comes with ACT. The only difference is some hack when drag starts. DragDropManager does not return the item being dragged to static position once it makes it absolute. It also does not increase the zIndex of the item. If the drag item does not become the top most item, while dragging it goes below other elements on the page. So, I have made some changes in the mouseDownHandler of the behavior to add these features:

   1: function mouseDownHandler(ev) {
   2:     window._event = ev;
   3:     var el = this.get_element();
   5:     if (!this.checkCanDrag( return;
   7:     // Get the location before making the element absolute
   8:     _location = Sys.UI.DomElement.getLocation(el);
  10:     // Make the element absolute 
  11: = el.offsetWidth + "px";
  12: = el.offsetHeight + "px";            
  13:     Sys.UI.DomElement.setLocation(el, _location.x, _location.y);               
  15:     _dragStartLocation = Sys.UI.DomElement.getLocation(el);        
  17:     ev.preventDefault();
  19:     this.startDragDrop(el);
  21:     // Hack for restoring position to static
  22:     el.originalPosition = "static";
  23:     el.originalZIndex =;
  24: = "60000";
  25: }

Setting el.originalPosition = static fixes the bug in DragDropManager. It incorrectly stores absolute has the originalPosition when startDragDrop is called. So, after calling this function, I set it to correct originalPosition which is “static”.

When drag completes, the original zIndex is restored and left, top, width and height is cleared. DragDropManager makes the item position static, but it does not clear the left, top, width and height attributes. This moves the element away from the place where it is dropped. This bug is fixed in the onDragEnd event:

   1: this.onDragEnd = function(canceled) {
   2:     if (!canceled) {
   3:         var handler = this.get_events().getHandler('move');
   4:         if(handler) {
   5:             var cancelArgs = new Sys.CancelEventArgs();
   6:             handler(this, cancelArgs);
   7:             canceled = cancelArgs.get_cancel();
   8:         }            
   9:     }
  11:     var el = this.get_element();
  12: = = = = "";
  13: = el.originalZIndex;
  14: }

That's all folks!

You can get the code for the extenders here.


Posted: Oct 22 2007, 10:03 AM by oazabir | with 13 comment(s)
Filed under: ,
Synchronously execute and get return parameters from Workflow

In my DropThings project, I have used Workflows to develop the business layer that run synchronously and do most of the work in the middle-tier. The business layer facade named DashboardFacade has no code but to call different workflows. Each of the workflow serve a particular operation like new user visit, existing user visit, adding a tab, moving a widget from one column to another etc. ASP.NET page calls DashboardFacade for each user action and DashboardFacade inturn calls a workflow to respond to that user action.

“This is insane!” you are thinking. I know. Please hear me out why I went for this approach:

Architects can “Design” business facade functions in terms of Activities and developers can just fill in small amount of unit code in each activity.

This is a really good reason because Architects can save time in writing Word Documents explaining how things should work. They can directly go into Workflow Designer, design the activities, connect them, design the flow, and verify whether all input and output are properly mapped or not. This is lot better than drawing flow-charts, writing pseudocode, explaining in stylish text how an operation should work. It is also helpful for developers because they can see the workflow and easily understand how to craft the whole operation. They just open up each activity and write small amount of very specific reusable code. They know what will be the input to the Activity (like function parameters) and they know what to produce (return value of function). This makes the activities reusable and architects can reuse one activity in many workflows. Workflows can be debugged right on Visual Studio Workflow Designer. So, developers can easily find out defects in their implementation by debugging the workflow. Architects can enforce many standards like validations, input output check, Fault handling on the workflow. Developers cannot but comply with those and thus produce really good code. Another great benefit for both architect and developer is that there’s no need to keep a separate technical specification document up-to-date because the workflow is always up-to-date and it speaks for itself. If someone wants to study how a particular operation works, one can just printout the workflow and read it through.

“But what about performance”, you say? Both you and I have heard workflow foundation is a pretty big library and can be memory hog. Also the workflow runtime is quite big and takes time to start up. I did some profiling on the overhead of workflow execution and it is very fast for synchronous execution. Here's proof from the log you get in Visual Studio output window:

   1: b030692b-5181-41f9-a0c3-69ce309d9806 Activity: Get User Guid        0.078125
   2: b030692b-5181-41f9-a0c3-69ce309d9806 Activity: Get User Pages       0.0625
   3: b030692b-5181-41f9-a0c3-69ce309d9806 Activity: Get User Setting     0.046875
   4: b030692b-5181-41f9-a0c3-69ce309d9806 Activity: Get Widgets in page: 189 0.0625
   5: b030692b-5181-41f9-a0c3-69ce309d9806 Total: Existing user visit     0.265625

First four entries are the time taken by individual activities during data access only, not the total time taken to execute the whole activity. The time entries here are in seconds and the first four entries represent duration of database operations inside activities. The last one is the total time for running a workflow with the four activities shown above and some extra code. If you sum up all the individual activity execution time for database operations only, it is 0.2500 which is just 0.015625 sec less than the total execution time. This means, executing the workflow itself along with overhead of running activities takes around 0.015 sec which is almost nothing compared to the total effort of doing the complete operation.

An example of such workflow is as following:

   1: public void MoveWidgetInstance( int widgetInstanceId, int toColumn, int toRow )
   2: {
   3:   using( new TimedLog(this._UserName, "Move Widget:" + widgetInstanceId) )
   4:   {
   5:     var properties = new Dictionary<string,object>();
   6:     properties.Add("UserName", this._UserName);
   7:     properties.Add("WidgetInstanceId", widgetInstanceId);
   8:     properties.Add("ColumnNo", toColumn);
   9:     properties.Add("RowNo", toRow);
  11:     WorkflowHelper.ExecuteWorkflow( typeof( MoveWidgetInstanceWorkflow ), properties );
  12:   }
  13: }

MoveWidgetInstance is a method in DashboardFacade. It just calls a workflow named MoveWidgetInstanceWorkflow which does the job for moving a widget from one column to another, rearrange the widgets on the new column, pull up widgets on the old column to remove the empty space, and update all widgets positions. If I wrote all these code in one function, it becomes quite a big function and requires documentation. But having a workflow means I have a flowchart of what's going on and I have some handy reusable Activities which I can reuse in other operations.

Implementing business layer as workflows has three important requirements:

  1. Execute workflow synchronoulsy within the ASP.NET request thread
  2. Get output parameters from workflow which is returned as return value from Business Facade methods
  3. Get exceptions raised from Activities in a synchronous manner inside the same request thread

WorkflowHelper is a handy class I made, which makes use of Workflow a breeze, especially from ASP.NET. In the business layer, I need synchronous execution of workflow where the default implementation of Workflow Foundation is to work asynchronously. Moreover, I need return values from Workflows after their execution complete, which is not so easily supported due to asynchronous nature of workflow. Both of these require some tweaking with workflow runtime in order to successfully run in ASP.NET environment. You will find the source code of WorkflowHelper in the code zip file from

WorkflowHelper.Init function initializes Workflow Runtime for ASP.NET environment. It makes sure there’s only one workflow runtime per Application Domain. Workflow Runtime cannot be created twice in the same application domain. So, it stores the reference of the Workflow Runtime in Application Context.

   1: public static WorkflowRuntime Init()
   2: {
   3:   WorkflowRuntime workflowRuntime;
   5:   // Running in local mode, create an return new runtime
   6:   if( HttpContext.Current == null )
   7:     workflowRuntime = new WorkflowRuntime();
   8:   else
   9:   {
  10:     // running in web mode, runtime is initialized only once per 
  11:     // application
  12:     if( HttpContext.Current.Application["WorkflowRuntime"] == null )
  13:       workflowRuntime = new WorkflowRuntime();
  14:     else
  15:       return HttpContext.Current.Application["WorkflowRuntime"] as WorkflowRuntime;
  16:   }   

The initialization takes care of both ASP.NET and Console/Winforms mode. After the initialization, it registers ManualWorkflowSchedulerService, which take care of synchronous execution of Workflow. Activities.CallWorkflowService is a handy service that executes workflow synchrnously from another workflow. Read this post for details. These two services make Workflow Foundation usable from ASP.NET environment for practical scenarios.

   1: var manualService = new ManualWorkflowSchedulerService();
   2: workflowRuntime.AddService(manualService);
   4: var syncCallService = new Activities.CallWorkflowService();
   5: workflowRuntime.AddService(syncCallService);
   7: workflowRuntime.StartRuntime();
   9: // on web mode, store the runtime in application context so that
  10: // it is initialized only once. On dekstop mode, ignore
  11: if( null != HttpContext.Current )
  12:   HttpContext.Current.Application["WorkflowRuntime"] = workflowRuntime;
  14: return workflowRuntime;

Workflow Runtime is initialized from Application_Start event in Global.asax. This ensures the initialization happens only once per App Domain.

   1: void Application_Start(object sender, EventArgs e) 
   2: {
   3:   // Code that runs on application startup
   5:   DashboardBusiness.WorkflowHelper.Init();
   6: }

The runtime is disposed from Application_End event in Gloabal.asax:

   1: void Application_End(object sender, EventArgs e) 
   2: {
   3:     //  Code that runs on application shutdown
   4:     DashboardBusiness.WorkflowHelper.Terminate();
   5: }

The most interesting function is the ExecuteWorkflow function which does the following:

  • Execute workflow synchronously
  • Pass parameters to workflow
  • Upon completion, get output parameters from workflow and return them
    Handle exceptions raised in Workflow and raise to ASP.NET exception handler

First ExecuteWorkflow creates an instance of Workflow and passes input parameters to it:

   1: public static void ExecuteWorkflow( Type workflowType, Dictionary<string,object> properties)
   2: {
   3:   WorkflowRuntime workflowRuntime = Init();
   5:   ManualWorkflowSchedulerService manualScheduler = workflowRuntime.GetService<ManualWorkflowSchedulerService>();
   7:   WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowType, properties);        
   8:   instance.Start();

ManualWorkflowSchedulerService service executes the workflow synchronously. Next step is to hook WorkflowCompleted and WorkflowTerminated events of Workflow Runtime so that I can capture output parameters and exceptions and handle them properly.

   1: EventHandler<WorkflowCompletedEventArgs> completedHandler = null;
   2: completedHandler = delegate(object o, WorkflowCompletedEventArgs e)
   3: {
   4:   if (e.WorkflowInstance.InstanceId ==instance.InstanceId)
   5:   {
   6:     workflowRuntime.WorkflowCompleted -= completedHandler;
   8:     // copy the output parameters in the specified properties dictionary
   9:     Dictionary<string,object>.Enumerator enumerator = e.OutputParameters.GetEnumerator();
  10:     while( enumerator.MoveNext() )
  11:     {
  12:       KeyValuePair<string,object> pair = enumerator.Current;
  13:       if( properties.ContainsKey(pair.Key) )
  14:       {
  15:         properties[pair.Key] = pair.Value;
  16:       }
  17:     }
  18:   }
  19: };

When workflow completes, WorkflowCompletedEventArgs gives me the OutputParameters dictionary. It contains all the public properties of Workflow. I read all the entries in the OutputParameters and update the input parameters Dictionary with the new values. This is required in the AddWidget function of DashboardFacade where I need to know the widget instance created by the workflow.

WorkflowTerminated fires when there’s an exception. When any activity inside the workflow raises exception, this event fires and workflow execution aborts. I capture this exception and throw it again so that ASP.NET can trap this exception using its default exception handler.

   1: Exception x  = null;
   2: EventHandler<WorkflowTerminatedEventArgs> terminatedHandler = null;            
   3: terminatedHandler = delegate(object o, WorkflowTerminatedEventArgs e)
   4: {
   5:   if (e.WorkflowInstance.InstanceId == instance.InstanceId)
   6:   {
   7:     workflowRuntime.WorkflowTerminated -= terminatedHandler;                    
   8:     Debug.WriteLine( e.Exception );
  10:     x = e.Exception;
  11:   }
  12: };
  13: workflowRuntime.WorkflowCompleted += completedHandler;
  14: workflowRuntime.WorkflowTerminated += terminatedHandler;
  16: manualScheduler.RunWorkflow(instance.InstanceId);
  18: if (null != x)
  19:   throw new WorkflowException(x);

This helps me get exceptions shown in ASP.NET Exception handler like this:

The WorkflowHelper is a reusable class that you can use in your work project. Just copy the class file out of my project and add in your own.

Posted: Oct 22 2007, 09:59 AM by oazabir | with 2 comment(s)
Filed under: ,
A significant part of sql server process memory has been paged out. This may result in performance degradation

If you are using SQL Sever Server standard edition 64 bit on a Windows 2003 64bit, you will frequently encounter this problem where SQL Server says:

A significant part of sql server process memory has been paged out. This may result in performance degradation. Duration 0 seconds. Working set (KB) 25432, committed (KB) 11296912, memory utilization 0%

The number in working set and duration will vary. What happens here is SQL Server is forced to release memory to operating system because some other application or OS itself needs to allocate RAM.

We went through many support articles like:

  • 918483: How to reduce paging of buffer pool memory in the 64-bit version of SQL Server 2005
  • 905865: The sizes of the working sets of all the processes in a console session may be trimmed when you use Terminal Services to log on to or log off from a computer that is running Windows Server 2003
  • 920739: You may experience a decrease in overall system performance when you are copying files that are larger than approximately 500 MB in Windows Server 2003 Service Pack 1

But nothing solved the problem. We still have the page out problem happening every day.

The server has 16 GB RAM where 12 GB is maximum limit allocated to SQL Server. 4 GB is left to OS and and other application. We have also turned off antivirus and any large backup job. 12 GB RAM should be plenty because there's no other app running on the dedicated SQL Server box. But the page out still happens. When this happens, SQL Server becomes very slow. Queries timeout, website throws error, transactions abort. Sometimes this problems goes on for 30 to 40 minutes and website becomes slow/unresponsive during that time.

I have found what causes SQL Server to page out. File System cache somehow gets really high and forces SQL Server to trim down.


You see the System cache resident bytes are very high. During this time SQL Server gets much less RAM than it needs. Queries timeout at very high rate like 15 per sec. Moreover, there's high SQL Lock Timeout/sec (around 15/sec not captured in screen shot).


SQL Server max memory is configured 12 GB. But here it shows it’s getting less than 8 GB.

While the file system cache is really high, there’s no process that’s taking significant RAM.


After I used SysInternal’s CacheSet to reset file system cache and set around 500 MB as max limit, memory started to free up.


SQL Server started to see more RAM free:


Then I hit the “Clear” button to clear file system cache and it came down dramatically.


Paging stopped. System cache was around 175 MB only. SQL Server lock timeout came back to zero. Everything went back to normal.

So, I believe there's either some faulty driver or the OS itself is leaking file system cache in 64bit environment.

What we have done is, we have a dedicated person who goes to production database servers every hour, runs the CacheSet program and clicks "Clear" button. This clears the file system cache and prevents it from growing too high.

There are lots of articles written about this problem. However, the most informative one I have found is from the SQL Server PSS team:


The final solution is to run this program on Windows Startup:

SetSystemFileCacheSize 128 256

This sets the lower and higher limit for the System Cache. You need to run this on every windows startup because a restart will undo the cache setting to unlimited.

You can run the program without any parameter to see what is the current setting.

Download the program from this page:

Go to the end and you will get the link to the

Posted: Oct 19 2007, 08:31 PM by oazabir | with 2 comment(s)
Filed under:
Serve extensionless URL from ASP.NET without using ISAPI module or IIS 6 Wildcard mapping

If you want to serve extensionless URL from ASP.NET 2.0 like the following:


You cannot, unless you use some third party ISAPI module or use IIS 6.0 Wildcard mapping feature. Third party ISAPI module needs to be installed on the server directly. If you don't have a dedicated server or a VPS, you cannot do this. IIS 6.0 Wildcard mapping makes each and every request go through ASP.NET 2.0 ISAPI handler including Urls with .gif, .css, .js, .html etc. So, it suffers from scalability problem. Some independent research shows there's 30% drop in performance in IIS 6.0 when you use wildcard mapping. So, this is not a good solution either.

Here's an approach which works without using ISAPI module or wildcard mapping in IIS 6.0. When you request extensionless URL, you get HTTP 404. This means IIS receives the request but it serves the page configured for HTTP 404. It does not send the request to ASP.NET ISAPI. So, if you can forward all HTTP 404 to ASP.NET, you can serve such extensionless URL. In order to forward HTTP 404 to ASP.NET ISAPI, all you need to do is configure IIS to redirect to some .aspx extension on HTTP 404.

Benefits of this approach:

  • No thirdparty ISAPI module required
  • No Wildcard mapping thus no performance sacrifice

Here's how to configure 404 redirection in IIS 6.0:

On IIS 6.0 change 404 default page to /404.aspx and the type to "URL".  On IIS 7.0, change 404 default page to /404.aspx and the type to "ExecuteURL". Also, change the default error response to "Custom error pages".

When you will request an URL like "" it will redirect to ";". From Global.asax BeginRequest event, capture this URL and see whether it's an extensionless URL request. If it is, do your URL rewriting stuff for such extensionless URL.


   1: protected void Application_BeginRequest(object sender, EventArgs e)
   2: {
   3:     string url = HttpContext.Current.Request.Url.AbsolutePath;
   5:     // HTTP 404 redirection for extensionless URL or some missing file
   6:     if (url.Contains("404.aspx"))
   7:     {
   8:         // On 404 redirection, query string contains the original URL in this format:
   9:         // 404;http://localhost:80/Http404Test/OmarALZabir
  11:         string[] urlInfo404 = Request.Url.Query.ToString().Split(';');
  12:         if (urlInfo404.Length > 1)
  13:         {
  14:             string originalUrl = urlInfo404[1]; 
  16:             string[] urlParts = originalUrl.Split('?');
  18:             string queryString = string.Empty;
  19:             string requestedFile = string.Empty;
  21:             if (urlParts.Length > 1)
  22:             {
  23:                 requestedFile = urlParts[0];
  24:                 queryString = urlParts[1];
  25:             }
  26:             else
  27:             {
  28:                 requestedFile = urlParts[0];
  29:             }
  31:             if( requestedFile.IndexOf('.') > 0 )
  32:             {
  33:                 // There's some extension, so this is not an extensionless URL.
  34:                 // Don't handle such URL because these are really missing files
  35:             }
  36:             else
  37:             {
  38:                 // Extensionless URL. Use your URL rewriting logic to handle such URL
  39:                 // I will just add .aspx extension to the extension less URL.
  40:                 HttpContext.Current.RewritePath(requestedFile + ".aspx?" + queryString);
  41:             }
  42:         }
  43:     }
  44: }


Posted: Oct 17 2007, 03:56 PM by oazabir | with 2 comment(s)
Filed under: ,
Prevent Denial of Service (DOS) attacks in your web application

Web services are the most attractive target for hackers because even a pre-school hacker can bring down a server by repeatedly calling a web service which does expensive work. Ajax Start Pages like Pageflakes are the best target for such DOS attack because if you just visit the homepage repeatedly without preserving cookie, every hit is producing a brand new user, new page setup, new widgets and what not. The first visit experience is the most expensive one. Nonetheless, it’s the easiest one to exploit and bring down the site. You can try this yourself. Just write a simple code like this:

   1: for( int i = 0; i < 100000; i ++ )
   2: {
   3:    WebClient client = new WebClient();
   4:    client.DownloadString("");
   5: }

In your great surprise, you will notice that, after a couple of call, you don't get valid response. It’s not that you have succeeded in bringing down the server. It’s that your requests are being rejected. You are happy that you no longer get any service, thus you achieve Denial of Service (for yourself). I am happy to Deny You of Service (DYOS).

The trick I have in my sleeve is an inexpensive way to remember how many requests are coming from a particular IP. When the number of request exceeds the threshold, deny further request for some duartion. The idea is to remember caller’s IP in Cache and maintain a count of request per IP. When the count exceeds a predefined limit, reject further request for some specific duration like 10 mins. After 10 mins, again allow requests from that IP.

I have a class named ActionValidator which maintains a count of specific actions like First Visit, Revisit, Asynchrnous postbacks, Add New widget, Add New Page etc. It checks whether the count for such specific action for a specific IP exceeds the threshold value or not.

   1: public static class ActionValidator
   2: {
3: private const int DURATION = 10; // 10 min period
   5:     public enum ActionTypeEnum
   6:     {
   7:         FirstVisit = 100, // The most expensive one, choose the valu wisely. 
   8:         ReVisit = 1000, // Welcome to revisit as many times as use likes
   9:         Postback = 5000,   // Not must of a problem for us
  10:         AddNewWidget = 100, 
  11:         AddNewPage = 100,
  12:     }

The enumeration contains the type of actions to check for and their threshold value for a specific duration – 10 mins.

A static method named IsValid does the check. It returns true if the request limit is not passed, false if the request needs to be denied. Once you get false, you can call Request.End() and prevent from proceeding further. You can also switch to a page which shows “Congratulations! You have succeeded in Denial of Service Attack.”


public static bool IsValid( ActionTypeEnum actionType )
   2: {
   3: HttpContext context  = HttpContext.Current;
if( context.Request.Browser.Crawler ) return false;
   6: string key = actionType.ToString()  + context.Request.UserHostAddress;
   8: HitInfo hit  = (HitInfo)(context.Cache[key] ?? new HitInfo());
  10: if( hit.Hits > (int)actionType ) return false;
  11: else hit.Hits ++;
  13: if( hit.Hits == 1 )
  14:     context.Cache.Add(key, hit, null, DateTime.Now.AddMinutes(DURATION), 
  15:       System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
  17: return true;
  18: }

The cache key is built with a combination of action type and client IP address. First it checks if there’s any entry for the action and the client IP in Cache or not. If not, start the count and store remember the count for the IP in cache for the specific duration. The absolute expiration on cache item ensures after the duration, the cache item will be cleared and the count will restart. When there’s already an entry in the cache, get the last hit count, and check if the limit is exceeded or not. If not exceeded, increase the counter. There is no need to store the updated value in the cache again by doing: Cache[url]=hit; because the hit object is by reference and changing it means it gets changed in the cache as well. In fact, if you do put it again in the cache, the cache expiration counter will restart and fail the logic of restarting count after specific duration.

The usage is very simple:

protected override void OnInit(EventArgs e)
   2: {
   3:   base.OnInit(e);
   5:   // Check if revisit is valid or not
   6:   if(  !base.IsPostBack ) 
   7:   {
   8:     // Block cookie less visit attempts
   9:     if( Profile.IsFirstVisit )
  10:     {
  11:        if( !ActionValidator.IsValid(ActionValidator.ActionTypeEnum.FirstVisit) Response.End();
  12:     }
  13:    else
  14:     {
  15:      if( !ActionValidator.IsValid(ActionValidator.ActionTypeEnum.ReVisit) ) Response.End();
  16:     }
  17:   }
  18:  else
  19:   {
  20:    // Limit number of postbacks
  21:     if( !ActionValidator.IsValid(ActionValidator.ActionTypeEnum.Postback)  Response.End();
  22:   }
  23: }

Here I am checking specific scenario like First Visit, re-visit, postbacks etc.

Of course you can put in some Cisco firewall and prevent DOS attack. You will get guaranty from your hosting provider that their entire network is immune to DOS and DDOS (Distributed DOS) attacks. What they guaranty is network level attack like TCP SYN attacks or malformed packet floods etc. There is no way they can analyze the packet and find out a particular IP is trying to load the site too many times without supporting cookie or trying to add too many widgets. These are called application level DOS attack which hardware cannot prevent. It must be implemented in your own code.

There are very few websites out their which take such precaution for application level DOS attacks. Thus it’s quite easy to make servers go mad by writing a simple loop and hitting expensive pages or web services continuously from your home broadband connection. I hope this small but effective class will help you implement DOS attack in your own web applications.



Here's the code of the full ActionValidator class:

// Copyright (c) Omar AL Zabir. All rights reserved.
// For continued development and updates, visit

using System;
using System.Data;
using System.Configuration;
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;

/// <summary>
/// Summary description for ActionValidator
/// </summary>
namespace Dropthings.Web.Util
  public static class ActionValidator
  private const int DURATION = 10; // 10 min period
  * Type of actions and their maximum value per period
  public enum ActionTypeEnum
  None = 0,
  FirstVisit = 100, // The most expensive one, choose the value wisely.
  Revisit = 1000, // Welcome to revisit as many times as user likes
  Postback = 5000, // Not must of a problem for us
  AddNewWidget = 100,
  AddNewPage = 100,

  private class HitInfo
  public int Hits;
  private DateTime _ExpiresAt = DateTime.Now.AddMinutes(DURATION);
  public DateTime ExpiresAt { get { return _ExpiresAt; } set { _ExpiresAt = value; } }

  public static bool IsValid( ActionTypeEnum actionType )
  HttpContext context = HttpContext.Current;
  if( context.Request.Browser.Crawler ) return false;

  string key = actionType.ToString() + context.Request.UserHostAddress;

  HitInfo hit = (HitInfo)(context.Cache[key] ?? new HitInfo());

  if( hit.Hits > (int)actionType ) return false;
  else hit.Hits ++;

  if( hit.Hits == 1 )
  context.Cache.Add(key, hit, null, DateTime.Now.AddMinutes(DURATION),
  System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
  return true;


Posted: Oct 16 2007, 09:40 PM by oazabir | with 20 comment(s) |
Filed under:
More Posts Next page »