﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
  <channel>
    <title>Programming Without Walls</title>
    <description>Software Engineering and Things Related</description>
    <link>http://www.norimek.com/blog/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 2.5.0.10</generator>
    <language>en-US</language>
    <blogChannel:blogRoll>http://www.norimek.com/blog/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://www.dotnetblogengine.net/syndication.axd</blogChannel:blink>
    <dc:creator>Robert C. Barth</dc:creator>
    <dc:title>Programming Without Walls</dc:title>
    <geo:lat>0.000000</geo:lat>
    <geo:long>0.000000</geo:long>
    <item>
      <title>jQuery Linear Gradient Effect Plug-In Using CSS3 Background-Image Linear-Gradient Value</title>
      <description>&lt;p&gt;jQuery, along with jQuery UI provides developers with many effects options. Unfortunately, many of the newer, more complex CSS3 effects cannot be automatically animated using jQuery's built-in animation code. In this post I will show you how to use the step option jQuery's animate method to manipulate just about any property of an element, including any CSS3 property (specifically the linear-gradient value for the background-image property in this example).&lt;/p&gt;
&lt;h1&gt;CSS3 Linear Gradient&lt;/h1&gt;
&lt;p&gt;CSS3 introduced a number of new ways to style HTML markup. One of the more complex among them (syntactically) is the linear-gradient value added to the background-image property. The way you specify a linear gradient is as follows:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;p&gt;
background-image: linear-gradient( [&amp;lt;point&amp;gt; || &amp;lt;angle&amp;gt;,]? &amp;lt;stop&amp;gt;, &amp;lt;stop&amp;gt; [, &amp;lt;stop&amp;gt;]* )
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;where:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;p&gt;
&amp;lt;stop&amp;gt;
&amp;lt;color&amp;gt; [ &amp;lt;percentage&amp;gt; | &amp;lt;length&amp;gt; ]
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, it's kind of complicated so I won't explain the syntax, the &lt;a href="http://dev.w3.org/csswg/css3-images/#linear-gradients"&gt;w3c draft specification&lt;/a&gt; does a good job on its own. (It helps if you've ever used Photoshop to create gradients because it basically uses the same stop concept) Instead, I'll focus on how we can manipulate this syntax within a custom animation to create a custom jQuery effect.&lt;/p&gt;
&lt;h1&gt;jQuery Step Option&lt;/h1&gt;
&lt;p&gt;Utilizing the step property of the options of the second call method of jQuery's &lt;a href="http://api.jquery.com/animate/"&gt;animate&lt;/a&gt; function, you can create custom animations of any type, not just the built-in CSS properties that jQuery knows about. There are many articles posted in many blogs about this, but I first read about it on &lt;a href="http://www.bennadel.com/blog/1856-Using-jQuery-s-Animate-Step-Callback-Function-To-Create-Custom-Animations.htm"&gt;Ben Nadel's&lt;/a&gt; blog. What the step option gives us is a function that jQuery will call for each step of the animation. Meaning that it will calculate the easing, timing, etc, and make this call to your function for each step, providing you with some key information (e.g. the now variable, which gives you the current calculated value of the custom CSS property you asked jQuery to animate; in our example, this property is called 'percent'). This means we can create virtually any animation one can think of.&lt;/p&gt;
&lt;h1&gt;Custom Animation&lt;/h1&gt;
&lt;p&gt;Given the step option, and the skeleton jQuery effect plug-in I wrote about &lt;a href="http://www.norimek.com/blog/post/2011/08/26/Creating-Custom-Effects-in-jQuery.aspx"&gt;last time&lt;/a&gt;, we can create an effect plug-in that will do the following:
&lt;ol&gt;
&lt;li&gt;Accept a times option to specify how many times the animation should run&lt;/li&gt;
&lt;li&gt;A duration to specify how long it should run per time (in milliseconds)&lt;/li&gt;
&lt;li&gt;A starting angle for the linear-gradient (this plug-in actually does require it to be a numeric angle and not the specification's permitted textual direction parameters).&lt;/li&gt;
&lt;li&gt;A stops array, which itself can contain either a color only in each index, or a two-item array specifying the color and the position. Note that if the position is not specified in at least one of the stops, this effect won't animate anything, as it's the positions that the effect animates.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given those requirements, here's the code:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;
/*!
* jQuery linear gradient effect plug-in.
* Requires jQuery UI.
* http://norimek.com/blog/page/jQuery-Plug-Ins.aspx
*
* Copyright 2011, Robert C. Barth
* Licensed under the MIT license.
* http://www.opensource.org/licenses/MIT
*
* Date: Sat Aug 27 13:00:00 2011 -0700
*/
(function($, undefined) {

$.effects.lineargradient = function(o) {

	return this.queue(function() {
		
		var $this = $(this), 
			props = [ 'background-image' ],
			times = o.options.times || 1,
			duration = o.duration || 1000,
			angle = o.options.angle || 0,
			stops = o.options.stops;
		
		$.effects.save($this, props);
		$this.css('percent', 0);
		
		for (var i = 0; i &lt; times; i++) {
			
			$this.animate({ percent: 125 }, {
				queue: false,
				duration: duration,
				easing: o.options.easing,
				step: function(now, fx) {
					
					var gradientSpecifier = [ angle.toString() + 'deg, ' ]

					for (var ii = 0, l = stops.length; ii &lt; l; ii++) {
						
						if ($.isArray(stops[ii])) {
							// Color
							gradientSpecifier.push(stops[ii][0].toString() + ' ');
							// Position
							gradientSpecifier.push(String(now + stops[ii][1]) + '%');
						} else {
							// Color only
							gradientSpecifier.push(stops[ii].toString());
						}
						
						if (ii &lt; l - 1) {
							gradientSpecifier.push(', ');
						}
					}
					
					gradientSpecifier = gradientSpecifier.join('');
					
					$(fx.elem).css('background-image', '-webkit-linear-gradient(' + gradientSpecifier + ')');
					$(fx.elem).css('background-image', '-moz-linear-gradient(' + gradientSpecifier + ')');
					$(fx.elem).css('background-image', '-o-linear-gradient(' + gradientSpecifier + ')');
					$(fx.elem).css('background-image', 'linear-gradient(' + gradientSpecifier + ')');
				},
				complete: function() {
					
					$this.css('percent', 0);
					$.effects.restore($this, props);
					
					$this.dequeue();
					
					if (o.callback) {
						o.callback.apply(this, arguments);
					}
				}
			});
		}
	});
};
})(jQuery);
&lt;/pre&gt;
&lt;p&gt;It's actually a pretty simple effect plug-in. It just sets up a custom CSS property iterator ('percent'), setting the value to get to to 125 (jQuery will animate from zero to that, and the completion function sets it back to zero), and on its way toward 125, will call the step function specified, which does the actual animating by creating a string that is the linear-gradient specifier, and setting the background-image CSS property of the specified element to that (since the linear-gradient value is not standardized yet, it sets the background-image property four different ways for Opera, Mozilla, Webkit, and finally the CSS3 standard).&lt;/p&gt;
&lt;p&gt;Please note that the stop positions specified in the array are &lt;span style="font-style: italic"&gt;offsets&lt;/span&gt; (unlike the CSS value itself which takes positions as percents -- the animation code converts the offsets to percents during the animation). Meaning, if you were to create a gradient at 10%, 20%, 100%, the offsets to put into the array are something like -25, -15, 65. It is important to usually start at -25 or so because the animator goes to +25 so that larger gradients can "complete" (it makes more sense when you watch the gradients themselves animate -- the trailing part needs to disappear for it to look right).&lt;/p&gt;
&lt;p style="font-weight: bold;"&gt;Also note that this plug-in requires &lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt;. Please reference the jQuery UI in your page when you use it or it won't work!&lt;/p&gt;
&lt;p&gt;OK, enough talking already, the example is &lt;a href="http://www.norimek.com/blogexamples/example/jQueryLinearGradientEffect/"&gt;here&lt;/a&gt;. There are a couple of examples of what the plug-in can do, but you can certainly do more with it. The plug-in source code is available via the link below.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.norimek.com/blogexamples/Scripts/jQueryLinearGradientEffect/jquery.effects.lineargradient.js"&gt;jquery.effects.lineargradient.js (1.80 kb)&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://www.norimek.com/blog/post/2011/08/27/jQuery-Linear-Gradient-Effect-Plug-In-Using-CSS3-Background-Image-Linear-Gradient-Value.aspx</link>
      <comments>http://www.norimek.com/blog/post/2011/08/27/jQuery-Linear-Gradient-Effect-Plug-In-Using-CSS3-Background-Image-Linear-Gradient-Value.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=b43e89cd-9647-46b2-8653-62e73d4c3451</guid>
      <pubDate>Sat, 27 Aug 2011 13:00:00 -0700</pubDate>
      <category>jQuery</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=b43e89cd-9647-46b2-8653-62e73d4c3451</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=b43e89cd-9647-46b2-8653-62e73d4c3451</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2011/08/27/jQuery-Linear-Gradient-Effect-Plug-In-Using-CSS3-Background-Image-Linear-Gradient-Value.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=b43e89cd-9647-46b2-8653-62e73d4c3451</wfw:commentRss>
    </item>
    <item>
      <title>Creating Custom Effects in jQuery</title>
      <description>&lt;p&gt;The other day I needed to create a custom effect in jQuery but I couldn&amp;rsquo;t find decent documentation on how to do it. I resorted to reading through the jQuery UI effects source code to figure it out, and while that&amp;rsquo;s fine, in case you&amp;rsquo;re looking to do the same thing (create a custom effect, not read through source code), I figured I&amp;rsquo;d write a post to at least speed up your development effort.&lt;/p&gt;
&lt;p&gt;All of the effects follow the same basic layout: a self-contained function that extends the $.effects namespace with the name of the effect (e.g. $.effects.myEffect) as a function that takes a single parameter (&amp;lsquo;o&amp;rsquo;, that contains all of the options the user of your effect passes in via the call, and some other information that jQuery stuffs in there).&lt;/p&gt;
&lt;p&gt;Inside this function, you basically just return the result of doing this.queue(); (which takes a single parameter &amp;ndash; a function). That call enqueues your effect into the jQuery animation queue. The code inside the queue call also follows the same basic structure: set up your effect properties, declare the CSS properties you want to set back to their original values (the jQuery UI infrastructure has a nice function pair [$.effect.save()/restore()] for saving and restoring CSS properties so that whatever element your effect was invoked on is returned to the visual state it was in before your effect was run), and then set up a loop to run your animation the number of times requested by the user of your effect. If the effect is the kind that you&amp;rsquo;d only run once (e.g. fade), you don&amp;rsquo;t need/want the loop. Regardless, you then call $.animate() to perform your custom animation, as necessary. A skeleton effect might look like this:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;
/** 
 * jQuery effect plug-in skeleton. 
 */ 
(function($, undefined) { 

$.effects.myEffect = function(o) { 

   return this.queue(function() { 

        var $this = $(this),  
            props = [ 'background-image' ], 
            times = o.options.times || 1, 
            duration = o.duration || 1000; 

        $this.css('percent', 0); 

        for (var i = 0; i &lt; times; i++) { 
            // Call $this.animate() as necessary to perform animation for your effect. 
        } 
    }); 
}; 
})(jQuery);
&lt;/pre&gt;
&lt;p style="margin-top: 6px;"&gt;This should be enough to get you started creating your own custom effects. One thing to note: in your last call to animate, you will want to make sure you set up a callback function, and in it, call $this.dequeue() or else your animation will never start, or else start the animation after the last animate call if your effect can&amp;rsquo;t be chained. That would also be where your restore the CSS properties you saved with $.effects.save() (line 15). For example (note: this is for a chained effect, you&amp;rsquo;ll want to animate with queue: false for this kind of effect, see the animate method&amp;rsquo;s &lt;a href="http://api.jquery.com/animate/"&gt;documentation&lt;/a&gt;):&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;
// Last animate call in the effect 
$this.animate({ /* Whatever */}, { 
    complete: function() { 

        $.effects.restore($this, props); 
        $this.dequeue(); 

        if (o.callback) { 
            o.callback.apply(this, arguments); 
        } 
    } 
});
&lt;/pre&gt;
&lt;p style="margin-top: 6px;"&gt;In an upcoming post, I will show how I created two custom effects that jQuery&amp;rsquo;s animate() function doesn&amp;rsquo;t natively support (linear-gradient and box-shadow) using the step parameter in the animate method.&lt;/p&gt;</description>
      <link>http://www.norimek.com/blog/post/2011/08/26/Creating-Custom-Effects-in-jQuery.aspx</link>
      <comments>http://www.norimek.com/blog/post/2011/08/26/Creating-Custom-Effects-in-jQuery.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=1b830976-fe69-47a0-81b6-64c880994685</guid>
      <pubDate>Fri, 26 Aug 2011 14:31:00 -0700</pubDate>
      <category>Algorithms</category>
      <category>Javascript</category>
      <category>jQuery</category>
      <category>Programming</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=1b830976-fe69-47a0-81b6-64c880994685</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=1b830976-fe69-47a0-81b6-64c880994685</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2011/08/26/Creating-Custom-Effects-in-jQuery.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=1b830976-fe69-47a0-81b6-64c880994685</wfw:commentRss>
    </item>
    <item>
      <title>Setting Up .net 3.5 SP1 URL Routing In IIS 5.1/6.0 Without Wildcard Mapping</title>
      <description>&lt;p&gt;With the release of .net 3.5 SP1 came the release of the URL routing framework, which makes it extremely easy to be able to map user-friendly URL's to different things inside your application (notably, this functionality is required for MVC).&lt;/p&gt;
&lt;p&gt;This all works fine in IIS 7, but if you're using IIS 5.1 on Windows XP Pro (like me) or IIS 6.0 on Vista, you're hosed. It simply will not work without a bit of hackery. The prevalent hackery involves using so-called wildcard mapping to map all file extensions to the asp.net ISAPI dll. This probably works in IIS 6.0 (I don't have it, so I'm guessing), but it certainly does &lt;em&gt;not&lt;/em&gt; work in IIS 5.1 (you'll get a bunch of happy-fun-time 404 errors, or, at least, I did, and so did at least one other person on the Internet that I saw). Besides, who wants every file request (including css, html, png, jpg, etc.) to go through the asp.net ISAPI dll? From what I understand, that can reduce the speed of a request by up to 30%. Yuck!&lt;/p&gt;
&lt;p&gt;A much better way to do it is to do what I recently&amp;nbsp;did:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up a custom extension for your stuff. If you're using MVC, that extension is chosen for you (.mvc). For my purposes (a toned-down content management system), I chose ".content." Just go into the configuration for your application in the IIS Management Console and add your extension (as I mentioned, .content in my case).&lt;/li&gt;
&lt;li&gt;Modify your RoutingTable Route rule to look for a static file with your extension (in my case, I chose content.content, so paths would look like: "content.content/{stuff}" with "stuff" being the parameter data the routing infrastructure would turn into a key/value pair for me.&lt;/li&gt;
&lt;li&gt;Install your URL rewriting ISAPI filter. I used &lt;a href="http://cheeso.members.winisp.net/IIRF.aspx" target="_blank"&gt; Ionic's ISAPI Rewrite Filter (IIRF)&lt;/a&gt;. The thing you want to do here is rewrite URL's to your specific folder alluded to in step 2 (for me, /content/) to whatever you chose for your RoutingTable entry (in my case, content.content). So, what happens for me is, if a request for "/hostname/virtualfolder/content/stuff" is made, it rewrites the URL to "hostname/virtualfolder/content.content/stuff". This makes it so that the asp.net ISAPI dll will now handle the request (because of the .content "extension").&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="margin-top: 1em;"&gt;There, now you're done. Three simple steps. Depending on the URL rewriting ISAPI filter you choose, getting the rewriting to work might be a slight pain. For instance, IIRF uses regular expressions and I needed help figuring out the magic regular expression that would do the rewrite appropriately (I suck at creating regular expressions unless I spend a couple of weeks neck-deep in them, which is rare). Incidentally, &lt;a href="http://www.gskinner.com/RegExr/" target="_blank"&gt;RegExr&lt;/a&gt; is an awesome online Flash-based regular-expression testing tool and is what I use to test regular expression syntax. It helps because it not only shows you what will be captured in your sample text, it also shows you the capture groups and has all kinds of help describing what each character in your regular expression is doing.&lt;/p&gt;
&lt;p&gt;I hope this saves someone some time.&lt;/p&gt;</description>
      <link>http://www.norimek.com/blog/post/2009/02/16/Setting-Up-net-35-SP1-URL-Routing-In-IIS-5160-Without-Wildcard-Mapping.aspx</link>
      <comments>http://www.norimek.com/blog/post/2009/02/16/Setting-Up-net-35-SP1-URL-Routing-In-IIS-5160-Without-Wildcard-Mapping.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=e2d6e46c-276d-4a40-91f5-8ad01cea078e</guid>
      <pubDate>Mon, 16 Feb 2009 21:14:00 -0700</pubDate>
      <category>Programming</category>
      <category>Setup</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=e2d6e46c-276d-4a40-91f5-8ad01cea078e</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=e2d6e46c-276d-4a40-91f5-8ad01cea078e</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2009/02/16/Setting-Up-net-35-SP1-URL-Routing-In-IIS-5160-Without-Wildcard-Mapping.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=e2d6e46c-276d-4a40-91f5-8ad01cea078e</wfw:commentRss>
    </item>
    <item>
      <title>10 Rules For Creating Decent Specifications Documents</title>
      <description>&lt;p&gt;It is an unfortunate state of our industry that I&amp;#39;ve worked on a large number of projects over the years but the quality of the specifications (if they existed at all) has been poor. Here are ten rules for creating &lt;span class="Apple-style-span" style="font-style: italic"&gt;decent&lt;/span&gt;&amp;nbsp;specification documents, in no particular order. They all begin with the statement, &amp;quot;A decent specification is one that...&amp;quot;&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&lt;/span&gt;1. Exists&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;If I had a dollar for every project I was on that contained zero written pages of specification, well, I&amp;#39;d be pretty poor, but the fact remains that a large percentage of projects simply have no written specification. Loads of reasons are given for this oversight (the requirements always change, there&amp;#39;s no time for specifications, there&amp;#39;s too much to document (!), etc.), but none of them outweigh the return on investment of actually knowing what you&amp;#39;re writing.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;2. Describes What, Not How&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;Many specifications have screenshots, pseudocode, and other things in them. These are all &lt;span class="Apple-style-span" style="font-style: italic"&gt;solutions&lt;/span&gt;&amp;nbsp;to a problem. The specification should &lt;span class="Apple-style-span" style="font-style: italic"&gt;not&lt;/span&gt;&amp;nbsp;describe &lt;span class="Apple-style-span" style="font-style: italic"&gt;how&lt;/span&gt;&amp;nbsp;to fix the problem, just &lt;span class="Apple-style-span" style="font-style: italic"&gt;what&lt;/span&gt;&amp;nbsp;the problem is. I will not pretend that this is an easy task, because it isn&amp;#39;t. It&amp;#39;s especially difficult for software engineers who (usually) will immediately try to figure out how to solve a problem. One can only describe the &amp;quot;what&amp;quot; of a&amp;nbsp;problem after some experience.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 17px"&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 22px"&gt;3. Can Be Interpreted In As Few Ways As Possible&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;This one is vital. If the specification is ambiguous, it isn&amp;#39;t really worthwhile. If software engineer A thinks it says one thing, QA tester B thinks it says another thing, and the customer thinks it says something else entirely, I can guarantee the solution will never solve the problem it was designed to in the first place.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;4. Is Widely Distributed&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;Everyone on the team needs to have access to the specification. This includes QA staff, managers, and especially the customer (in addition to the engineering team and whoever is writing it). Without access, everyone will have their own idea of what the software is supposed to do.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;5. Is Agreed Upon As Being The&amp;nbsp;Spec By All Parties Involved&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;There can sometimes be competing interests in a project, especially if the project has broad appeal. Group A has its goals and group B has its, and the two may not be congruent. If everyone agrees that whatever is in the spec is the way the software will work when its done, you can avoid the incongruous goals of disparate groups (or, at least, force them to agree to some sort of compromise before any code is written).&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;6. Is Concise&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;Wordy explanations and jargon-filled specs only confuse people. Only say what is necessary to describe the problem, and no more. Use language the average person off-the-street who has no knowledge of your problem domain can understand so that new software engineers to the project can come up to speed quickly.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;7. Is Consistent&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;If something is mentioned one way in one place, say it the same way everywhere. Or, better yet, refer the reader to the prior explanation. Inconsistincies in the spec will manifest themselves in engineering problems down the road.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;8. Is Updated Regularly As Requirements Change&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;It&amp;#39;s a fact of life in the software engineering world that the requirements are going to change. People change their minds. Customers are lost and gained. Those are the facts of life. What this means, however, is that someone is going to have to take on the job of maintaining the specification and time (and money) will have to be budgeted for that work in the project plan.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;9. Describes As Much Of The Problem As Is Possible And Practical&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;Gather as much information as you can when writing the specification, but if you can&amp;#39;t get any information about how a certain piece should work, leave it out. As long as it isn&amp;#39;t a key piece of the overall problem, it probably won&amp;#39;t affect anything and can be added later. On the flip-side, for things that are well-known, describe enough so that a software engineer can design a solution that will work.&lt;/p&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 11px; font-weight: normal"&gt;&amp;nbsp;&lt;/span&gt;10. Is Testable&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;Everything in the specification should be testable in some form. How else will you know if the solution provided solves the problem if it can&amp;#39;t be tested? You won&amp;#39;t and neither will the customer, and you&amp;#39;ll be left to haggle over that last payment.&lt;/p&gt;</description>
      <link>http://www.norimek.com/blog/post/2008/12/19/10-Rules-For-Creating-Decent-Specifications-Documents.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/12/19/10-Rules-For-Creating-Decent-Specifications-Documents.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=0a7b7e7e-9d71-41de-9a18-4f2c4bf72dd1</guid>
      <pubDate>Fri, 19 Dec 2008 17:13:00 -0700</pubDate>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=0a7b7e7e-9d71-41de-9a18-4f2c4bf72dd1</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=0a7b7e7e-9d71-41de-9a18-4f2c4bf72dd1</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/12/19/10-Rules-For-Creating-Decent-Specifications-Documents.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=0a7b7e7e-9d71-41de-9a18-4f2c4bf72dd1</wfw:commentRss>
    </item>
    <item>
      <title>Call Business Object Methods From Client JavaScript</title>
      <description>&lt;p&gt;
Using the techniques I will describe in this post you will be able to call just about any method on your business objects that your website project has a reference to, avoiding pass-through web service methods or static PageMethodAttribute&amp;#39;d methods on the aspx page. 
&lt;/p&gt;
&lt;h1&gt;History&lt;/h1&gt;
&lt;p&gt;
If you&amp;#39;ve worked with ASP.net AJAX for any length of time you&amp;#39;re probably called your fair share of webservices from client JavaScript or static methods on an aspx page via the PageMethods AJAX object and the PageMethodAttribute. 
&lt;/p&gt;
&lt;p&gt;
I was looking for a way to be able to call a method in my business objects directly from the client JavaScript, bypassing the pass-through methods. I knew this was possible because ASP.net AJAX does this itself. If I had to create all of these pass-through methods for the duration of my project, I was going to get very bored and there would be a lot of basically useless code that basically forwarded calls. 
&lt;/p&gt;
&lt;h1&gt;Revelation&lt;/h1&gt;
&lt;p&gt;
I realized, after researching how AJAX makes its calls (via an HttpHandler), that I could put together a ScriptControl that implemented IHttpHandler that would broker calls to any other object that the web project had a reference to (via reflection). This means that I could set up a call on the client (in JavaScript) directly to a method on my business object on the server, without an intervening PageMethodAttribute&amp;#39;d static method on the aspx page or creating a web service. 
&lt;/p&gt;
&lt;h1&gt;Start&lt;/h1&gt;
&lt;p&gt;
I called my control ClientBridge since it bridges the client and the business logic layer. Sometimes names are the hardest part of developing code, and I&amp;#39;m not convinced this name is all that great, but it&amp;#39;ll work for now. Anyway, as I mentioned, this class is both a ScriptControl as well as an HttpHandler, so it must inherit from ScriptControl and IHttpHandler: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Norimek.Web.UI.WebControls
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     [ToolboxData(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;{0}:ClientBridge runat=\&amp;quot;server\&amp;quot;&amp;gt;&amp;lt;/{0}:ClientBridge&amp;gt;&amp;quot;&lt;/span&gt;)]
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ClientBridge : ScriptControl, IHttpHandler
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1&gt;Creating The HttpHandler&lt;/h1&gt;
&lt;p&gt;
I&amp;#39;ll start with the HttpHandler part of the code since it&amp;#39;s short and more difficult. As I&amp;#39;m sure you know, the IHttpHandler interface has only one method: ProcessRequest. This is where you put the code to do whatever you need to do when your handler is called. The handler is called in response to whatever path you set up in your web.config for your handler. In the httpHandlers section of the web.config, you add your handler via the add tag: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;httpHandlers&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &amp;lt;add verb=&lt;span style="color: #006080"&gt;&amp;quot;*&amp;quot;&lt;/span&gt; path=&lt;span style="color: #006080"&gt;&amp;quot;ClientBridge.axd&amp;quot;&lt;/span&gt; validate=&lt;span style="color: #006080"&gt;&amp;quot;false&amp;quot;&lt;/span&gt; type=&lt;span style="color: #006080"&gt;&amp;quot;Norimek.Web.UI.WebControls.ClientBridge, Norimek.Web.UI.WebControls&amp;quot;&lt;/span&gt; /&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &amp;lt;/httpHandlers&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
We don&amp;#39;t care what the path is, it just needs to be the same as what is called on the client JavaScript. This will be taken care of with code we add to the ScriptControl, so as long as those two match, the user of the control will not need to deal with this information. 
&lt;/div&gt;
&lt;div&gt;
In ProcessRequest what we need to do is take the parameters that are passed in via the HttpContext parameter (specifically, in the context.Request.InputStream property). These are parameters that are sent as part of the web method call, which is set up in the ScriptControl&amp;#39;s JavaScript. The method takes three parameters: the name of the type to call, the name of the method to call, and a serialized parameters object, which is the parameters to the business object, which are parsed in ProcessRequest: 
&lt;/div&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ProcessRequest(HttpContext context)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Parameter_TypeName = &lt;span style="color: #006080"&gt;&amp;quot;typeName&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Parameter_MethodName = &lt;span style="color: #006080"&gt;&amp;quot;methodName&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Parameter_Parameters = &lt;span style="color: #006080"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; parameters = Common.DeserializeRequestParameters(context);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(parameters[Parameter_TypeName]))
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(Parameter_TypeName);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(parameters[Parameter_MethodName]))
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(Parameter_MethodName);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; typeName = parameters[Parameter_TypeName];
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; methodName = parameters[Parameter_MethodName];
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         Type objType;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;             objType = Type.GetType(typeName, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Exception(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;The typename specified &amp;#39;{0}&amp;#39; could not be loaded.&amp;quot;&lt;/span&gt;, typeName), e);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] parameterList;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         Type[] typeList;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         CreateParameterList(parameters[Parameter_Parameters], &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; parameterList, &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; typeList);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;         MethodInfo mi = objType.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, typeList, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mi == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Exception(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;Could not find a method for type &amp;#39;{0}&amp;#39; with the name &amp;#39;{1}&amp;#39; and the parameters types &amp;#39;{2}&amp;#39;.&amp;quot;&lt;/span&gt;, typeName, methodName, OutputArrayItems&amp;lt;Type&amp;gt;(typeList)));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mi.GetCustomAttributes(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(WebMethodAttribute), &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;).Length == 0)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Exception(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;Could not find a method for type &amp;#39;{0}&amp;#39; with the name &amp;#39;{1}&amp;#39; and the parameters types &amp;#39;{2}&amp;#39;.&amp;quot;&lt;/span&gt;, typeName, methodName, OutputArrayItems&amp;lt;Type&amp;gt;(typeList)));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;         ResponseObject response = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ResponseObject(mi.Invoke(&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, parameterList));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;         context.Response.ContentType = &lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;         context.Response.Cache.SetMaxAge(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TimeSpan(0));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; responseString = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; JavaScriptSerializer().Serialize(response);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (responseString != &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  52:&lt;/span&gt;             context.Response.Write(responseString);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  53:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  54:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  55:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  56:&lt;/span&gt;         Common.WriteExceptionJsonString(context, e);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  57:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  58:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  59:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Common.DeserializeRequestParameters is a helper function that does what it says and CreateParameterList is another helper function that deserializes the parameters parameter into an array of objects and types that are used in both GetMethod to find the specified method and in the method invocation to pass the parameter values. 
&lt;/p&gt;
&lt;p&gt;
Using these data (type to call, name of method, and parameters), the code uses reflection to load the specified type, find the specified method, and pass in the specified parameters. 
&lt;/p&gt;
&lt;p&gt;
Please note some design choices: the method it looks for can be public, private, or internal, but must be static and must be attributed with the WebMethodAttribute. This last constraint is a security consideration. The reason I added this constraint is because it makes it so that the client JavaScript can only call methods I want it to call. This constraint can easily be removed, if you like, but I suggest keeping it so that a malicious user cannot just make calls into your business objects all day long trying to find out what he or she can do. 
&lt;/p&gt;
&lt;h1&gt;Creating the Control&lt;/h1&gt;
&lt;p&gt;
The reason I implemented a ScriptControl is because then all I have to do is drop this control on a page and I can make all the calls to my business objects I want. Creating a ScriptControl is not trivial, and the documentation is a bit sketchy. 
&lt;/p&gt;
&lt;h2&gt;ScriptControl&lt;/h2&gt;
&lt;p&gt;
The two keys to implementing a ScriptControl is setting up the client properties of the client object (the object that will exist as a javascript object on the client) and creating the reference to the client JavaScript that will exist in a JavaScript file as an embedded resource file: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IEnumerable&amp;lt;ScriptDescriptor&amp;gt; GetScriptDescriptors()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     ScriptControlDescriptor descriptor = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ScriptControlDescriptor(&lt;span style="color: #006080"&gt;&amp;quot;AFU.ClientBridge&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     descriptor.AddProperty(&lt;span style="color: #006080"&gt;&amp;quot;timeout&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Timeout);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     descriptor.AddProperty(&lt;span style="color: #006080"&gt;&amp;quot;userContext&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.UserContext);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     descriptor.AddProperty(&lt;span style="color: #006080"&gt;&amp;quot;succeededCallback&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CallbackSucceededHandler);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     descriptor.AddProperty(&lt;span style="color: #006080"&gt;&amp;quot;failedCallback&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CallbackFailedHandler);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     descriptor.AddProperty(&lt;span style="color: #006080"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;, Common.MakeUrl(&lt;span style="color: #006080"&gt;&amp;quot;ClientBridge.axd&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Page.Request.Url));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ScriptDescriptor[] { descriptor };
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IEnumerable&amp;lt;ScriptReference&amp;gt; GetScriptReferences()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     ScriptReference reference = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ScriptReference(&lt;span style="color: #006080"&gt;&amp;quot;Adot.Fast.Web.UI.WebControls.ClientBridge.js&amp;quot;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #006080"&gt;&amp;quot;Adot.Fast.Web.UI.WebControls&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ScriptReference[] { reference };
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In GetScriptDescriptors, all of the descriptor.AddProperty calls are properties that exist on the JavaScript object. If they do not exist there, an error will occur upon loading the page on the client (note that the property names are case sensitive). As you can see, the url property is set here explicitly. As I mentioned earlier, the end-user need not worry about this parameter because it is set here by us once and for all. Whatever endpoint is here (in this case, ClientBridge.axd), it must match the line in the httpHandlers section, described earlier. 
&lt;/p&gt;
&lt;h2&gt;Client JavaScript&lt;/h2&gt;
&lt;p&gt;
The two purposes of the JavaScript is to define the object and to call the IHttpHandler. Conveniently, the ScriptControl implementation and the IHttpHandler implementation are in the same class. The JavaScript is rather short: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;//&amp;lt;![CDATA[&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Type.registerNamespace(&lt;span style="color: #006080"&gt;&amp;quot;Norimek.Web.UI&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; Norimek.Web.UI.ClientBridge = function(element)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     Norimek.Web.UI.ClientBridge.initializeBase(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, [element]);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._timeout = 0;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._userContext = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._succeededCallback = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._failedCallback = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._url;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt; Norimek.Web.UI.ClientBridge.prototype = 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     get_timeout: function() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._timeout; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     get_userContext: function() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._userContext; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     get_succeededCallback: function() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._succeeededCallback; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     get_failedCallback: function() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._failedCallback; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     get_url: function() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._url; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     set_timeout: function(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._timeout = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     set_userContext: function(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._userContext = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     set_succeededCallback: function(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._succeededCallback = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     set_failedCallback: function(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._failedCallback = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     set_url: function(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._url = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; },
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     invoke : function(typeName, methodName, parameters, succeededCallback, failedCallback, userContext, timeout)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Sys.Net.WebServiceProxy.invoke(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._url, &lt;span style="color: #006080"&gt;&amp;quot;invoke&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, { &lt;span style="color: #006080"&gt;&amp;quot;typeName&amp;quot;&lt;/span&gt; : typeName, 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                     &lt;span style="color: #006080"&gt;&amp;quot;methodName&amp;quot;&lt;/span&gt; : methodName, &lt;span style="color: #006080"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;: parameters }, 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;                     succeededCallback == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; ? eval(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._succeededCallback) : succeededCallback, 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;                     failedCallback == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; ? eval(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._failedCallback) : failedCallback, 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;                     userContext == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; ? &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._userContext : userContext, 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                     timeout == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; ? &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;._timeout : timeout);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt; Norimek.Web.UI.ClientBridge.registerClass(&lt;span style="color: #006080"&gt;&amp;quot;Norimek.Web.UI.ClientBridge&amp;quot;&lt;/span&gt;, Sys.UI.Control);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt; //]]&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
All there is are the property set and get accessors and the call to the Sys.Net.WebServiceProxy.invoke method. Since the url is &amp;quot;hard-coded&amp;quot; to the value set up in the ScriptControl.GetScriptDescriptors, the end-user does not need to know what it is. Note that this file must be marked as an &amp;quot;Embedded Resource&amp;quot; in the build action (right-click the file in the Solution Explorer and select Properties). 
&lt;/p&gt;
&lt;h1&gt;Use&lt;/h1&gt;
&lt;p&gt;
To use the control, add a reference to the dll to your web project, add a register tag to the page for the control&amp;#39;s library, and then drop the control on your page. Once the control is on your page you can call the invoke method of the control to call just about any type&amp;#39;s method that your web project has a reference to: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;%@ Page Language=&lt;span style="color: #006080"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; AutoEventWireup=&lt;span style="color: #006080"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; CodeBehind=&lt;span style="color: #006080"&gt;&amp;quot;default.aspx.cs&amp;quot;&lt;/span&gt; Inherits=&lt;span style="color: #006080"&gt;&amp;quot;ClientBridgeTest._Default&amp;quot;&lt;/span&gt; %&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &amp;lt;%@ register assembly=&lt;span style="color: #006080"&gt;&amp;quot;Norimek.Web.UI.WebControls&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt;=&lt;span style="color: #006080"&gt;&amp;quot;Norimek.Web.UI.WebControls&amp;quot;&lt;/span&gt; tagprefix=&lt;span style="color: #006080"&gt;&amp;quot;nor&amp;quot;&lt;/span&gt; %&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &amp;lt;!DOCTYPE html PUBLIC &lt;span style="color: #006080"&gt;&amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &amp;lt;html xmlns=&lt;span style="color: #006080"&gt;&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt; &amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &amp;lt;head runat=&lt;span style="color: #006080"&gt;&amp;quot;server&amp;quot;&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &amp;lt;title&amp;gt;ClientBridge Test&amp;lt;/title&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &amp;lt;/head&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &amp;lt;body&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &amp;lt;form runat=&lt;span style="color: #006080"&gt;&amp;quot;server&amp;quot;&lt;/span&gt; id=&lt;span style="color: #006080"&gt;&amp;quot;frmMain&amp;quot;&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &amp;lt;script type=&lt;span style="color: #006080"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         function test1()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             $find(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;%=ncbMain.ClientID %&amp;gt;&amp;quot;&lt;/span&gt;).invoke(&lt;span style="color: #006080"&gt;&amp;quot;Norimek.BusinessInterface.System1, Norimek.BusinessInterface&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;TestMethod1&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;{ &amp;#39;value1&amp;#39;: &amp;#39;System.Int32,10&amp;#39; }&amp;quot;&lt;/span&gt;, onCallbackSucceeded);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         function test2()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             $find(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;%=ncbMain.ClientID %&amp;gt;&amp;quot;&lt;/span&gt;).invoke(&lt;span style="color: #006080"&gt;&amp;quot;Norimek.BusinessInterface.System1, Norimek.BusinessInterface&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;TestMethod2&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;{ &amp;#39;value1&amp;#39;: &amp;#39;String,Value from parameter&amp;#39;, &amp;#39;value2&amp;#39;: { &amp;#39;value1&amp;#39;: [1, 2, 3], &amp;#39;value2&amp;#39;: 5 }, &amp;#39;value3&amp;#39;: &amp;#39;Int32,8&amp;#39; }&amp;quot;&lt;/span&gt;, onCallbackSucceeded);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         function onCallbackSucceeded(result, userContext, methodName)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;             alert(String.format(&lt;span style="color: #006080"&gt;&amp;quot;Response from method &amp;#39;{0}&amp;#39;: &amp;#39;{1}&amp;#39;.&amp;quot;&lt;/span&gt;, methodName, result));
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         &amp;lt;asp:ScriptManager runat=&lt;span style="color: #006080"&gt;&amp;quot;server&amp;quot;&lt;/span&gt; ID=&lt;span style="color: #006080"&gt;&amp;quot;scrMain&amp;quot;&lt;/span&gt; EnablePageMethods=&lt;span style="color: #006080"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; EnablePartialRendering=&lt;span style="color: #006080"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; /&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         &amp;lt;nor:ClientBridge runat=&lt;span style="color: #006080"&gt;&amp;quot;server&amp;quot;&lt;/span&gt; id=&lt;span style="color: #006080"&gt;&amp;quot;ncbMain&amp;quot;&lt;/span&gt; /&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         &amp;lt;button type=&lt;span style="color: #006080"&gt;&amp;quot;button&amp;quot;&lt;/span&gt; onclick=&lt;span style="color: #006080"&gt;&amp;quot;test1();&amp;quot;&lt;/span&gt;&amp;gt;Test 1&amp;lt;/button&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;         &amp;lt;button type=&lt;span style="color: #006080"&gt;&amp;quot;button&amp;quot;&lt;/span&gt; onclick=&lt;span style="color: #006080"&gt;&amp;quot;test2();&amp;quot;&lt;/span&gt;&amp;gt;Test 2&amp;lt;/button&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;     &amp;lt;/form&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt; &amp;lt;/body&amp;gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt; &amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Note: there must be an AJAX ScriptManager control on the page for the ClientBridge control to work; it uses the AJAX library&amp;#39;s infrastructure to define itself. 
&lt;/p&gt;
&lt;p&gt;
The first test (test1) shows a call to a simple method that takes a single integer value and returns a single integer value. The second test (test2) shows how you can pass strings and arrays into the server method. Not shown, but also possible, is the ability to return arrays and complex objects from the server method. Note that the format of the parameters is a JSON string. The type of a parameter is specified as the value in the form, &amp;quot;type,value&amp;quot;. Type can be either a fully-specified type (e.g. System.Int32) or just Int32. The type of the parameter is important so that the reflection code can find the the method signature. 
&lt;/p&gt;
&lt;h1&gt;Solution Example&lt;/h1&gt;
&lt;p&gt;
In the example (linked below), there are three projects: Norimek.Web.UI.WebControls, Norimek.Web.ClientBridgeTest, and Norimek.BusinessInterface. The first contains the code for the control. The second is a web project used to test the control. In this project you can see how to set up the calls in JavaScript. The third is a sample business interface layer library with a couple of test methods that are called from the web project&amp;#39;s default.aspx via JavaScript associated with the buttons on the page. With this project you can see how to handle the parameters that are passed in to the method. 
&lt;/p&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://www.norimek.com/blog/file.axd?file=ClientBridge.zip" target="_blank"&gt;ClientBridge.zip (76.62 kb)&lt;/a&gt; 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/06/07/Call-Business-Object-Methods-From-Client-JavaScript.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/06/07/Call-Business-Object-Methods-From-Client-JavaScript.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=031bae4d-24a2-4787-b5c2-fc98cdd07de4</guid>
      <pubDate>Sat, 07 Jun 2008 20:40:00 -0700</pubDate>
      <category>AJAX</category>
      <category>ASP.net Server Controls</category>
      <category>Programming</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=031bae4d-24a2-4787-b5c2-fc98cdd07de4</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=031bae4d-24a2-4787-b5c2-fc98cdd07de4</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/06/07/Call-Business-Object-Methods-From-Client-JavaScript.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=031bae4d-24a2-4787-b5c2-fc98cdd07de4</wfw:commentRss>
    </item>
    <item>
      <title>Implementing OptGroup In A DropDownList Control</title>
      <description>&lt;p&gt;
As I promised in the &lt;a href="http://www.norimek.com/blog/blog/post/2008/05/Displaying-Hierarchies-In-A-DropDownList-Control.aspx"&gt;previous post&lt;/a&gt;, I will detail how to implement the HTML &lt;a href="http://www.w3schools.com/tags/tag_optgroup.asp"&gt;&amp;lt;optgroup&amp;gt;&lt;/a&gt; tag inside a &amp;lt;select&amp;gt; tag in this post. The HTML markup looks as follows when using the optgroup tag: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;optgroup&lt;/span&gt; &lt;span style="color: #ff0000"&gt;label&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Group 1&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;optgroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;optgroup&lt;/span&gt; &lt;span style="color: #ff0000"&gt;label&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Group 2&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 4&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 5&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 6&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Item 7&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;option&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;optgroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
That code would render something like the following: 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.norimek.com/blog/image.axd?picture=WindowsLiveWriter/ImplementingOptGroupInADropDownListContr_12889/optgroupexample_thumb.png" border="0" alt="optgroupexample" width="88" height="175" /&gt; 
&lt;/p&gt;
&lt;p&gt;
As you can see, the optgroup tags render as bold and italicized group labels (that cannot be selected), and the items under each are indented. Note that in IE the optgroup tags cannot be styled but FireFox does permit styling. 
&lt;/p&gt;
&lt;p&gt;
As we know, the select tag is implemented in .net as the DropDownList control. At render time, the control renders &amp;lt;option&amp;gt; tags from its Items collection. At first glance, it would seem like all one has to do to subclass the control and add an OptionGroups collection property which is a collection of ListItems (the type of the standard Items property). While this &lt;em&gt;is&lt;/em&gt; part of what needs to be done, it is only the beginning. 
&lt;/p&gt;
&lt;h1&gt;Adding Option Groups&lt;/h1&gt;
&lt;p&gt;
To start off, obviously we must create a class that inherits from DropDownList. I called this control OptionGroupDropDownList. Next, we need to add something to hold the optgroup tags. I added an OptionGroups property to the control: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; OptionGroupCollection OptionGroups
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     get
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_optionGroups == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             _optionGroups = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; OptionGroupCollection();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_isTrackingViewState)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;                 _optionGroups.TrackViewState();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _optionGroups;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
As you can see, the OptionGroups property is of type OptionGroupCollection. Two helper classes are required to implement this control: the aforementioned OptionGroupCollection and OptionGroup. Additionally, some state management things are going on in the property get accessor (there&amp;#39;s no need for a set accessor). The state management is the thing that complicates this control beyond a simple subclass and render override that the UnEncodedDropDownList was. You&amp;#39;ll see why we need to manage state in a moment. 
&lt;/p&gt;
&lt;h1&gt;OptionGroupCollection And OptionGroup Classes&lt;/h1&gt;
&lt;p&gt;
To make things easy, OptionGroupCollection is simply a wrapper around a List&amp;lt;OptionGroup&amp;gt; private member. The OptionGroup is a couple of properties necessary to implement the optgroup tag and a wrapper for a ListItemCollection, which is a collection of the ListItems (option tags) that will render inside the optgroup tag. This is where the state management comes in. To make it easy for the user I wanted the items inside each OptionGroup to look and behave the same as the items in a normal DropDownList so I used the same class the built-in control uses: ListItemCollection. However, because ListItemCollection (and the ListItem child objects) are sealed, it is somewhat more cumbersome to manage the state of items in this collection than it would be otherwise. Luckily, ListItemCollection implements the IStateManager interface, which we will use to tell it when to manage its own state and obtain a state object. 
&lt;/p&gt;
&lt;h1&gt;State Management&lt;/h1&gt;
&lt;p&gt;
To correctly manage state, the OptionGroupDropDownList control must manually manage its own state by overriding all of the IStateManager methods of the base DropDownList control, most important among them being TrackViewState: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; TrackViewState()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.TrackViewState();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.OptionGroups.TrackViewState();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     _isTrackingViewState = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
TrackingViewState signals the control (and any child controls that also need to know via manual forwarding) to start tracking viewstate. Without this signal, the ListItemCollection would never save its state between server round-trips. OptionGroupCollection and OptionGroup both implement IStateManager and therefore TrackViewState. 
&lt;/p&gt;
&lt;p&gt;
Two other important methods to override in the OptionGroupDropDownList (with regard to state management) are SaveViewState and LoadViewState. This is because the OptionGroupsCollection&amp;#39;s state needs to be saved and loaded (which, in turn, saves the OptionGroup&amp;#39;s, which in turn saves the ListItemCollection&amp;#39;s state, which in turn saves the individual ListItem&amp;#39;s state - it&amp;#39;s just a chain and each individual object is responsible for saving its own state as an object and returning that object in SaveViewState). This is what these two method overrides look like: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; SaveViewState()
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Pair(&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.SaveViewState(), _optionGroups.SaveViewState());
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; LoadViewState(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; savedState)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     Pair viewState = (Pair)savedState;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.LoadViewState(viewState.First);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.OptionGroups.LoadViewState(viewState.Second);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1&gt;Rendering&lt;/h1&gt;
&lt;p&gt;
The last important method to override is the RenderContents method which actually renders out our new OptionGroup items. This method is not very complicated and simply iterates the OptionGroups and OptionGroup.Items: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RenderContents(System.Web.UI.HtmlTextWriter writer)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.OptionGroups.Count &amp;gt; 0)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (OptionGroup optionGroup &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.OptionGroups)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             writer.AddAttribute(&lt;span style="color: #006080"&gt;&amp;quot;label&amp;quot;&lt;/span&gt;, optionGroup.LabelText);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             optionGroup.LabelStyle.AddAttributesToRender(writer);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             writer.RenderBeginTag(&lt;span style="color: #006080"&gt;&amp;quot;optgroup&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (ListItem item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; optionGroup.Items)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Enabled)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;                 {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Selected)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                         writer.AddAttribute(HtmlTextWriterAttribute.Selected, &lt;span style="color: #006080"&gt;&amp;quot;selected&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                     writer.AddAttribute(HtmlTextWriterAttribute.Value, item.Value);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Attributes != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; item.Attributes.Count &amp;gt; 0)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;                         item.Attributes.Render(writer);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Page != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Page.ClientScript.RegisterForEventValidation(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.UniqueID, item.Value);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;                     writer.RenderBeginTag(&lt;span style="color: #006080"&gt;&amp;quot;option&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                     writer.Write(item.Text);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                     writer.RenderEndTag();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                 }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;             }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;             writer.RenderEndTag();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.RenderContents(writer);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1&gt;Use&lt;/h1&gt;
&lt;p&gt;
To use the control simply add OptionGroups and items to the OptionGroups you create: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; OptionGroupDropDownList ogdMain = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; OptionGroupDropDownList();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; OptionGroup group = ogdMain.OptionGroups.Add(&lt;span style="color: #006080"&gt;&amp;quot;Group 1&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 1&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 2&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 3&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; group = ogdMain.OptionGroups.Add(&lt;span style="color: #006080"&gt;&amp;quot;Group 2&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 4&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 5&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 6&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; group.Items.Add(&lt;span style="color: #006080"&gt;&amp;quot;Item 7&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; Page.Controls.Add(ogdMain);
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Of course, you can declare the control on the aspx page; I have created it here programmatically just so the code runs if you copy and paste. 
&lt;/p&gt;
&lt;p&gt;
This control works just fine inside an AJAX UpdatePanel, in case you&amp;#39;re wondering. There are some other incidentals with dealing with post data, which you can check out in the code, linked below. 
&lt;/p&gt;
&lt;h1&gt;Conclusion/Caveats&lt;/h1&gt;
&lt;p&gt;
This was an interesting control to implement as I had to do a bunch of spelunking using Reflector to figure out how ListItemCollection saves state. It permits me to use the optgroup tag in a select tag, which is not exactly a requirement very often, but it&amp;#39;s one of those things that when you need it, you need it. 
&lt;/p&gt;
&lt;p&gt;
Of course there are caveats: The default Items collection is not rendered in any way. I didn&amp;#39;t need both at the same time so I didn&amp;#39;t implement it. You can, however, change the code however you like. You&amp;#39;ll want to mess about in the RenderContents method. Additionally, not a whole lot of testing has been done. I know, as I stated above, that this control works with an AJAX postback just perfectly, however, I&amp;#39;m not exactly sure how it works with regular postbacks. Most likely it works fine since the AJAX scenario is more complicated, but I make no guarantees. 
&lt;/p&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://www.norimek.com/blog/file.axd?file=OptionGroupDropDownList.cs" target="_blank"&gt;OptionGroupDropDownList.cs (7.29 kb)&lt;/a&gt; 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/06/06/Implementing-OptGroup-In-A-DropDownList-Control.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/06/06/Implementing-OptGroup-In-A-DropDownList-Control.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=3b427d0d-cc38-48e3-8cb7-4302e65b1a1d</guid>
      <pubDate>Fri, 06 Jun 2008 20:32:00 -0700</pubDate>
      <category>ASP.net Server Controls</category>
      <category>Programming</category>
      <category>UI Controls</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=3b427d0d-cc38-48e3-8cb7-4302e65b1a1d</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=3b427d0d-cc38-48e3-8cb7-4302e65b1a1d</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/06/06/Implementing-OptGroup-In-A-DropDownList-Control.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=3b427d0d-cc38-48e3-8cb7-4302e65b1a1d</wfw:commentRss>
    </item>
    <item>
      <title>Displaying Hierarchies In A DropDownList Control</title>
      <description>&lt;p&gt;
A lot of software has hierarchies in it. Anything having to do with classifications, ordering, or reporting structures usually has some kind of hierarchy involved. Many times, a tree control is an easy and convenient way to show the hierarchy. It has nice little plus and minus signs as well as little tree &amp;quot;branch&amp;quot; lines linking the parent elements to the child elements. 
&lt;/p&gt;
&lt;p&gt;
However, sometimes a tree control is overkill. For instance, if you are adding functionality to permit the user to search through some records via a field that is a hierarchy, you don&amp;#39;t really need to show a whole tree control. A drop-down list with indented items would most likely fit the bill, especially if the hierarchy doesn&amp;#39;t have too many items. 
&lt;/p&gt;
&lt;p&gt;
Filling a drop-down list with hierarchical items is rather trivial when you think about it. As long as you know the hierarchy level of an item, and the items are given to you in order of the hierarchy, you can simply indent by the hierarchy level (e.g. if you have an element that is a first order ancestor of the root, indent by one space, two order ancestor, indent by two spaces, etc.). 
&lt;/p&gt;
&lt;p&gt;
To make this work, since user agents (browsers) automatically distill extra space in HTML (as they should, according to the HTML spec), you need to use the HTML character entity &amp;amp;nbsp; to add your extra spaces. In .net, however, there is a problem: the DropDownList control does not render HTML character entities in the ListItem text property. The implementation for the ListControl&amp;#39;s RenderContents method (DropDownList is derived from ListControl) uses the HttpUtility class&amp;#39;s HtmlEncode method when writing out the ListItem&amp;#39;s text. This makes &lt;em&gt;any&lt;/em&gt; attempt at adding an HTML character entity futile. What&amp;#39;s a developer to do? Well, you can derive a new control from DropDownList and override the RenderContents method yourself: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI.WebControls;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Norimek.Web.UI.WebControls
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; UnEncodedDropDownList : DropDownList
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RenderContents(System.Web.UI.HtmlTextWriter writer)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             ListItemCollection items = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Items;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; items.Count; i++)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                 ListItem item = items[i];
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Enabled)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                 {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                     writer.WriteBeginTag(&lt;span style="color: #006080"&gt;&amp;quot;option&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Selected)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                         writer.WriteAttribute(&lt;span style="color: #006080"&gt;&amp;quot;selected&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;selected&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                     writer.WriteAttribute(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;, item.Value, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (item.Attributes != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; item.Attributes.Count &amp;gt; 0)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                         item.Attributes.Render(writer);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Page != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Page.ClientScript.RegisterForEventValidation(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.UniqueID, item.Value);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                     writer.Write(&lt;span style="color: #006080"&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;                     writer.Write(item.Text);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                     writer.WriteEndTag(&lt;span style="color: #006080"&gt;&amp;quot;option&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;                     writer.WriteLine();
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;                 }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;             }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  42:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The important part is line 34. Where it previously was HttpUtility.HtmlEncode(item.Text, writer), it is now just plain writer.Write(item.Text). Just use this control in place of a regular DropDownList control anytime you need to display a hierarchical list (or need to use HTML character entities in drop-down). I leave the creation of the controls item collection as an exercise for the reader since it will be highly-individualized. Suffice it to say it will very likely involve a small recursive function. 
&lt;/p&gt;
&lt;p&gt;
Of course you know, with great power comes great responsibility. Microsoft encoded that value for a reason. A lot of the time that text value is something the user entered. A malicious user could enter all sorts of crazy stuff into whatever data is later displayed on the page via this new control and wreak havoc with your application. It is your responsibility to make sure that the data that is in that text property is not something that will harm your user or the website, or anything else for that matter. 
&lt;/p&gt;
&lt;p&gt;
Next time I will show you how to implement a derived DropDownList that gives you the ability to use the &amp;lt;optgroup&amp;gt; tag inside of it so you can group your option items. Not terribly important, but very convenient when needed. And, surprisingly, a little bit more complicated than it seems it would be when you first look at it. 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/05/22/Displaying-Hierarchies-In-A-DropDownList-Control.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/05/22/Displaying-Hierarchies-In-A-DropDownList-Control.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=eb82e3e7-121b-4c19-9618-e5fdfeb9fbc8</guid>
      <pubDate>Thu, 22 May 2008 10:01:00 -0700</pubDate>
      <category>ASP.net Server Controls</category>
      <category>Programming</category>
      <category>UI Controls</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=eb82e3e7-121b-4c19-9618-e5fdfeb9fbc8</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=eb82e3e7-121b-4c19-9618-e5fdfeb9fbc8</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/05/22/Displaying-Hierarchies-In-A-DropDownList-Control.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=eb82e3e7-121b-4c19-9618-e5fdfeb9fbc8</wfw:commentRss>
    </item>
    <item>
      <title>Query a Single Field for Multiple Values in a Stored Procedure</title>
      <description>&lt;p&gt;
Every once-in-a-while it would just be convenient to query a single field for multiple values. For example, you want to select from your database the people who live in the states of Arizona, New Mexico, and California. That&amp;#39;s no big deal, just do an IN, right? Sure, that works fine, if you know in advance what states you want to look for; but what if you don&amp;#39;t? What if a user of your application can pick any number of any of the fifty states to search for? 
&lt;/p&gt;
&lt;p&gt;
I guess one &lt;em&gt;could&lt;/em&gt; assign a bit value to each state, sum the bit values of the selected states, and then do some bit-wise arithmetic in the SELECT, but what if your list is of more than fifty items? Or the list is of user-defined items that you can&amp;#39;t assign a bit value to beforehand? Well, then you can use the method I have outlined here. 
&lt;/p&gt;
&lt;p&gt;
To get this to work, you create a delimited string of ID&amp;#39;s and pass that into the stored procedure and do a like operation on it in the WHERE clause: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;where&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     @stateIDString &lt;span style="color: #0000ff"&gt;like&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;#39;%|&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(StateID &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;(max)) + &lt;span style="color: #006080"&gt;&amp;#39;|%&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This will allow SQL Server to compare the ID&amp;#39;s in the table to the delimited string. You can have as many ID&amp;#39;s in the string as you need. As you can tell from the example, the string is delimited by pipes (&amp;#39;|&amp;#39;) and must both start and end with the pipe (e.g. &amp;#39;|1|34|67|9|&amp;#39;). You do not need to delimit the string with a pipe. As long as you&amp;#39;re comparing against a number, it can be anything &lt;em&gt;other than&lt;/em&gt; a number. 
&lt;/p&gt;
&lt;p&gt;
As you can expect, there are drawbacks to this method. It is not fast. Searching a table with 500,000 rows took about four seconds, and searching a table with one million rows took about nine seconds. I was able to reduce the time by about half by adding a column to the table that was a pre-delimited version of the ID field (e.g. it contained &amp;#39;%|23|%&amp;#39; if the ID was 23). In this case, the like would just contain the name of the field. This field would be easy to set once during the insert operation via the business object, the stored procedure doing the insert, or even a trigger. 
&lt;/p&gt;
&lt;p&gt;
I can&amp;#39;t take credit for this tip (although the aforementioned optimization is my own idea). A guy that likes to go by the name Homer Sapien introduced this technique to me a while ago. If you happen to know who he is, good for you. If not, your loss. :-) 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/04/30/Query-a-Single-Field-for-Multiple-Values-in-a-Stored-Procedure.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/04/30/Query-a-Single-Field-for-Multiple-Values-in-a-Stored-Procedure.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=293971eb-be54-4e57-b0e2-17294510493e</guid>
      <pubDate>Wed, 30 Apr 2008 18:06:00 -0700</pubDate>
      <category>Programming</category>
      <category>SQL</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=293971eb-be54-4e57-b0e2-17294510493e</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=293971eb-be54-4e57-b0e2-17294510493e</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/04/30/Query-a-Single-Field-for-Multiple-Values-in-a-Stored-Procedure.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=293971eb-be54-4e57-b0e2-17294510493e</wfw:commentRss>
    </item>
    <item>
      <title>Dynamic Sort Parameters in MS SQL Server 2005</title>
      <description>&lt;p&gt;
I prefer to have the parts of a software system that are good at particular tasks to do those tasks. Case in point: sorting. SQL Server (with proper indexes) is very good at sorting data, so I make sure that most, if not all of the sorting of data in my applications occurs in stored procedures in SQL Server. 
&lt;/p&gt;
&lt;p&gt;
This can cause a bit of a problem, however, if you&amp;#39;re developing an application that permits the user to sort by different columns. One solution would be to write as many different stored procedures as you have sort criteria. Maintenance would be a nightmare on that so I don&amp;#39;t think it&amp;#39;s a good idea. Another way would be to parameterize the sort criteria into either a string or magic numbers and use a case statement in the ORDER BY clause to figure out what to sort by. That is the method I often use, and it looks like this: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;order&lt;/span&gt; &lt;span style="color: #0000ff"&gt;by&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;asc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; desc
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In this example, imagine we are sorting a table with a person&amp;#39;s first and last names as fields named (conveniently) FirstName and LastName. The first part permits sorting in ascending order and the second part permits sorting in descending order. The @sortExpression takes the form that .net data controls serve up. It is important to CAST the field names as sql_variant type. In this example, it doesn&amp;#39;t really matter, however, if the data types of the columns that are returned from the case statement are different (e.g. an NVARCHAR and a DATETIME), SQL Server will complain because it can&amp;#39;t figure out what data type you&amp;#39;re trying to return (it will choose the data type of the first element in the CASE statement, and anything that isn&amp;#39;t that type or can be implicitly converted to that type, will cause it to have an error at run-time). 
&lt;/p&gt;
&lt;p&gt;
Okay, so this solves the immediate problem of being able to sort by parameter, but what if we want to sort by multiple fields? For example, when the user sorts by LastName (as in the example above), shouldn&amp;#39;t the software also sort by FirstName as a secondary sort field? Of course it should. Here&amp;#39;s how you do that: 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;order&lt;/span&gt; &lt;span style="color: #0000ff"&gt;by&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;asc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;asc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname asc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;asc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;desc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;lastname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(FirstName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; &lt;span style="color: #0000ff"&gt;desc&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #0000ff"&gt;when&lt;/span&gt; @sortExpression = &lt;span style="color: #006080"&gt;&amp;#39;firstname desc&amp;#39;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;then&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(LastName &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sql_variant&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; desc
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Notice lines 6, 7, 12, and 13. These lines inject another field into the order by clause &lt;em&gt;after&lt;/em&gt; the first case statement has already returned the primary field. They are whole CASE statements all on their own. You can continue to add fields to the sort list in this way until your hands get tired. In this example, I&amp;#39;m sorting by FirstName as a secondary field when the user selects the LastName field to sort by (and vice-versa); you, however, can make it do whatever you want. For example, you might permit the user to sort by HireDTm (representing the date this person was hired), and then by LastName and FirstName using the technique above. If you happen to also need the ability to page the returned data, this method also works perfectly with the ROW_NUMBER() OVER() syntax also introduced in SQL Server 2005. Just put the order by information in the OVER() part. 
&lt;/p&gt;
&lt;p&gt;
Of course, nothing is perfect and there are a couple of problems with this method. The first (which I consider minor) is that the user cannot select the secondary (and further) sort fields. I suppose if you &lt;em&gt;really&lt;/em&gt; wanted to, you could change the @sortExpression parameter to be something other than what I have above and instead pass in a value that indicates which of a matrix of combinations of sort fields the user has selected, and then write the WHEN parts of the CASE statement for &lt;em&gt;every combination&lt;/em&gt; the user could choose. While that would probably work, I&amp;#39;m thinking it&amp;#39;s overkill (and a lot of work). You can usually get away with a couple of static secondary field choices, as long as you spend a couple of moments thinking about how the data is used by the user. 
&lt;/p&gt;
&lt;p&gt;
The second problem is that this method is not very speedy. In a table with 500,000 rows, it will return in about two seconds (my test table had six columns, one primary key integer IDENTITY column, and five data columns, which were NVARCHAR(50), NVARCHAR(100), INT, INT, and NUMERIC(14, 4)). In a table with over three million rows (3.2 to be exact), it took between 18 and 22 seconds. I didn&amp;#39;t do enough tests to see if the speed degradation is linear or geometric, but it&amp;#39;s not good, nonetheless. If you use this method, use it on smallish tables. 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/04/29/Dynamic-Sort-Parameters-in-MS-SQL-Server-2005.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/04/29/Dynamic-Sort-Parameters-in-MS-SQL-Server-2005.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=a27e651c-46dd-4e99-8e42-b637fefb679e</guid>
      <pubDate>Tue, 29 Apr 2008 19:04:00 -0700</pubDate>
      <category>Programming</category>
      <category>SQL</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=a27e651c-46dd-4e99-8e42-b637fefb679e</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=a27e651c-46dd-4e99-8e42-b637fefb679e</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/04/29/Dynamic-Sort-Parameters-in-MS-SQL-Server-2005.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=a27e651c-46dd-4e99-8e42-b637fefb679e</wfw:commentRss>
    </item>
    <item>
      <title>Calculating Work Days</title>
      <description>&lt;p&gt;
A couple of weeks ago a client of mine asked for a feature in which the software could display the number of days a piece of work was overdue. That&amp;#39;s not a problem. Naturally, however, they wanted it to be &lt;em&gt;work&lt;/em&gt; days. I didn&amp;#39;t want to explain how computers are unbelievably bad at messing with dates so I just said &amp;quot;sure.&amp;quot; 
&lt;/p&gt;
&lt;p&gt;
The other day I came to the part in the project where I had to implement this feature. Figuring someone, somewhere had figured out how to do this (and published it in a blog or something), I perused Google. Unfortunately, the solutions I found either involved using the Microsoft.VisualBasic assembly and the DateDiff function (which don&amp;#39;t work*) or writing a row to a database table for every day in the year, with various shenanigans to determine whether the day is a work day or not, running the gamut from computed columns (which I actually liked) to indexing the entire year by number, skipping non-work days. 
&lt;/p&gt;
&lt;p&gt;
I really did not want to create a solution in which my client would need to tediously create a new calendar for every day of the year, every year. I&amp;#39;m sure I could have written a nice UI and everything but I didn&amp;#39;t want to waste the time or money. Instead, I figured I could write an algorithm that figures out weekends mathematically. The result follows. It took me about three hours before I had something that worked and I don&amp;#39;t guarantee this works for every two valid date combinations, but it passed the 27 tests I could think of. 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// Calculates the whole number of work days between two arbitrary dates.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;param name=&amp;quot;startDate&amp;quot;&amp;gt;The first date of the range to check.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;param name=&amp;quot;endDate&amp;quot;&amp;gt;The second date of the range to check.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;param name=&amp;quot;nonWorkDays&amp;quot;&amp;gt;An array of DateTime values indicating non-work days. Note: This&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// array cannot contain days that occur on weekends.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;returns&amp;gt;The count of whole work days that occur between startDate and endDate, inclusive.&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CalculateWorkdaysCount(
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             DateTime startDate,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             DateTime endDate,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             DateTime[] nonWorkDays)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Zero the time&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     DateTime sdt = startDate.Subtract(startDate.TimeOfDay);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     DateTime edt = endDate.Subtract(endDate.TimeOfDay);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (sdt &amp;gt; edt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Get an initial workdays count&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; workDays = (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)edt.Subtract(sdt).TotalDays + 1;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; weeks = workDays / 7;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Subtract the weekends indicated by the number of whole weeks the dates span&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     workDays -= weeks * 2;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Remove the whole weeks from the span and figure out what is left&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     edt = edt.AddDays(-weeks * 7);
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Subtracting the whole weeks leaves us with a partial week. If the date span is a&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// a multiple of seven, edt will be == sdt and need not be checked. At this point,&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// anything over a week looks the same as if the date span were less than a week, originally.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (edt &amp;gt; sdt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// If the start and end dates span a weekend, decrement the work day count by two&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (sdt.DayOfWeek &amp;gt; edt.DayOfWeek &amp;amp;&amp;amp; edt.DayOfWeek &amp;lt; DayOfWeek.Saturday &amp;amp;&amp;amp; edt.DayOfWeek &amp;gt; DayOfWeek.Sunday)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;             workDays -= 2;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// If the start date is a Saturday or Sunday, decrement the work day count&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (sdt.DayOfWeek == DayOfWeek.Saturday || sdt.DayOfWeek == DayOfWeek.Sunday)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;                 workDays--;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// If the end date is a Saturdayor Sunday, decrement the work day count&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (edt.DayOfWeek == DayOfWeek.Saturday || edt.DayOfWeek == DayOfWeek.Sunday)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;                 workDays--;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Remove the non-work days from the count if they are between the (original) startDate and endDate.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Note: the times of the non-work days are zeroed.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  52:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// This implies that a nonWorkDay cannot be a weekend due to the calculations, above.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  53:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (nonWorkDays != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  54:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (DateTime nonWorkDay &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; nonWorkDays)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  55:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (nonWorkDay.Subtract(nonWorkDay.TimeOfDay) &amp;gt;= startDate &amp;amp;&amp;amp; nonWorkDay.Subtract(nonWorkDay.TimeOfDay) &amp;lt;= endDate)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  56:&lt;/span&gt;                 workDays--;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  57:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  58:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; workDays;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  59:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I also created a version as an MS SQL Server function so that data I pull out of the database can have counts in them and, more importantly, I can use the calculation in a WHERE clause. 
&lt;/p&gt;
&lt;div style="font-size: 8pt; margin: 0px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px"&gt;
&lt;div style="font-size: 8pt; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; ANSI_NULLS &lt;span style="color: #0000ff"&gt;ON&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; QUOTED_IDENTIFIER &lt;span style="color: #0000ff"&gt;ON&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff"&gt;FUNCTION&lt;/span&gt; [dbo].[CalculateWorkdaysCount]
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; (
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     @refCalendarTypeID &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     @startDate datetime,
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     @endDate datetime
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; )
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;RETURNS&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;BEGIN&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #008000"&gt;-- Note: If @@DATEFIRST != 7, this function won&amp;#39;t work&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @sdt datetime
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @edt datetime
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (@startDate &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &lt;span style="color: #0000ff"&gt;or&lt;/span&gt; @endDate &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @sdt = &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;MONTH&lt;/span&gt;(@startDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) + &lt;span style="color: #006080"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;DAY&lt;/span&gt;(@startDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) + &lt;span style="color: #006080"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;YEAR&lt;/span&gt;(@startDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; datetime)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @edt = &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;MONTH&lt;/span&gt;(@endDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) + &lt;span style="color: #006080"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;DAY&lt;/span&gt;(@endDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) + &lt;span style="color: #006080"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;YEAR&lt;/span&gt;(@endDate) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; datetime)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (@sdt &amp;gt; @edt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @workDays &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @weeks &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = DATEDIFF(&lt;span style="color: #0000ff"&gt;day&lt;/span&gt;, @sdt, @edt) + 1
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @weeks = @workDays / 7
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = @workDays - (@weeks * 2)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @edt = DATEADD(&lt;span style="color: #0000ff"&gt;day&lt;/span&gt;, -@weeks * 7, @edt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; @edt &amp;gt; @sdt
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;begin&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @sdtWeekday &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @edtWeekday &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @sdtWeekday = DATEPART(weekday, @sdt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @edtWeekday = DATEPART(weekday, @edt)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;         
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (@sdtWeekDay &amp;gt; @edtWeekDay &lt;span style="color: #0000ff"&gt;and&lt;/span&gt; @edtWeekDay &amp;lt; 7 &lt;span style="color: #0000ff"&gt;and&lt;/span&gt; @edtWeekDay &amp;gt; 1)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = @workDays - 2
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;begin&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  52:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  53:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (@sdtWeekday = 7 &lt;span style="color: #0000ff"&gt;or&lt;/span&gt; @sdtWeekDay = 1)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  54:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = @workDays - 1
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  55:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  56:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (@edtWeekDay = 7 &lt;span style="color: #0000ff"&gt;or&lt;/span&gt; @edtWeekDay = 1)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  57:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = @workDays - 1
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  58:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  59:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  60:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  61:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  62:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  63:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; @refCalendarTypeID &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  64:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  65:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;begin&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  66:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  67:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @nonWorkDayCount &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  68:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  69:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;select&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  70:&lt;/span&gt;             @nonWorkDayCount = &lt;span style="color: #0000ff"&gt;COUNT&lt;/span&gt;(*)
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  71:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;from&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  72:&lt;/span&gt;             Calendars c
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  73:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;where&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  74:&lt;/span&gt;             c.RefCalendarTypeID = @refCalendarTypeID
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  75:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;and&lt;/span&gt; c.NonWorkDayDate &lt;span style="color: #0000ff"&gt;between&lt;/span&gt; @startDate &lt;span style="color: #0000ff"&gt;and&lt;/span&gt; @endDate
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  76:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  77:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; @workDays = @workDays - @nonWorkDayCount
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  78:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  79:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  80:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  81:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; @workDays
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  82:&lt;/span&gt;&amp;nbsp; 
&lt;/pre&gt;
&lt;pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px"&gt;
&lt;span style="color: #606060"&gt;  83:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;END&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1&gt;How It Works&lt;/h1&gt;
&lt;p&gt;
The function takes a start date, end date, and an array of non-work days. The non-work days parameter can be NULL. The function first figures out the number of days between the two dates. Then, it figures out the number of full weeks between the two days and subtracts out 2 * the number of weeks from the previously calculated total days. It then subtracts the number of days in the full weeks from the end date, which will leave us with the partial week that is at either the beginning or end of the range. Then a little checking is done to see if this period spans a weekend and starts or ends on a weekend day, and depending on what it figures out, the appropriate amount is subtracted from the running total. Lastly, it runs through the non-working days checking if any occur between the start and end dates, and subtracts those that do from the running count. 
&lt;/p&gt;
&lt;p&gt;
The T-SQL function expects there to be a table named &lt;strong&gt;Calendars&lt;/strong&gt; with two fields: RefCalendarTypeID (int) and NonWorkDayDate (smalldatetime). This is because you can&amp;#39;t exactly pass in an array of non-work days like you can in the C# function. Just add your non-work days (e.g. holidays) to the Calendars table, and the function will calculate the number of work days between two valid dates. If you don&amp;#39;t need that functionality, you can take out that portion at the end of the function. You&amp;#39;ll notice the function also takes a parameter @refCalendarTypeID. This corresponds to the RefCalendarTypeID field in the Calendars table and enables you to have more than one calendar of non-work days. 
&lt;/p&gt;
&lt;h1&gt;Caveats&lt;/h1&gt;
&lt;p&gt;
There are a few caveats that you need to be aware of. If you define a non-work day in the non-work days array (or table in the T-SQL function, below) that falls on a weekend it will be counted twice. Also, if you&amp;#39;re working on&amp;nbsp;a project or in an area&amp;nbsp;where weekends &lt;em&gt;are&lt;/em&gt; work days (or either of Saturday or Sunday) this function won&amp;#39;t work, but you can of course tweak it to do what you want. One last thing: in the T-SQL function, as the comment states, @@DATEFIRST must be equal to 7 or&amp;nbsp;it won&amp;#39;t work (see &lt;a href="http://msdn2.microsoft.com/en-us/library/ms181598.aspx" target="_blank"&gt;SET DATEFIRST&lt;/a&gt; in the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms130214.aspx" target="_blank"&gt;SQL Server BOL&lt;/a&gt;). 
&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;
I like this method better than the numerous methods involving filling a database table with each day of the year because the maintenance is reduced. It will degrade nicely if there are no non-work days defined and it doesn&amp;#39;t cause the calendar table to be filled with almost 2,000 rows after five years in production (not that 2,000 rows is a lot, but if we use 10 holidays per year as non-work days, that&amp;#39;s only 50 rows with this implementation). 
&lt;/p&gt;
&lt;hr size="1" /&gt;
&lt;p&gt;
* If you use Reflector to check out the DateDiff function, you&amp;#39;ll see that all it does is divide the total days between the two dates by seven and return that as a long when you pass in a DateInterval of Weekday. I dont think I have to say that this won&amp;#39;t work for our purposes (frankly, I&amp;#39;m at a loss for a situation in which this &lt;em&gt;would&lt;/em&gt; work). 
&lt;/p&gt;
</description>
      <link>http://www.norimek.com/blog/post/2008/04/24/Calculating-Work-Days.aspx</link>
      <comments>http://www.norimek.com/blog/post/2008/04/24/Calculating-Work-Days.aspx#disqus_thread</comments>
      <guid>http://www.norimek.com/blog/post.aspx?id=55abf763-1a07-4304-bf93-37d8a6566f58</guid>
      <pubDate>Thu, 24 Apr 2008 19:35:00 -0700</pubDate>
      <category>Algorithms</category>
      <category>Programming</category>
      <category>SQL</category>
      <dc:publisher>Robert Barth</dc:publisher>
      <pingback:server>http://www.norimek.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.norimek.com/blog/post.aspx?id=55abf763-1a07-4304-bf93-37d8a6566f58</pingback:target>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.norimek.com/blog/trackback.axd?id=55abf763-1a07-4304-bf93-37d8a6566f58</trackback:ping>
      <wfw:comment>http://www.norimek.com/blog/post/2008/04/24/Calculating-Work-Days.aspx#disqus_thread</wfw:comment>
      <wfw:commentRss>http://www.norimek.com/blog/syndication.axd?post=55abf763-1a07-4304-bf93-37d8a6566f58</wfw:commentRss>
    </item>
  </channel>
</rss>