<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ancient Geek</title>
	<atom:link href="http://www.ancientgeek.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ancientgeek.co.uk</link>
	<description>Remembrances of internet past</description>
	<lastBuildDate>Sun, 25 Dec 2011 18:13:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Limiting rows returned in SQL Server</title>
		<link>http://www.ancientgeek.co.uk/2011/09/25/limiting-rows-returned-in-sql-server/</link>
		<comments>http://www.ancientgeek.co.uk/2011/09/25/limiting-rows-returned-in-sql-server/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 06:01:39 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[common table expression]]></category>
		<category><![CDATA[CROSS APPLY]]></category>
		<category><![CDATA[derived table]]></category>
		<category><![CDATA[ROW_NUMBER]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=240</guid>
		<description><![CDATA[I&#8217;ve always felt it a shame that SQL Server lacks the limit clause like that in MySQL.  The limit clause lets you decide which rows to get back and you can choose to have say rows 51 to 100.  OK in SQL Server you can use top to choose the first 100 and then ignore [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always felt it a shame that SQL Server lacks the limit clause like that in MySQL.  The limit clause lets you decide which rows to get back and you can choose to have say rows 51 to 100.  OK in SQL Server you can use top to choose the first 100 and then ignore 50 but it never felt that smart and when you want rows 1001 to 1051 it&#8217;s positively inefficient.</p>
<p>Using the AdventureWorksLT2008R2 database and with a little help from ROW_NUMBER I have this.</p>
<pre>SELECT custdet.CustomerID
      ,NameStyle
      ,Title
      ,FirstName
      ,MiddleName
      ,LastName
      ,Suffix
      ,CompanyName
      ,SalesPerson
      ,EmailAddress
      ,Phone
FROM (SELECT ROW_NUMBER() OVER (ORDER BY CompanyName) rownum
	,CustomerID
  FROM SalesLT.Customer) custlist
CROSS APPLY (SELECT CustomerID
      ,NameStyle
      ,Title
      ,FirstName
      ,MiddleName
      ,LastName
      ,Suffix
      ,CompanyName
      ,SalesPerson
      ,EmailAddress
      ,Phone
  FROM SalesLT.Customer
  WHERE CustomerID = custlist.CustomerID) custdet
WHERE rownum BETWEEN 51 AND 100</pre>
<p>I like this approach with derived tables and the CROSS APPLY because the right hand derived table query will only have 50 rows queried, which can be important if there is a NTEXT or NVARCHAR(MAX) column included with loads of data therein.</p>
<p>However the reason I&#8217;m wanting this is to produce paginated lists so it would be handy to know how many rows would be returned overall, so I can decide how many pages there will be.  So the next step was to get this without running two queries (a count and the one above).</p>
<p>Using a common table expression and a union is the answer I came up with.</p>
<pre>WITH custlist AS (SELECT ROW_NUMBER() OVER (ORDER BY CompanyName) rownum
	,CustomerID
  FROM SalesLT.Customer)
SELECT NULL, custdet.CustomerID
      ,NameStyle
      ,Title
      ,FirstName
      ,MiddleName
      ,LastName
      ,Suffix
      ,CompanyName
      ,SalesPerson
      ,EmailAddress
      ,Phone
      ,PasswordHash
      ,PasswordSalt
      ,rowguid
      ,ModifiedDate
FROM custlist
INNER JOIN SalesLT.Customer custdet
ON custdet.CustomerID = custlist.CustomerID
WHERE rownum BETWEEN 51 AND 100
UNION ALL SELECT MAX(rownum)
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
FROM custlist</pre>
<p>So I still only pull 50 rows from the customer details, only hit the database once and get the number of rows returned (which will let me workout how many pages there will be).  Using UNION ALL removes a SELECT DISTINCT from the plan but makes little difference to performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2011/09/25/limiting-rows-returned-in-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Binding DataGridColumn visibility attribute</title>
		<link>http://www.ancientgeek.co.uk/2011/09/24/binding-datagridcolumn-visibility-attribute/</link>
		<comments>http://www.ancientgeek.co.uk/2011/09/24/binding-datagridcolumn-visibility-attribute/#comments</comments>
		<pubDate>Sat, 24 Sep 2011 13:34:55 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[WPF 4]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=230</guid>
		<description><![CDATA[The other weekend I decided to update an application with a DataGrid and turn off some columns when they weren&#8217;t needed. It seemed to me that to bind a property to the DataColumn visibility attribute would be the most appropriate solution so I merrily tried out the following in XAML. &#60;DataGridColumn Binding="{Binding Name}" Visibility="{Binding NameVisibility}" [...]]]></description>
			<content:encoded><![CDATA[<p>The other weekend I decided to update an application with a DataGrid and turn off some columns when they weren&#8217;t needed.</p>
<p>It seemed to me that to bind a property to the DataColumn visibility attribute would be the most appropriate solution so I merrily tried out the following in XAML.</p>
<pre>&lt;DataGridColumn Binding="{Binding Name}" Visibility="{Binding NameVisibility}" /&gt;</pre>
<p>This doesn&#8217;t work. Perhaps not entirely surprising. We expect to find Name in each Item in the ItemsSource property for the DataGrid, but the column visibility should be bound something in the DataGrid DataContext property.</p>
<p>There are a couple of things needed which will make this work. First we need to register the DataGridColumn type with the DataContextProperty.  I added these to App.xaml.cs in the start up event handler.</p>
<pre>FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));

FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid),
    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits,
        new PropertyChangedCallback(OnDataContextChanged)));</pre>
<p>Also add the PropertyChangedCallback handler in App.xaml.cs.</p>
<pre>private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    DataGrid d = sender as DataGrid;
    if (d != null)
    {
        foreach (DataGridColumn c in d.Columns)
        {
            c.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
        }
    }
}</pre>
<p>Then modify the DateGridColumn binding.</p>
<pre>&lt;DataGridColumn Binding="{Binding Name}" 
    Visibility="{Binding Path=(FrameworkElement.DataContext).NameVisibility},
        RelativeSource={x:Static RelativeSource.Self}" /&gt;</pre>
<p>I found most of this in another blog that I&#8217;ve lost the link to, but the full detail wasn&#8217;t in the blog itself but was in the example code with it. If someone has seen something like this elsewhere let me know, I&#8217;d like to trackback to it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2011/09/24/binding-datagridcolumn-visibility-attribute/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using WPF DataGrid ScrollIntoView</title>
		<link>http://www.ancientgeek.co.uk/2010/09/23/using-wpf-datagrid-scrollintoview/</link>
		<comments>http://www.ancientgeek.co.uk/2010/09/23/using-wpf-datagrid-scrollintoview/#comments</comments>
		<pubDate>Thu, 23 Sep 2010 15:58:45 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[DataGrid]]></category>
		<category><![CDATA[scrollintoview]]></category>
		<category><![CDATA[WPF 4]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=224</guid>
		<description><![CDATA[This simple method allows you to move a row into the viewport when the DataGrid has scrollbars showing.  Rather irritatingly the viewport only scrolls enough to bring the row into view.  So if you call this after the DataGrid is loaded, the desired row is at the bottom of the viewport. There is a simple [...]]]></description>
			<content:encoded><![CDATA[<p>This simple method allows you to move a row into the viewport when the DataGrid has scrollbars showing.  Rather irritatingly the viewport only scrolls enough to bring the row into view.  So if you call this after the DataGrid is loaded, the desired row is at the bottom of the viewport.</p>
<p>There is a simple trick to get the row to appear at the top of the view though. Just call ScrollIntoView twice.  The first time pass the last row in the DataGrid and the second time pass in the desired row.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2010/09/23/using-wpf-datagrid-scrollintoview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WPF Printing &#8211; some issues resolved</title>
		<link>http://www.ancientgeek.co.uk/2010/08/30/wpf-printing-some-issues-resolved/</link>
		<comments>http://www.ancientgeek.co.uk/2010/08/30/wpf-printing-some-issues-resolved/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 06:28:36 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[Printing]]></category>
		<category><![CDATA[WPF 4]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=218</guid>
		<description><![CDATA[After my recent post I emailed the development team at Microsoft and some issues have been worked out. When printing a landscape document via the preview control you need to set a print ticket on the FixedDocument before displaying it in preview. FixedDocument x = new FixedDocument(); PrintTicket pt = new PrintTicket(); pt.PageOrientation = PageOrientation.Landscape; [...]]]></description>
			<content:encoded><![CDATA[<p>After my recent post I emailed the development team at Microsoft and some issues have been worked out.</p>
<p>When printing a landscape document via the preview control you need to set a print ticket on the FixedDocument before displaying it in preview.</p>
<pre>FixedDocument x = new FixedDocument();
PrintTicket pt = new PrintTicket();
pt.PageOrientation = PageOrientation.Landscape;
x.PrintTicket = pt;</pre>
<p>You can then set the Document property of the DocumentViewer and when you print from there it should print landscape.</p>
<p>I haven&#8217;t tested this in anger because I moved on and found a neater approach (and I didn&#8217;t really want a preview of what I was printing I simply wanted to avoid wasting paper and ink).</p>
<p>I&#8217;ve since set up a PDF print queue using RedMon (great wee utility) and GhostScript so I&#8217;ve been using that to produce PDFs which I can look at.</p>
<p>A much tidier approach to printing involves printing objects that derive from the Visual class (and all FrameworkElement objects in  WPF do). So I created a new Page (although you could also base a new class on UserControl) and called it EntrySheet, set up the content as I wish and then to print I do the following:</p>
<pre>PrintDialog pd = new PrintDialog();
pd.PrintTicket.PageOrientation = PageOrientation.Landscape;

Size ps = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);

EntrySheet p = new EntrySheet();
p.Width = ps.Width;
p.Height = ps.Height;

p.Measure(ps);
p.Arrange(new Rect(new Point(0, 0), ps));
p.UpdateLayout();

pd.PrintVisual(p, "Entry Sheet");</pre>
<p>Because the EntrySheet object is not being displayed prior to printing, you must call Measure and Arrange so that it&#8217;s content can be dimensioned and layed out. UpdateLayout isn&#8217;t always needed but I found that if your Visual includes a DataGrid then this step is essential.</p>
<p>The issue I haven&#8217;t been able to resolve is a DataGrid where the columns have been given star dimensions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2010/08/30/wpf-printing-some-issues-resolved/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trials and Tribulations with WPF Printing</title>
		<link>http://www.ancientgeek.co.uk/2010/08/02/trials-and-tribulations-with-wpf-printing/</link>
		<comments>http://www.ancientgeek.co.uk/2010/08/02/trials-and-tribulations-with-wpf-printing/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 09:24:27 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[DataGrid]]></category>
		<category><![CDATA[Printing]]></category>
		<category><![CDATA[WPF 4]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=207</guid>
		<description><![CDATA[I&#8217;m developing a program to do sailing race results for my club. After some deliberation I elected to use WPF 4 as it finally includes the DataGrid control which I&#8217;ve always thought was essential. I&#8217;ll blog about things I&#8217;ve done to make editing and entering results as easy as possible soon as that was an [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m developing a program to do sailing race results for my club. After some deliberation I elected to use WPF 4 as it finally includes the DataGrid control which I&#8217;ve always thought was essential. I&#8217;ll blog about things I&#8217;ve done to make editing and entering results as easy as possible soon as that was an interesting learning curve and what at first appeared to be quite limited is finally working well.</p>
<p>With regards to printing WPF provides some very interesting and very powerful features and overall I&#8217;m impressed at how easy it is to produce printed output, though there are a few oddities.</p>
<p>These mostly came to light as I started working on printing race entry sheets which are set out before the race for competitors to enter with a set of boxes for the Race Officer to enter lap finish times. Essentially what I wanted was a single page containing a grid with equal size columns laid out landscape.</p>
<p>First I set up a Page with a DataGrid and fixed columns giving each column a star width. I added 15 empty rows to the grid to get a table. Getting a Page into a FixedDocument (which I will also detail elsewhere), is a bit of a palaver but I&#8217;d already worked out how to do that and so I got that done and that for Landscape I needed to change the PageOrientation on FixedDocument&#8217;s DocumentPaginator.</p>
<p>First problem, did a preview using a DocumentViewer and things look good, but print and it comes out Portrait mode on the paper and half my grid is missing, and after much searching I found the following:</p>
<p><a href="http://stackoverflow.com/questions/1003585/setting-pageorientation-for-the-wpf-documentviewer-printdialog">http://stackoverflow.com/questions/1003585/setting-pageorientation-for-the-wpf-documentviewer-printdialog</a></p>
<p>I&#8217;m already using a custom template for a DocumentViewer to remove the Search box, and the template I&#8217;d got from the standard control doesn&#8217;t have a print button and so there is no way to intercept the print command that I could see.</p>
<p>Two issues with DocumentViewer in my opinion:</p>
<p>1. Need to be able to turn off the search facility<br />
2. Need simple way to specify print orientation or it should work it out for itself (I&#8217;m passing a FixedDocument after all which knows the orientation!).</p>
<p>So I looked at printing without previewing.</p>
<p>The next issue which caused much head scratching, the DataGrid columns weren&#8217;t sized equally when printed but instead were given a minimal size despite the grid stretching across the page.  I tried calling Measure and Arrange on the Page and on the DataGrid but neither helped. Eventually I discovered I had to call BeginInit and EndInit after Measure and Arrange to do the sizing of the columns.</p>
<p>The dynamic DataGrid column sizing didn&#8217;t happen because I wasn&#8217;t previewing, i.e. making the document visible.</p>
<p>What I evenually also realised was that I didn&#8217;t need the Page at all or the FixedDocument, I could create a UserControl and set it&#8217;s size to the page, Measure, Arrange, BeginInit and EndInit and then print directly as a Visual.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2010/08/02/trials-and-tribulations-with-wpf-printing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Poor man&#8217;s URL rewrite for IIS</title>
		<link>http://www.ancientgeek.co.uk/2010/03/19/poor-mans-url-rewrite-for-iis/</link>
		<comments>http://www.ancientgeek.co.uk/2010/03/19/poor-mans-url-rewrite-for-iis/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 21:19:37 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[IIS]]></category>
		<category><![CDATA[Classic ASP]]></category>
		<category><![CDATA[IIS 6]]></category>
		<category><![CDATA[URL rewrite]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=158</guid>
		<description><![CDATA[Mod_rewrite is a very handy module that is included with most Apache installations and allows you to achieve some rather nifty stuff with a few lines in the .htaccess file. IIS 6 doesn&#8217;t have a direct mechanism to compete with this but you can still achieve similar results using IIS&#8217;s error handling mechanism. Start off [...]]]></description>
			<content:encoded><![CDATA[<p>Mod_rewrite is a very handy module that is included with most Apache installations and allows you to achieve some rather nifty stuff with a few lines in the .htaccess file.</p>
<p>IIS 6 doesn&#8217;t have a direct mechanism to compete with this but you can still achieve similar results using IIS&#8217;s error handling mechanism.</p>
<p>Start off by adding an error handling URL, in IIS Manager open the web site&#8217;s properties and select the Custom Errors tab:</p>
<p><img class="aligncenter  size-full wp-image-162" title="iis-custom-errors" src="http://www.ancientgeek.co.uk/wp-content/uploads/2010/03/iis-custom-errors.png" alt="IIS Custom Errors" width="475" height="461" /></p>
<p>Scroll down and find the 404 HTTP error entry, and then click on the Edit button.</p>
<p><img class="aligncenter size-full wp-image-163" title="iis-custom-error-edit" src="http://www.ancientgeek.co.uk/wp-content/uploads/2010/03/iis-custom-error-edit.png" alt="IIS Custom Error Edit" width="392" height="230" /></p>
<p>Select URL from the message type drop down and enter your URL in the File: box, say &#8220;/404handler.asp&#8221;. NB the leading forward slash is required.</p>
<p>Click OK to save this and click OK in the properties dialog to apply the change to the website.</p>
<p>Now you need to create your 404 handler.</p>
<p>The first thing to note is that that in Classic ASP, Response.QueryString will hold a value which looks like the following:</p>
<p>404;/url-that-doesnt-match-a-file?x=2</p>
<p>Which means you wont be able to use Response.QueryString(&#8220;x&#8221;) to read the value 2, so you may want to refrain from using query strings, which is normally one of the reasons you are looking at implementing a URL rewrite scheme.</p>
<p>So at the start of the handler the first thing you will need to do is look at Response.QueryString and check that the first four characters are &#8220;404;&#8221;</p>
<p>If that&#8217;s the case then use the remainder of the string as the URL to be rewritten.</p>
<p>How you do this is really up to you, a simple scheme I&#8217;ve used is a look up table in the database to find the name of a script and then use System.Transfer to switch control to it. Remember that no variables declared and assigned in the first script are available in the script called by System.Transfer, but the Request object is still valid so that isn&#8217;t really a problem.</p>
<p>You can also use the same table to issue redirect to your SEO friendly URL if someone accesses it directly.</p>
<p>Related material:</p>
<ul>
<li><a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/80cb8d8d-8fd8-4af5-bb3b-4d11fff3ab9c.mspx?mfr=true">Configuring Custom Error Messages (IIS 6.0)</a></li>
<li><a href="http://blogs.msdn.com/rakkimk/archive/2006/09/01/735684.aspx">403.18: “The Specific Request Cannot Be Executed from Current Application Pool.”</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2010/03/19/poor-mans-url-rewrite-for-iis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mask default home page in IIS</title>
		<link>http://www.ancientgeek.co.uk/2010/03/06/mask-default-home-page-in-iis/</link>
		<comments>http://www.ancientgeek.co.uk/2010/03/06/mask-default-home-page-in-iis/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 12:14:43 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[IIS]]></category>
		<category><![CDATA[Classic ASP]]></category>
		<category><![CDATA[IIS 6]]></category>
		<category><![CDATA[IIS 7]]></category>
		<category><![CDATA[URL rewrite]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=122</guid>
		<description><![CDATA[Recently a SEO consultant noted that on a site I was working on the home page was listed on two urls: http://www.example.com/ http://www.example.com/default.asp He suggested that any attempt to visit /default.asp directly should 301 redirect to /. The obvious approach seemed to be to use Request.ServerVariables(&#8220;url&#8221;) to see what had been requested, and here I [...]]]></description>
			<content:encoded><![CDATA[<p>Recently a SEO consultant noted that on a site I was working on the home page was listed on two urls:</p>
<p>http://www.example.com/<br />

http://www.example.com/default.asp</p>

<p>He suggested that any attempt to visit /default.asp directly should 301 redirect to /.</p>
<p>The obvious approach seemed to be to use Request.ServerVariables(&#8220;url&#8221;) to see what had been requested, and here I found a problem in IIS 6 (but not in IIS 7). IIS 6 rewrites the URL &#8220;/&#8221; to &#8220;/default.asp&#8221; so there was no way to tell which the user had requested and any attempt to redirect based on the server variable would cause a 301 infinite loop.</p>
<p>My solution was to change the default document setting in IIS to a document that did not exist and then register a 403;14 error handler.</p>
<p>Now when the user requests &#8220;/&#8221; IIS 6 cannot find the default document and instead tries to list the contents of the root directory. Make sure that Directory Browsing is disabled. This will cause a 403;14 error and our default.asp page will be called.</p>
<p>At the top of the default.asp page I add the following code:</p>
<pre>dim arrqs

'
' If we are being called as an error handler then querystring will look like:
'
' 403;http://www.example.com:80/
'
if instr(request.querystring, ";") &gt; 0 then
  '
  ' If there is a semi-colon, split the string and check that the first
  ' substring is 403. If not you need to think about what you would like
  ' to do, out of laziness here I just put a 301 redirect to "/".
  '
  arrqs = split(request.querystring,";")
  if arrqs(0) &lt;&gt; "403" then
    response.status="301 Moved Permanently"
    response.addheader "Location","/"
    response.end
  end if
end if

'
' Next if query string is empty I'm redirecting to "/" because that
' means someone is trying something other than "/".
'
if request.querystring = "" then
  response.status="301 Moved Permanently"
  response.addheader "Location","/"
  response.end
end if
</pre>
<p>Fairly simply though not elegant.</p>
<p>IIS 7 doesn&#8217;t rewrite the URL server variable so it&#8217;s simpler. No need to have the default document set to a non existant page, and the start of default.asp is:</p>
<pre>if Request.ServerVariables("URL") = "/default.asp" then
  response.status="301 Moved Permanently"
  response.addheader "Location","/"
  response.end
end if
</pre>
<p>Related posts:</p>
<ul>
<li><a href="http://www.mcanerin.com/EN/articles/301-redirect-IIS.asp">IIS 301 Redirect for SEO</a></li>
<li><a href="http://www.somacon.com/p145.php">Permanent Redirect with HTTP 301</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2010/03/06/mask-default-home-page-in-iis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery datepicker widget with drop downs</title>
		<link>http://www.ancientgeek.co.uk/2009/05/21/jquery-datepicker-widget-with-drop-downs/</link>
		<comments>http://www.ancientgeek.co.uk/2009/05/21/jquery-datepicker-widget-with-drop-downs/#comments</comments>
		<pubDate>Thu, 21 May 2009 20:36:02 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[datepicker]]></category>
		<category><![CDATA[jqueryui]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=22</guid>
		<description><![CDATA[A simple approach to a date selector drop downs working with jQuery&#8217;s datepicker. This uses three selects to get the month, day and year. Example The first step is the html. &#60;div&#62;&#60;input id="a" style="position: absolute; z-index: -1;" type="text" /&#62; &#60;select id="a_month"&#62; &#60;option value=""&#62;Month&#60;/option&#62; &#60;option value="1"&#62;Jan&#60;/option&#62; ... &#60;/select&#62; &#60;select id="a_day"&#62; &#60;option value=""&#62;Day&#60;/option&#62; &#60;option value="1"&#62;1&#60;/option&#62; ... &#60;/select&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>A simple approach to a date selector drop downs working with jQuery&#8217;s datepicker. This uses three selects to get the month, day and year.</p>
<p><a title="Example" href="/datepicker-example.html" target="_blank">Example</a></p>
<p>The first step is the html.</p>
<pre>&lt;div&gt;&lt;input id="a"
  style="position: absolute; z-index: -1;"
  type="text" /&gt;
&lt;select id="a_month"&gt;
&lt;option value=""&gt;Month&lt;/option&gt;
&lt;option value="1"&gt;Jan&lt;/option&gt;
...
&lt;/select&gt;
&lt;select id="a_day"&gt;
&lt;option value=""&gt;Day&lt;/option&gt;
&lt;option value="1"&gt;1&lt;/option&gt;
...
&lt;/select&gt;
&lt;select id="a_year"&gt;
&lt;option value=""&gt;Year&lt;/option&gt;
&lt;/select&gt;
&lt;a href="javascript:showDatepicker('a')"&gt;
  &lt;img img="calendar.png"&gt;
&lt;/a&gt;
&lt;/div&gt;
</pre>
<p>I&#8217;ve left the year drop down with no years in it since I&#8217;ll auto populate it using javascript when the page is loaded.</p>
<p>Note the div tag around everything and that I&#8217;ve put a text input first which wont be seen (it&#8217;s z-index hides it under the current layer). The position style means that the selects will lie on top of it.</p>
<p>Also the id of the text input is the same as the beginning of each select. This allows me to have multiple select groups and use the same javascript functions for display and callback.</p>
<p>The date picker is intended to be attached to an input or a div. If it&#8217;s attached to a div then it will replace the div with a date selector which would not be ideal here.</p>
<p>So we are going to attach our datepicker to the hidden input. In this case the datepicker will be overlayed on the page and should line up with the bottom of the input (which should be where the bottom of the selects are).</p>
<p>First use the ready event on the document to set the drop downs to todays date, and populate the year with last year through to next year.</p>
<pre>$(document).ready(function() {
  //
  // Get today's date
  //
  var d = new Date();

  //
  // Set month drop down to this month (NB getMonth is 0 based so
  // we need to add one to the return value)
  //
  $('#a_month').val(d.getMonth()+1);

  //
  // Set day drop down to today's date.
  //
  $('#a_day').val(d.getDate());

  //
  // Get the year drop down and populate it with
  // last year, this year and next year
  // so we have some choices.
  //
  var y = $('#a_year').get(0);
  for (i = d.getFullYear()-1; i &lt; d.getFullYear()+2; i++)
    y.options[y.options.length] = new Option(i, i);

  //
  // set selected year
  //
  $('#a_year').val(d.getFullYear())

  //
  // next initialise the datepicker, setting up min and max dates that
  // correspond to the date range we can select using the drop downs.
  //
  var minDate = new Date(y.options[1].value, 0, 1);
  var maxDate = new Date(y.options[y.options.length-1].value, 11, 31);
  $('#a').datepicker({dateFormat: 'd/m/yy',
      minDate: minDate,
      maxDate: maxDate,
      onSelect: setDate});
});</pre>
<p>Next the function which will display the datepicker</p>
<pre>function showDatepicker(id)
{
  //
  // Set the text input to the selected date in the drop downs
  // in the format we set for the datepicker.
  //
  $('#' + id).val($('#' + id + '_day').val() + '/' +
    $('#' + id + '_month').val() + '/' +
    $('#' + id + '_year').val());

  //
  // Display the date picker!
  //
  $('#' + id).datepicker('show');
}
</pre>
<p>And finally the callback</p>
<pre>function setDate(text, control)
{
  //
  // Text is the value selected by the user in the form d/m/yyyy
  // Control is the html input element, so we can use
  //the id value to select the drop downs.
  //
  var dt = text.split('/');
  $('#' + control.id + '_day').val(dt[0]);
  $('#' + control.id + '_month').val(dt[1]);
  $('#' + control.id + '_year').val(dt[2]);
}
</pre>
<p>And that&#8217;s it. If you wanted to remove the limits on years you can not set the maxDate and minDate options. You would need to add options to the year select in the callback setDate to display the user&#8217;s selection.</p>
<p>Related posts:</p>
<ul>
<li><a rel="nofollow" href="http://jqueryui.com/demos/datepicker/">jQuery UI &#8211; Datepicker Demos &amp; Documentation</a></li>
<li><a rel="nofollow" href="http://www.filamentgroup.com/lab/date_range_picker_using_jquery_ui_16_and_jquery_ui_css_framework/">Neat extension to Datepicker</a></li>
<li><a rel="nofollow" href="http://www.west-wind.com/weblog/posts/891992.aspx">jQuery UI Datepicker and z-Index</a></li>
</ul>
<p><span id="more-22"></span><!--more--></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2009/05/21/jquery-datepicker-widget-with-drop-downs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Classic ASP TextStream and unicode</title>
		<link>http://www.ancientgeek.co.uk/2009/04/16/classic-asp-textstream-and-unicode/</link>
		<comments>http://www.ancientgeek.co.uk/2009/04/16/classic-asp-textstream-and-unicode/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 18:30:27 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[Classic ASP]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=14</guid>
		<description><![CDATA[I had the following error from a piece of code which had been working: Microsoft VBScript runtime error '800a0005' Invalid procedure call or argument A snippet of what was throwing this: set os = fs.createtextfile(fn, true) os.write textmsg os.close The error was on the os.write call. The error I eventually realised was caused by form [...]]]></description>
			<content:encoded><![CDATA[<p>I had the following error from a piece of code which had been working:</p>
<pre>Microsoft VBScript runtime error '800a0005'
Invalid procedure call or argument</pre>
<p>A snippet of what was throwing this:</p>
<pre>set os = fs.createtextfile(fn, true)
os.write textmsg
os.close</pre>
<p>The error was on the os.write call. The error I eventually realised was caused by form input, the value that had been output to the browser contained &amp;#8206; i.e.:</p>
<pre>&lt;input type="text" name="val" value="&amp;#8206;"&gt;</pre>
<p>Which on submission was encoded as a char whose ascii value was 1. The TextStream  Write method is only intended to handle ascii out. Simple solution write a bit of code to strip all non printable characters from the input.</p>
<pre>  function NonPrintStrip(s)
    dim r, i
    for i = 1 to len(s)
      if asc(mid(s, i, 1)) &gt;= 32 and asc(mid(s, i, 1)) &lt; 128 then
        r = r &amp; mid(s, i, 1)
      end if
    next
    NonPrintStrip = r
  end function</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2009/04/16/classic-asp-textstream-and-unicode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In the beginning</title>
		<link>http://www.ancientgeek.co.uk/2009/02/24/in-the-beginning/</link>
		<comments>http://www.ancientgeek.co.uk/2009/02/24/in-the-beginning/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 20:43:38 +0000</pubDate>
		<dc:creator>David Woakes</dc:creator>
				<category><![CDATA[Internet (way back)]]></category>
		<category><![CDATA[archie]]></category>
		<category><![CDATA[winsock]]></category>

		<guid isPermaLink="false">http://www.ancientgeek.co.uk/?p=3</guid>
		<description><![CDATA[Brief description of how I got started in internet development.]]></description>
			<content:encoded><![CDATA[<p>My initial claim to internet fame is as the author of WsArchie and WsArch32, which were Archie clients.  What is an Archie client I hear you ask&#8230;</p>
<p>At the start of 1993 I started accessing the internet via Demon.  The Internet as we know it today did not exist, in particular the web hadn&#8217;t really started and when you did get connected to the internet the resources you had access to were:</p>
<ul>
<li>Anonymous FTP servers: These contained tons of free software you could download and use.  If you could find it.</li>
<li>Gopher servers: This was the one of the first search tools which for finding stuff on the internet which amalgamated results from other search engines.</li>
<li>Archie servers: These catalogued the anonymous ftp servers, so you could either telnet in run a query and get more responses that you could handle or you could use gopher or an archie client.</li>
<li>Email: You could send email to all your mates, except none of them had email addresses.</li>
</ul>
<p>And that was about it.  Initially much access was via command line clients unless you had access to a X terminal.  If you had a PC with Windows 3.1 you were almost certainly connecting to the internet using command line tools.</p>
<p>About this time Trumpet Winsock became available which was the first widely used TCP/IP layer for Windows 3.0.  It was a real revolution and suddenly meant there was a relatively user friendly method of connecting windows PCs to the internet via modems.</p>
<p>I had noticed that there was an X-Windows Archie client and thought it was a pretty cool idea so I decided to write one and WsArchie was born.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ancientgeek.co.uk/2009/02/24/in-the-beginning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

