<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Digital Colony</title>
	
	<link>http://digitalcolony.com</link>
	<description>Ideas in Web Development</description>
	<lastBuildDate>Thu, 26 Apr 2012 02:43:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/DigitalColony" /><feedburner:info uri="digitalcolony" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>DigitalColony</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Using Paint.NET To Create Art Inspired Photographs</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/BDrmFqtW7GE/</link>
		<comments>http://digitalcolony.com/2012/04/using-paint-net-to-create-art-inspired-photographs/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 02:42:12 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[paint.net]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=371</guid>
		<description><![CDATA[Back in 2007, I had some fun using PhotoShop CS to mashup my photos with classic artwork in the post Photo and Classical Artwork Mashup. Since then I have moved away from PhotoShop and over to the free image program &#8230; <a href="http://digitalcolony.com/2012/04/using-paint-net-to-create-art-inspired-photographs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Back in 2007, I had some fun using PhotoShop CS to mashup my photos with classic artwork in the post <a href="http://digitalcolony.com/2007/05/photo-and-classical-art-mashup/">Photo and Classical Artwork Mashup</a>. Since then I have moved away from PhotoShop and over to the free image program <a href="http://www.getpaint.net/">Paint.NET</a>. Today I discovered it is just as easy to perform this trick in Paint.NET provided you have the <a href="http://forums.getpaint.net/index.php?/topic/7291-pyrochild-plugins-2011-10-09/">Pyrochild Plugins</a>. I donated the requested $5 and immediately put the Color Match to work.</p>
<p><img class="alignnone size-full wp-image-376" title="locks-normal" src="http://digitalcolony.com/wp-content/uploads/2012/04/locks-normal.jpg" alt="" width="550" height="412" /></p>
<p><em><a href="http://en.wikipedia.org/wiki/Hiram_M._Chittenden_Locks">The Ballard Locks</a> are a block from where I live. </em></p>
<p><img class="alignnone size-full wp-image-372" title="color-match1" src="http://digitalcolony.com/wp-content/uploads/2012/04/color-match1.jpg" alt="" width="561" height="496" /></p>
<p><em>Select Adjustments &gt; Color Match&#8230;</em></p>
<p><img class="alignnone size-full wp-image-373" title="color-match2" src="http://digitalcolony.com/wp-content/uploads/2012/04/color-match2.jpg" alt="" width="530" height="477" /></p>
<p><em>For my first attempt, I loaded a Roy Lichtenstein. Yikes!</em></p>
<p><img class="alignnone size-full wp-image-374" title="color-match3" src="http://digitalcolony.com/wp-content/uploads/2012/04/color-match3.jpg" alt="" width="550" height="446" /></p>
<p><em>For attempt two, I used a painting by Thomas Kinkade. Much better!</em></p>
<p><img class="alignnone size-full wp-image-375" title="locks-kinkade" src="http://digitalcolony.com/wp-content/uploads/2012/04/locks-kinkade.jpg" alt="" width="550" height="412" /></p>
<p><em>The Ballard Locks mashed with Thomas Kinkade.</em></p>
<p>Thanks to Paint.NET and some cool third party plugins, I don&#8217;t miss PhotoShop at all.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/BDrmFqtW7GE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2012/04/using-paint-net-to-create-art-inspired-photographs/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2012/04/using-paint-net-to-create-art-inspired-photographs/</feedburner:origLink></item>
		<item>
		<title>Using SQL To Guess Bad URL Requests</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/jWc2cC4fUWE/</link>
		<comments>http://digitalcolony.com/2012/04/using-sql-to-guess-bad-url-requests/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 16:32:18 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[UDF]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=340</guid>
		<description><![CDATA[My coffee website INeedCoffee.com went live way back in April 1999. And although the search engines do a good job indexing the site, what I found when I studied the log files was that the site was receiving about 1,000 &#8230; <a href="http://digitalcolony.com/2012/04/using-sql-to-guess-bad-url-requests/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My coffee website <a href="http://www.ineedcoffee.com/">INeedCoffee.com</a> went live way back in April 1999. And although the search engines do a good job indexing the site, what I found when I studied the log files was that the site was receiving about 1,000 404 requests every week to invalid pages. The pages weren&#8217;t moved, the links to the site had errors. Often these links resided on websites and forums that weren&#8217;t being updated.</p>
<p>My goal was to connect the reader with the page they believed the link was taking them to. So instead of returning a simple 404 Page Not Found &#8220;Tough Luck&#8221; screen, I wanted to connect the reader to the resource they requested. When I looked at the requests, my human eyes could usually figure out what page they had incorrectly linked to. Many of the broken link requests fell into three patterns.</p>
<ol>
<li><strong>Truncated.</strong> Often the link had a missing trailing slash or a few letters.</li>
<li><strong>Extra <strong>Characters</strong>.</strong> The other common element was that the link was correct, but somehow extra letters got attached to the URL.</li>
<li><strong>Mistyped Characters.</strong> Sometimes when a URL is hand copied, a zero becomes an &#8220;O&#8221; or a one becomes an &#8220;l&#8221;.</li>
</ol>
<p>Here is an example of a valid link to INeedCoffee and 3 examples of how things could go wrong. <a href="http://www.ineedcoffee.com/07/aeropress/">http://www.ineedcoffee.com/07/aeropress/</a></p>
<ol>
<li><strong>Truncated: </strong><a href="http://www.ineedcoffee.com/07/aeropres" target="_blank">http://www.ineedcoffee.com/07/aeropres</a> (trailing &#8220;s&#8221; and slash is missing from request)</li>
<li><strong>Extra Characters: </strong><a href="http://www.ineedcoffee.com/07/aeropress/ target=" target="_blank">http://www.ineedcoffee.com/07/aeropress/ target=</a> (when the url href doesn&#8217;t get closed properly, the link sent includes the characters after the link until the quote is closed)</li>
<li><strong>Mistyped Characters: </strong><a href="http://www.ineedcoffee.com/07/aer0press/" target="_blank">http://www.ineedcoffee.com/07/aer0press/</a> (in this example, an &#8220;o&#8221; is typed as a zero)</li>
</ol>
<h3>One Stored Procedure and One User Defined Function</h3>
<p>The first thing I noticed was that it was rare for the garbage characters to appear between the base domain name (www.ineedcoffee.com) and the article URL (/07/aeropress/). My idea was to compile a full list of valid URLs on my site and then perform a character by character comparison. For every character that matches, I would score a point. The URL with the most points would likely be the correct URL.</p>
<h3>The Stored Procedure</h3>
<p>In the stored procedure, I create a temp table loaded with valid URLs. I don&#8217;t include the home page. For INeedCoffee this means a link to each article, each section and every contributor page.</p>
<pre class="brush: sql; title: ; notranslate">
IF OBJECT_ID('prcBadLinkSuggest') IS NOT NULL
DROP PROCEDURE prcBadLinkSuggest
GO
CREATE PROCEDURE prcBadLinkSuggest
    @errorURL VARCHAR(300)
AS
DECLARE @goodURL AS VARCHAR(200)
DECLARE @title AS VARCHAR(100)

SELECT TOP 1 G.url AS GoodURL, G.title
FROM (
SELECT url, title FROM Content
UNION
SELECT contributorURL AS URL, contributorName AS Title
FROM Contributors
UNION
SELECT sectionURL AS URL, sectionName AS Title
FROM Sections
) G
ORDER BY dbo.udfCompareURLs(G.url, @errorURL) DESC
</pre>
<h3>The User Defined Function</h3>
<p>In the stored procedure prcBadLinkSuggest, the UDF udfCompareURLs is being called in the ORDER BY clause. The errorURL and a valid URL are passed. The UDF returns a score based upon character matching. The valid URL with the highest score is returned from the stored procedure. Notice that the SELECT is returning just one row and the ORDER BY is sorting on the Score in descending order (high to low).</p>
<pre class="csharpcode"><span class="kwrd">IF</span> OBJECT_ID(<span class="str">'udfCompareURLs'</span>) <span class="kwrd">IS</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
    <span class="kwrd">DROP</span> <span class="kwrd">FUNCTION</span> udfCompareURLs
<span class="kwrd">GO</span>
<span class="kwrd">CREATE</span> <span class="kwrd">FUNCTION</span> udfCompareURLs(
    @goodURL    <span class="kwrd">VARCHAR</span>(200),
    @errorURL    <span class="kwrd">VARCHAR</span>(200)
    )
<span class="kwrd">RETURNS</span> <span class="kwrd">INT</span>
<span class="kwrd">AS</span>
<span class="kwrd">BEGIN</span>
    <span class="kwrd">DECLARE</span> @iCount <span class="kwrd">AS</span> <span class="kwrd">INT</span>
    <span class="kwrd">DECLARE</span> @score    <span class="kwrd">AS</span> <span class="kwrd">INT</span>
    <span class="kwrd">DECLARE</span> @eChar    <span class="kwrd">AS</span> <span class="kwrd">CHAR</span>
    <span class="kwrd">DECLARE</span> @gChar    <span class="kwrd">AS</span> <span class="kwrd">CHAR</span>
    <span class="kwrd">DECLARE</span> @urlLength    <span class="kwrd">AS</span> <span class="kwrd">INT</span>

    <span class="kwrd">SET</span> @iCount = 1
    <span class="kwrd">SET</span> @score = 0
    <span class="kwrd">SET</span> @urlLength = LEN(@errorURL)
    <span class="kwrd">WHILE</span> (@iCount &lt; @urlLength)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">SELECT</span> @eChar = <span class="kwrd">SUBSTRING</span>(@errorURL,@iCount,1)
        <span class="kwrd">SELECT</span> @gChar = <span class="kwrd">SUBSTRING</span>(@goodURL,@iCount,1)
        <span class="kwrd">IF</span> @eChar = @gChar
            <span class="kwrd">SET</span> @score = @score + 1
        <span class="kwrd">SET</span> @iCount = @iCount + 1
    <span class="kwrd">END</span>
    <span class="kwrd">RETURN</span> @Score
<span class="kwrd">END</span></pre>
<p>The User Defined Function takes the length of the ErrorURL and then constructs a loop where it does a character by character comparison building a score of matches.</p>
<h3>Last Words</h3>
<p>I tested this code using actual 404 data and it was extremely accurate in guessing the correct web page. It isn&#8217;t bullet-proof as it would return a low score if the garbage appears early in the URL string, but that case is extremely rare.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/jWc2cC4fUWE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2012/04/using-sql-to-guess-bad-url-requests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2012/04/using-sql-to-guess-bad-url-requests/</feedburner:origLink></item>
		<item>
		<title>Case Study: Failed WordPress Update Due to Database Issues</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/fXb7Sczq2wg/</link>
		<comments>http://digitalcolony.com/2012/03/case-study-failed-wordpress-update-due-to-database-issues/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 01:32:46 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=332</guid>
		<description><![CDATA[This post is about symptoms that broke my install of WordPress and how I was able to get everything fixed. This past Saturday I noticed some bizarre blog behavior. I was getting an email backup of this WordPress blog every &#8230; <a href="http://digitalcolony.com/2012/03/case-study-failed-wordpress-update-due-to-database-issues/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>This post is about symptoms that broke my install of WordPress and how I was able to get everything fixed.</em></p>
<p>This past Saturday I noticed some bizarre blog behavior. I was getting an email backup of this WordPress blog every minute for several days. Even after disabling the backup plugin, the email backups kept coming. So in a desperate attempt to do something, I upgraded to the latest version of WordPress.</p>
<h3>Database upgrade required</h3>
<p>After running the auto-install to the latest version, I got a screen telling saying &#8220;Database upgrade required&#8221;. When I pressed the button for that screen, I was told the Upgrade was complete. But it wasn&#8217;t. Clicking that button sent me back to the &#8220;Database upgrade required&#8221; screen. Endless loop.</p>
<p>Joe from <a href="http://artlung.com/blog/">ArtLung.com</a> tipped me off to the post <a href="http://www.clickonf5.org/2247/solution-database-upgrade-required/">Solution for WordPress WP-Options Issue – Database Upgrade Required</a>. Basically, the database version exists on both the install and as a field in the database and they need to be equal for things to run. The solution is to update the database field so they are equal.</p>
<h3>UPDATE Fails on WordPress Database</h3>
<p>Using <a href="http://www.heidisql.com/">HeidiSQL</a> I executed an UPDATE command to fix everything.</p>
<blockquote><p>UPDATE WP_Options SET option_value = &#8217;19470&#8242; WHERE option_name = &#8216;db_version&#8217;</p></blockquote>
<p>No luck.</p>
<blockquote><p>/* SQL Error (1142): UPDATE command denied to user &#8216;xxx&#8217; for table &#8216;wp_options&#8217; */</p></blockquote>
<p>Now I was stumped, so I reached out to my host. They informed me my database was full.</p>
<h3>Database Full</h3>
<p>Turns out my WordPress database had filled up. It went from a few MBs to 50 MBs. How did that happen on less than 100 blog posts? Seems my <a href="http://urbangiraffe.com/plugins/redirection/">Redirection plugin</a> had created a log file of over 54,000 rows.  I attempted to delete the log file from the settings page, but it failed, so I did it from HeidiSQL. That dropped the database back down to under 3 MB. To prevent this from happening again, I found a setting for the plugin that truncates that log entries. I set it to 30 days.</p>
<h3>All Is Well</h3>
<p>Once the database had free space, UPDATE commands worked and the WordPress install went successfully. The endless backup problem was solved as well, once that plugin was able to update the database.</p>
<p>Hopefully, this post helps at least one other blogger.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/fXb7Sczq2wg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2012/03/case-study-failed-wordpress-update-due-to-database-issues/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2012/03/case-study-failed-wordpress-update-due-to-database-issues/</feedburner:origLink></item>
		<item>
		<title>Writing Your Own Search Engine Using SQL Server</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/89kmar_cDaA/</link>
		<comments>http://digitalcolony.com/2011/12/writing-your-own-search-engine-using-sql-server/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 01:07:08 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[UDF]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=311</guid>
		<description><![CDATA[My coffee site INeedCoffee needed a better search engine. I had thrown some basic SQL together when the site was launched back in 1999. It did an OK job when the site didn&#8217;t have much content. Over the years, the &#8230; <a href="http://digitalcolony.com/2011/12/writing-your-own-search-engine-using-sql-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My coffee site <a href="http://www.ineedcoffee.com">INeedCoffee</a> needed a better search engine. I had thrown some basic SQL together when the site was launched back in 1999. It did an OK job when the site didn&#8217;t have much content. Over the years, the quality of the search results got worse and worse. So I did what any coder would do, I looked for a free solution.</p>
<p>Google did better job searching my site than my own code, so I looked at their <em>Google Custom Search</em> solution. I didn&#8217;t like their free ad version and I didn&#8217;t what to pay them $100 each and every year for the non-ad version. I decided that not only could I write my own search engine that was just as fast, but I could also deliver better results to the users. After all, I knew my content better than anyone else.</p>
<h3>Assigning a Quality Score</h3>
<p>The first thing I noticed about Google&#8217;s search results is that the best article on a given topic often wasn&#8217;t listed first. It had no way to know quality, but I did. So I added a quality score of 1 to 5 for every article. The default was 3. The best content was rated a 4 or 5. Articles that needed better photos or improved in some way, were given a 1 or 2. Later I&#8217;d also use this quality score when assigning weight on the sitemap.</p>
<h3>Web Form -&gt; Server Side Code -&gt; Stored Procedure</h3>
<p>The HTML search form is pretty basic. A single text box and a submit button. What server side code you use to call the stored procedure is irrelevant. ASP.NET, Classic ASP, PHP &#8211; it is all good. The server side code will call the search stored procedure.</p>
<h3>Two Temp Tables</h3>
<p>The search stored procedure will have two temp tables: #searchWords and #searchResults. The purpose of #searchWords is to chop up any search phrase into individual words and then record their position. Later that position will be used to order search results, which more weight being placed on the first and second word in a search query. The #searchResults table are the results being returned to the web page.</p>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #searchWords (
    word      <span class="kwrd">VARCHAR</span>(100),
    <span class="kwrd">position</span>    <span class="kwrd">INT</span>
)
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #searchResults (
    url        <span class="kwrd">VARCHAR</span>(100),
    title      <span class="kwrd">VARCHAR</span>(100),
    longDesc   <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>),
    quality    TINYINT,
    score      <span class="kwrd">INT</span>
)</pre>
<h3>Splitting Search Phrases</h3>
<p>For this functionality, I found some code on <em>StackOverflow</em> that did the job. The <a href="http://stackoverflow.com/a/2681">SplitWordList user-defined function</a> by Terrapin works perfectly. If the user places the search term inside quotes, I do not call the SplitWordFunction and inside enter the entire phrase as one row in the #searchWords table.</p>
<pre class="csharpcode"><span class="kwrd">INSERT</span> <span class="kwrd">INTO</span> #searchWords <span class="kwrd">SELECT</span> word, <span class="kwrd">position</span> <span class="kwrd">from</span> SplitWordList(@searchString)</pre>
<h3>Count String Function</h3>
<p>For the actual search, I used the <a href="http://www.sql-server-helper.com/functions/count-string.aspx">Count String Occurrence Function</a>. The search words are compared first against the article title and then the content itself.</p>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">FUNCTION</span> [dbo].[udfCountString](
    @InputString    <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>),
    @SearchString    <span class="kwrd">VARCHAR</span>(100)
)
<span class="kwrd">RETURNS</span> <span class="kwrd">INT</span>
<span class="kwrd">BEGIN</span>
    <span class="kwrd">RETURN</span> (LEN(@InputString) -
            LEN(REPLACE(@InputString, @SearchString, <span class="str">''</span>))) /
            LEN(@SearchString)
END</pre>
<h3>I Like Cursors</h3>
<p>The most straight forward approach I could think of for getting search results was to use two cursors. One with the content and one with the search words. Then write the hits to the #searchResults temp table. But cursors are often frowned upon for poor performance. I decided I would first code the search engine using Cursors and then if I ran into a performance problem, I&#8217;d come up with an alternate solution. But I didn&#8217;t need to, as I got rocking fast results using CURSORS.</p>
<pre class="csharpcode"><span class="kwrd">DECLARE</span> ContentCursor <span class="kwrd">CURSOR</span> FAST_FORWARD <span class="kwrd">FOR</span>
<span class="kwrd">SELECT</span> url, title, longDesc, quality, page
<span class="kwrd">FROM</span> Articles 

<span class="kwrd">DECLARE</span> SearchWordCursor <span class="kwrd">CURSOR</span> <span class="kwrd">DYNAMIC</span> <span class="kwrd">FOR</span>
<span class="kwrd">SELECT</span> word, <span class="kwrd">position</span> <span class="kwrd">FROM</span> #searchWords
<span class="kwrd">OPEN</span> SearchWordCursor 

<span class="kwrd">OPEN</span> ContentCursor
<span class="kwrd">FETCH</span> <span class="kwrd">NEXT</span> <span class="kwrd">FROM</span> ContentCursor <span class="kwrd">INTO</span> @url, @title, @longDesc, @quality, @page

<span class="kwrd">WHILE</span> <span class="preproc">@@FETCH_STATUS</span> = 0
<span class="kwrd">BEGIN</span>
    <span class="kwrd">FETCH</span> <span class="kwrd">FIRST</span> <span class="kwrd">FROM</span> SearchWordCursor <span class="kwrd">INTO</span> @word, @<span class="kwrd">position</span>
    <span class="kwrd">WHILE</span> <span class="preproc">@@FETCH_STATUS</span> = 0
    <span class="kwrd">BEGIN</span>
        <span class="rem">-- place more weight on the first search term</span>
        <span class="kwrd">SELECT</span> @score = <span class="kwrd">CASE</span> @<span class="kwrd">position</span>
            <span class="kwrd">WHEN</span> 1 <span class="kwrd">THEN</span> 3
            <span class="kwrd">WHEN</span> 2 <span class="kwrd">THEN</span> 2
            <span class="kwrd">ELSE</span> 1
        <span class="kwrd">END</span>
        <span class="rem">-- search the TITLE </span>
        <span class="kwrd">SET</span> @<span class="kwrd">count</span> = dbo.udfCountString(@title, @word)
        <span class="kwrd">IF</span> @<span class="kwrd">count</span> &gt; 0
        <span class="kwrd">BEGIN</span>
            <span class="kwrd">INSERT</span> <span class="kwrd">INTO</span> #searchResults <span class="kwrd">VALUES</span> (@url, @title, @longDesc, @quality, @score * 10)
        <span class="kwrd">END</span>
        <span class="rem">-- search the PAGE</span>
        <span class="kwrd">SET</span> @<span class="kwrd">count</span> = dbo.udfCountString(@page, @word)
        <span class="kwrd">IF</span> @<span class="kwrd">count</span> &gt; 0
        <span class="kwrd">BEGIN</span>
            <span class="kwrd">INSERT</span> <span class="kwrd">INTO</span> #searchResults <span class="kwrd">VALUES</span> (@url, @title, @longDesc, @quality, @score)
        <span class="kwrd">END</span>                    

        <span class="kwrd">FETCH</span> <span class="kwrd">NEXT</span> <span class="kwrd">FROM</span> SearchWordCursor <span class="kwrd">INTO</span> @word, @<span class="kwrd">position</span>
    <span class="kwrd">END</span>
    <span class="kwrd">FETCH</span> <span class="kwrd">NEXT</span> <span class="kwrd">FROM</span> ContentCursor <span class="kwrd">INTO</span> @url, @title, @longDesc, @quality, @page
<span class="kwrd">END</span>

<span class="kwrd">CLOSE</span> ContentCursor
<span class="kwrd">DEALLOCATE</span> ContentCursor

<span class="kwrd">CLOSE</span> SearchWordCursor
<span class="kwrd">DEALLOCATE</span> SearchWordCursor</pre>
<h3>Working With the Results</h3>
<p>Before dropping both temp tables, here is the query used to return the search results. If you look at the SQL above you will see that it is possible (likely) that a search hit will take place on both the title and the page content. I ran some tests and determined that a search hit against a word in the title was 10 times more important than the content, so I multiply the score time ten if there is a title match.</p>
<p>To flatten the results, I use a GROUP BY clause in the SQL. Then the results are returned order from highest to lowest scores.</p>
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> 20 S.url, S.title, S.longDesc, S.quality, <span class="kwrd">SUM</span>(S.score) <span class="kwrd">AS</span> Score
<span class="kwrd">FROM</span> #searchResults S
<span class="kwrd">GROUP</span> <span class="kwrd">BY</span> S.url, S.title, S.longDesc, S.quality
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> <span class="kwrd">SUM</span>(S.score) <span class="kwrd">DESC</span>, S.Quality DESC</pre>
<h3>Better Than Google?</h3>
<p>I ran numerous tests comparing my search engine to Google. My hand-coded <a href="http://www.ineedcoffee.com/search/">INeedCoffee search engine</a> delivered better results at equal or faster speeds. And the best part is I don&#8217;t need to send Google a check for $100 every year.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/89kmar_cDaA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2011/12/writing-your-own-search-engine-using-sql-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2011/12/writing-your-own-search-engine-using-sql-server/</feedburner:origLink></item>
		<item>
		<title>Using a Classic ASP Dictionary Object To Handle Broken Links</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/ZYze43BZM-w/</link>
		<comments>http://digitalcolony.com/2011/05/using-a-classic-asp-dictionary-object-to-handle-broken-links/#comments</comments>
		<pubDate>Thu, 05 May 2011 18:36:11 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[Classic ASP]]></category>
		<category><![CDATA[dictionary]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=297</guid>
		<description><![CDATA[My site INeedCoffee was first built way back in 1999 using Classic ASP.  Back then it was just called ASP or Active Server Pages.  It works well and doesn&#8217;t require moving to ASP.NET, so I never updated the code base.  &#8230; <a href="http://digitalcolony.com/2011/05/using-a-classic-asp-dictionary-object-to-handle-broken-links/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My site <a href="http://www.ineedcoffee.com">INeedCoffee</a> was first built way back in 1999 using Classic ASP.  Back then it was just called ASP or Active Server Pages.  It works well and doesn&#8217;t require moving to ASP.NET, so I never updated the code base.  <em>If it isn&#8217;t broke, don&#8217;t fix it.</em></p>
<p>There was one thing I wanted to address better recently and that was how I handled incoming broken links.  I used to just redirect every request to the home page, but I&#8217;ve since learned that <a href="http://googlewebmastercentral.blogspot.com/2011/05/do-404s-hurt-my-site.html">404 error codes are OK</a> to have.  If the page is missing, returning a 404 code is appropriate.</p>
<p>When I studied the bad incoming links, I isolated about 15 where I could tell what article was intended in the link.  For these links, I wanted to give a 404 error and provide a suggestion on what page is most likely the correct link.  For this I used the Scripting.Dictionary object.  In it, I matched the bad link with the good link.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">RequestedBadLink = Request.ServerVariables(<span class="str">"QUERY_STRING"</span>)

<span class="rem">'- Dictionary of known bad URL requests</span>
<span class="kwrd">Set</span> BadLinks = Server.CreateObject(<span class="str">"Scripting.Dictionary"</span>)
BadLinks.Add <span class="str">"404;http://example.com:80/bad-link"</span>,<span class="str">"http://example.com/good-link"</span>
<span class="kwrd">'- add more links here
If</span> BadLinks.Exists(RequestedBadLink) <span class="kwrd">Then</span>
    SuggestedURL = BadLinks.Item(RequestedBadLink)
<span class="kwrd">Else</span>
    SuggestedURL = <span class="str">""</span>
<span class="kwrd">End</span> If</pre>
<p>For the bad links, I added &#8220;404;&#8221; to the front of the link and embedded &#8220;:80&#8243; after the domain.  This is the format that the QUERY_STRING ServerVariables uses.  Then on your 404 page, you can test to see if you found a Suggested URL and display it for the user.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/ZYze43BZM-w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2011/05/using-a-classic-asp-dictionary-object-to-handle-broken-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2011/05/using-a-classic-asp-dictionary-object-to-handle-broken-links/</feedburner:origLink></item>
		<item>
		<title>My Secret For Picking Excellent Web Hosts</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/DSVdNVzx4V8/</link>
		<comments>http://digitalcolony.com/2011/02/my-secret-for-picking-excellent-web-hosts/#comments</comments>
		<pubDate>Thu, 10 Feb 2011 19:25:45 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[web hosting]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=285</guid>
		<description><![CDATA[I have paid for web hosting since 1995.  When it comes to service, I&#8217;ve done pretty good.  I follow a three step process when searching for web hosting. Web Research &#8211; Everyone does this.  Find a host that meets all &#8230; <a href="http://digitalcolony.com/2011/02/my-secret-for-picking-excellent-web-hosts/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have paid for web hosting since 1995.  When it comes to service, I&#8217;ve done pretty good.  I follow a three step process when searching for web hosting.</p>
<ol>
<li><strong>Web Research</strong> &#8211; Everyone does this.  Find a host that meets all your requirements at the price point you are willing to pay.</li>
<li><strong>Sunday or Late Night Email</strong> &#8211; Let us say that you have 2 or 3 possible web hosts in mind.  Wait until Sunday and then fire off an email to their support staff asking a question.  The question shouldn&#8217;t be too difficult as to require lots of research, but not easy enough to be answered by a sales person.</li>
<li><strong>Wait For Responses</strong> &#8211; The winner of your business will be the web host that quickly and professionally responds to your off hour email question.</li>
</ol>
<p>When I pay for web hosting I want to know that they have competent people working during non-business hours.  Some of these discount web hosts are able to offer rock bottom prices, because they have bare bones technical support.  They staff their rock stars during business hours, because that is when they are most likely to land a new customer.  <strong>Sending an email on Sunday, or late in the night, is perfect way to test a web host before handing over your credit card data.</strong></p>
<p>After you have established a relationship with a web host, periodically send an off hour email.  Maybe once or twice a year.  Keep them on their toes.  Consider this test to be part of your website back up strategy.</p>
<p>This site uses <a href="http://www.winhost.com/a/digitalc_b_7">WinHost</a>, which I highly recommend for ASP.NET and SQL Server web hosting.  They passed the Sunday email test.</p>
<p><a href="http://www.winhost.com/a/digitalc_b_7"><img title="WinHost ASP.NET Web Hosting" src="http://www.winhost.com/c/b_25" alt="WinHost ASP.NET Web Hosting" width="300" height="250" /></a></p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/DSVdNVzx4V8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2011/02/my-secret-for-picking-excellent-web-hosts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2011/02/my-secret-for-picking-excellent-web-hosts/</feedburner:origLink></item>
		<item>
		<title>Using Instapaper for Web Legibility</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/lLOBOFENdkI/</link>
		<comments>http://digitalcolony.com/2010/12/using-instapaper-for-web-legibility/#comments</comments>
		<pubDate>Sun, 26 Dec 2010 22:07:01 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[instapaper]]></category>
		<category><![CDATA[typography]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=269</guid>
		<description><![CDATA[When I first looked over the Instapaper application I didn&#8217;t think I needed it.  I used Delicious for my social bookmarketing site.  Why would I need Instapaper?  Then news stories came out saying that Yahoo! would either shutdown or sell &#8230; <a href="http://digitalcolony.com/2010/12/using-instapaper-for-web-legibility/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When I first looked over the Instapaper application I didn&#8217;t think I needed it.  I used Delicious for my social bookmarketing site.  Why would I need Instapaper?  Then news stories came out saying that Yahoo! would either shutdown or sell Delicious, so I gave Instapaper another look.</p>
<p>How did I miss the primary reason for using Instapaper?  It&#8217;s primary feature is not bookmarking, it is <strong>making text legible</strong>.  There was this trend in web design around 2003 where font sizes got really small.  I&#8217;m afraid it may be coming back and my eyes just can&#8217;t take it.  Thankfully with Instapaper, I no longer have to suffer through reading painfully small fonts or <span style="color: #999999;">gray text</span> on a while background.</p>
<p>Here is how it works.</p>
<ol>
<li>Set up an account on <a href="http://www.instapaper.com">Instapaper</a>.</li>
<li>Add the <strong>Read Later</strong> bookmarklet to your browser, per their instructions.</li>
<li>Go to a page you wish to read that has a hideous web design with dreadful legibility.  For this example, I am going to use the outstanding article <a href="http://www.westonaprice.org/blogs/vitamin-d-problems-with-the-latitude-hypothesis.html">Vitamin D &#8212; Problems With the Latitude Hypothesis</a> on the Weston A Price website.</li>
<li>Press your Read Later bookmarklet.</li>
<li>Go back to Instapaper, locate the article on your list and click the Text button.</li>
</ol>
<p><img class="alignnone size-full wp-image-270" title="awful " src="http://digitalcolony.com/wp-content/uploads/2010/12/instapaper-before.png" alt="" width="550" height="444" /></p>
<p><em>Painful typography</em></p>
<p><img class="alignnone size-full wp-image-271" title="instapaper" src="http://digitalcolony.com/wp-content/uploads/2010/12/instapaper.png" alt="" width="554" height="147" /></p>
<p><em>Add it to Instapaper and then click the Text button.</em></p>
<p><img class="alignnone size-full wp-image-272" title="instapaper-after" src="http://digitalcolony.com/wp-content/uploads/2010/12/instapaper-after.png" alt="" width="549" height="359" /></p>
<p><em>Presto.  The article is now readable. </em></p>
<p>Instapaper doesn&#8217;t work for every website, but works for most.  My online reading speed and comprehension has never been greater.  I highly recommend Instapaper.</p>
<p>UPDATE: Seems Instapaper has a feature in their Extras section called <a href="http://www.instapaper.com/extras">Instapaper Text</a>.  Drag that bookmarklet to your toolbar and click it whenever you need text cleaned up.  No account needed.  Use this if you don&#8217;t need the bookmarking features.   They also give a shout out to a similar solution called <a href="http://lab.arc90.com/experiments/readability/">Readability</a>.</p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/lLOBOFENdkI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2010/12/using-instapaper-for-web-legibility/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2010/12/using-instapaper-for-web-legibility/</feedburner:origLink></item>
		<item>
		<title>DreamHost and the Myth of Unlimited Domains</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/aXPLZiGUVHs/</link>
		<comments>http://digitalcolony.com/2010/11/dreamhost-and-the-myth-of-unlimited-domains/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 20:30:57 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[dreamhost]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[web hosting]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=253</guid>
		<description><![CDATA[DreamHost promotes unlimited domain web hosting for $8.95/month.  It seemed like a sweet deal, so I signed up for it.  The reality is that their offer is misleading.  DreamHost offers 100 MB of memory per account.  If you exceed this &#8230; <a href="http://digitalcolony.com/2010/11/dreamhost-and-the-myth-of-unlimited-domains/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>DreamHost promotes <em>unlimited </em>domain web hosting for $8.95/month.  It seemed like a sweet deal, so I signed up for it.  The reality is that their offer is misleading.  DreamHost offers 100 MB of memory per account.  If you exceed this number &#8211; even for a second &#8211; they unleash a procwatch to kill the process.</p>
<p>At this point you can reach out to DreamHost&#8217;s support team.  They will tell you that it is the fault of WordPress plugins and then try and upsell you on a VPS account.  They promise not to kill your processes if you get a VPS account.  Kind of like a shop keeper that pays the gangster protection money so his store doesn&#8217;t burn down.  How sweet!  My personal opinion is <strong>why should I pay for an enhanced service if the basic service is awful?</strong> I&#8217;ll just switch web hosts.</p>
<p>Back to the question of resources.  Just how much memory does a website running WordPress with some basic plugins use?  As of this writing, I have 2 WordPress sites on DreamHost (not DigitalColony.com).  I installed 2 plugins to help me track my memory usage: <a href="http://wordpress.org/extend/plugins/wp-memory-usage/">WP-Memory-Usage</a> and <a href="http://wordpress.org/extend/plugins/tpc-memory-usage/">TPC! Memory Usage</a>.  Below is a screen shot from one of my sites.  The other site shows similar numbers.</p>
<p><img class="alignnone size-full wp-image-255" title="dreamhost-memory" src="http://digitalcolony.com/wp-content/uploads/2010/11/dreamhost-memory.png" alt="" width="392" height="431" /></p>
<p>With these two plugins I learned a few things:</p>
<ol>
<li>DreamHost limits your PHP memory to just 90 MB.</li>
<li>A basic install of WordPress takes about 30 MB of memory on a 64 bit installation of PHP.</li>
<li>I activated and deactivated every plugin.  Most used trivial amounts of memory.  No plugin exceeded 2 MB of memory.  Even the much aligned All-In-One SEO plugin used only 1.05 MB.</li>
<li>Switching themes had almost no impact on memory usage.</li>
<li><strong>With as little as two domains using WordPress on DreamHost you are already reaching the upper limits of memory allocated.</strong> So much for unlimited domains.  Perhaps they should rephrase it to unlimited <em>unused</em> domains?</li>
<li><strong>DreamHost has a serious LOAD AVERAGE problem</strong>.  The numbers in the above screen capture were the lowest I captures.  Often the Load Averages exceeded 10.</li>
</ol>
<p>Even though I went looking for answers on memory usage, the load average numbers  jumped out at me.  What do they mean and what is a good number?</p>
<p>The article <a href="http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages">Understanding Linux CPU Load &#8211; when should you be worried?</a> is a great tutorial on the topic.  It makes the case that the maximum load should not exceed the number of cores on the server.  My DreamHost server has 4 cores.   I monitored this number all day and it is always in the red zone. The CPU load on DreamHost servers is excessive.</p>
<p>My advice is to stay away from DreamHost.  Their servers are overloaded and if you plan to host more than one WordPress account you&#8217;ll experience problems.</p>
<p>UPDATE (Nov 25, 2010) &#8211; This morning the DreamHost Load times spiked much higher!</p>
<ul>
<li><strong>Load Averages</strong>: <strong> <span style="color: #ff0000;">144.95 45.93 21.12</span></strong></li>
</ul>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/aXPLZiGUVHs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2010/11/dreamhost-and-the-myth-of-unlimited-domains/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2010/11/dreamhost-and-the-myth-of-unlimited-domains/</feedburner:origLink></item>
		<item>
		<title>Adding a Stylesheet to a Master Page in C#</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/o6pyQmN4lqI/</link>
		<comments>http://digitalcolony.com/2010/11/adding-a-stylesheet-to-a-master-page-in-c/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 20:12:26 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HtmlLink]]></category>
		<category><![CDATA[Master Pages]]></category>
		<category><![CDATA[WebControls]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=241</guid>
		<description><![CDATA[I just updated the code for the Row and Column Highlight for Gridview Control lab. I decided to put the CSS specific to that feature in its own style sheet. Since I am using Master Pages for the labs, I &#8230; <a href="http://digitalcolony.com/2010/11/adding-a-stylesheet-to-a-master-page-in-c/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just updated the code for the <a href="http://digitalcolony.com/lab/row-highlight/gridview.aspx">Row and Column Highlight for Gridview Control</a> lab.  I decided to put the CSS specific to that feature in its own style sheet.  Since I am using Master Pages for the labs, I needed a way to programatically add the style sheet into the &lt;head&gt; when the page loaded.</p>
<p>Here is the C# code I used to drop in an additional style sheet.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">using</span> System.Web.UI.WebControls;</pre>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="rem">/* add custom CSS */</span>
HtmlLink rowCSS = <span class="kwrd">new</span> HtmlLink();
rowCSS.Href = <span class="str">"highlight.css"</span>;
rowCSS.Attributes.Add(<span class="str">"rel"</span>, <span class="str">"stylesheet"</span>);
rowCSS.Attributes.Add(<span class="str">"type"</span>, <span class="str">"text/css"</span>);
Header.Controls.Add(rowCSS);</pre>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/o6pyQmN4lqI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2010/11/adding-a-stylesheet-to-a-master-page-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2010/11/adding-a-stylesheet-to-a-master-page-in-c/</feedburner:origLink></item>
		<item>
		<title>Validate Web Page Against W3C Validator in .NET</title>
		<link>http://feedproxy.google.com/~r/DigitalColony/~3/ChdgTeBrNY8/</link>
		<comments>http://digitalcolony.com/2010/11/validate-web-page-against-w3c-validator-in-net/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 02:35:08 +0000</pubDate>
		<dc:creator>Michael Allen Smith</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[validate]]></category>
		<category><![CDATA[W3C]]></category>

		<guid isPermaLink="false">http://digitalcolony.com/?p=225</guid>
		<description><![CDATA[During one of the redesigns of DeepFitness.com, I decided to make sure all the articles validated to XHTML.  The post Converting HTML to XHTML Programmatically in .NET shows how I did that.  FreeTextBox did an excellent job assisting with the &#8230; <a href="http://digitalcolony.com/2010/11/validate-web-page-against-w3c-validator-in-net/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>During one of the redesigns of <a href="http://deepfitness.com">DeepFitness.com</a>, I decided to make sure all the articles validated to XHTML.  The post <a href="http://digitalcolony.com/2007/03/converting-html-to-xhtml-programmatically-in-net/">Converting HTML to XHTML Programmatically in .NET</a> shows how I did that.  FreeTextBox did an excellent job assisting with the conversion, but it wasn&#8217;t perfect.  A small percentage of the articles were not XHTML and I needed a way to know which ones needed to be fixed by hand.  Hand entering over 1,000 article URLs into the W3C validator was not an option.</p>
<p>Below is some code that sends a URL to be tested against the W3C Validator.  It returns a true or false.  If you have a lot of URLs to test &#8211; like I did &#8211; just add some reporting code to flag the ones that don&#8217;t pass.<br />
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">using</span> System.Net;</pre>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">bool</span> IsPageValid(<span class="kwrd">string</span> url)
{
    <span class="kwrd">string</span> validatorURL = <span class="str">"http://validator.w3.org/check?uri="</span>;
    <span class="kwrd">string</span> checkURL = validatorURL + url;
    <span class="kwrd">string</span> validStatus = <span class="str">"Invalid"</span>;

    <span class="rem">// create the request</span>
    HttpWebRequest request = WebRequest.Create(checkURL) <span class="kwrd">as</span> HttpWebRequest;
    <span class="rem">// instruct the server to return headers only</span>
    request.Method = <span class="str">"HEAD"</span>;
    <span class="rem">// make the connection</span>
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    WebHeaderCollection headers = response.Headers;

    <span class="kwrd">foreach</span> (<span class="kwrd">string</span> key <span class="kwrd">in</span> headers.Keys)
    {
        <span class="kwrd">if</span> (key == <span class="str">"X-W3C-Validator-Status"</span>)
            validStatus = headers[key];
    }

    <span class="kwrd">if</span> (validStatus == <span class="str">"Valid"</span>)
    {
        <span class="kwrd">return</span> <span class="kwrd">true</span>;
    }
    <span class="kwrd">else</span>
    {
        <span class="kwrd">return</span> <span class="kwrd">false</span>;
    }
}</pre>
<p>Lab <a href="http://digitalcolony.com/lab/xhtml-validator/check-validation.aspx">Validate DOCTYPE in ASP.NET</a></p>
<img src="http://feeds.feedburner.com/~r/DigitalColony/~4/ChdgTeBrNY8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://digitalcolony.com/2010/11/validate-web-page-against-w3c-validator-in-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://digitalcolony.com/2010/11/validate-web-page-against-w3c-validator-in-net/</feedburner:origLink></item>
	</channel>
</rss>

