<?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>dougv.com « Doug Vanderweide &#187; REST</title>
	<atom:link href="http://www.dougv.com/tag/rest/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.dougv.com</link>
	<description>ASP.NET, PHP, XML, JavaScript, Web geekery, Entrepreneurship</description>
	<lastBuildDate>Thu, 17 May 2012 22:33:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Displaying Selected YouTube Data API Thumbnails On A Web Page Via ASP.NET Web Forms</title>
		<link>https://www.dougv.com/2012/03/15/displaying-selected-youtube-data-api-thumbnails-on-a-web-page-via-asp-net-web-forms/</link>
		<comments>https://www.dougv.com/2012/03/15/displaying-selected-youtube-data-api-thumbnails-on-a-web-page-via-asp-net-web-forms/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 23:37:41 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[API]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Social Media]]></category>
		<category><![CDATA[Web Forms]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[YouTube Data API]]></category>
		<category><![CDATA[bit.ly]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[XPath]]></category>
		<category><![CDATA[XSLT]]></category>

		<guid isPermaLink="false">http://www.dougv.com/?p=4325</guid>
		<description><![CDATA[Describes how to query the YouTube Data API, process its response XML, and display thumbnails hyperlinked to youtube.com video pages.<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2012/03/08/displaying-selected-youtube-video-thumbnails-on-an-asp-net-web-forms-page/" rel="bookmark">Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page</a> (64.7)</li>
				<li><a href="https://www.dougv.com/2011/04/24/automatically-hash-tagging-text-with-asp-net-web-forms-vb-net/" rel="bookmark">Automatically Hash Tagging Text With ASP.NET Web Forms (VB.NET)</a> (24.5)</li>
				<li><a href="https://www.dougv.com/2011/12/25/parent-child-dropdownlist-controls-in-asp-net-web-forms-vb-net/" rel="bookmark">Parent-Child DropDownList Controls In ASP.NET Web Forms (VB.NET)</a> (23.9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Previously, I blogged about &#8220;<a href="http://www.dougv.com/2012/03/08/displaying-selected-youtube-video-thumbnails-on-an-asp-net-web-forms-page/" title="Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page">Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page</a>,&#8221; when you know the video IDs of the thumbnails you want to hyperlink.</p>
<p>A reader recently asked me how to hyperlink YouTube video thumbnails based on searching for a keyword. I promised to address that, so here goes.</p>
<p>Interestingly enough, searching the <a href="https://developers.google.com/youtube/" target="_blank">YouTube Data API</a> is accomplished in a <a href="http://www.infoq.com/articles/rest-introduction" target="_blank">REST</a>-like manner quite similar to the methodology I used for <a href="http://www.dougv.com/2009/07/02/shortening-urls-with-the-bit-ly-api-via-asp-net/" title="Shortening URLs With The bit.ly API Via ASP.NET">shortening URLs in ASP.NET via the bit.ly API</a>. </p>
<ul>
<li>Form a simple request URL to the YouTube Data API that contains the appropriate search parameters;</li>
<li>Use a <a href="http://msdn.microsoft.com/en-us/library/system.net.webrequest.aspx" target="_blank">WebRequest</a> to send that URL to Google, which returns an XML document with results;</li>
<li>Use <a href="http://msdn.microsoft.com/en-us/library/system.net.webresponse.aspx" target="_blank">WebResponse</a> to dump that stream into an <a href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx" target="_blank">XmlDocument</a>;</li>
<li>Use <a href="http://www.w3schools.com/xpath/default.asp" target="_blank">XPath</a> and <a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.aspx" target="_blank">XmlNode</a>&#8216;s SelectNodes method to recursively get the thumbnails from each entry; and</li>
<li>Bind up a pile of <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hyperlink.aspx" target="_blank">Hyperlink</a> controls, which are added dynamically to a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.panel.aspx" target="_blank">Panel</a> control.</li>
</ul>
<p>Sounds more complicated than it actually is. Let&#8217;s do it.<br />
<span id="more-4325"></span></p>
<h3>Overview Of The YouTube Data API</h3>
<p>First step in leveraging the YouTube Data API: <a href="https://code.google.com/apis/youtube/dashboard" target="_blank">Get a Youtube Data API developer key</a>.</p>
<div class="aside">As of this writing, you can keyword search query the YouTube Data API without supplying a developer key and get a useful response. However, Google wants you to supply a key, and a time may come where you must supply one. So take the 30 seconds required to register a key.</div>
<p>With our developer key in hand, we can proceed to build a simple keyword query. In this case, we&#8217;re going to get the top 12 videos that meet the search criteria &#8220;Miss Maine.&#8221; </p>
<p>For our purposes, &#8220;top 12 videos&#8221; means the 12 videos YouTube deems most relevant to the exact search term &#8220;Miss Maine.&#8221; In other words, our search is going to work exactly as though we had typed &#8220;Miss Maine&#8221; (including the double quotes) into the search box at youtube.com; the results we get back should be the same as the first 12 results we would get via a default search on youtube.com. (For the usual vague reasons, this won&#8217;t always be the case, but the results sets will be similar.)</p>
<p>The YouTube Data API tells us that, <a href="https://developers.google.com/youtube/2.0/reference#Searching_for_videos" target="_blank">to do a search query, we can GET a request to its servers</a>, with our search parameters as querystring variables, and Google will return to us an XML document containing records that match our query.</p>
<p>Because we&#8217;re not requesting user-specific data, we don&#8217;t need to authenticate our requests; as previously mentioned, we don&#8217;t even need to send along our developer key. (But, again, being courteous and thorough, we will send it, as requested.)</p>
<p>So, the methodology we use to get our records is exactly the same as we used to shorten a URL via the bit.ly API; we&#8217;re going to create a URL containing all our parameters, then make a WebRequest to the YouTube Data API; we&#8217;ll get its returned XML via a WebResponse, and push that into an XmlDocument, from which we can extract the information we want. </p>
<div class="aside">As we build this solution, let&#8217;s keep some non-technical things in mind:</p>
<ul>
<li>Many of the videos on YouTube aren&#8217;t very good, in the aesthetic, intellectual or civil senses. In other words, much of what is on YouTube is terrible.</li>
<li>A sizable number of YouTube videos are spam.</li>
<li>It&#8217;s <em>de rigueur</em> to keyword spam video descriptions, especially if the video is spam.</li>
<li>Trolling is mandatory for YouTube video comments, and you&#8217;ll probably be linking directly to that.</li>
</ul>
<p>We can mitigate the damage, somewhat, by applying the smartSearch filter, being very specific with our search term, including specific words we don&#8217;t want returned in our results, restricting the categories in which we want to search &#8230; in other words, being as specific as we can about what we want to see.</p>
<p>However, I&#8217;ll bet a dollar to doughnuts that if you request any sizable result set on any generic search term, your results set is going to contain items you wish weren&#8217;t in there. That&#8217;s just the nature of the thing, and there&#8217;s little that can be done about it.</p></div>
<h3>Querying The YouTube Data API</h3>
<p>There are three distinct phases in our solution: query the API, get the information we need from its response, and put that information on the page. Therefore, we will use three distinct functions and subroutines to do the work. </p>
<p>First up, a function to submit our query. It accepts as arguments our developer key and a formatted querystring, and it puts the response into an XML document for us. If the request fails, it will report as much in a Label control, and return an empty XML document.</p>
<pre class="brush: vb; title: ; notranslate">
Function QueryYouTubeDataAPI(ByVal strAPIKey As String, ByVal strQuery As String) As XmlDocument
	'Returns empty XMLDocument on failure, results XML on success
	'This function requires your page to have a label control named lblStatus for error reporting

	'build URL to shorten method resource
	Dim strUri As New StringBuilder(&quot;https://gdata.youtube.com/feeds/api/videos?&quot;)
	strUri.Append(&quot;v=2&quot;)
	strUri.Append(&quot;&amp;&quot;)
	strUri.Append(strQuery)
	strUri.Append(&quot;&amp;key=&quot;)
	strUri.Append(Server.HtmlEncode(strAPIKey))
	strUri.Append(&quot;&amp;prettyprint=true&quot;) 'adds line breaks &amp; white space to response; useful for debugging

	Dim objRequest As HttpWebRequest
	Dim objResponse As WebResponse
	Dim objXML As New XmlDocument() 'This is the document the function will return

	Try
		'create request for shorten resource
		objRequest = WebRequest.Create(strUri.ToString)
		'since we are passing querystring variables, our method is get
		objRequest.Method = &quot;GET&quot;
		'act as though we are sending a form
		objRequest.ContentType = &quot;application/x-www-form-urlencoded&quot;
		'don't wait for a 100 Continue HTTP response
		objRequest.ServicePoint.Expect100Continue = False
		'since we are using get, we need not send a request body; set content-length to 0
		objRequest.ContentLength = 0

		'read the Data API response into XML document
		objResponse = objRequest.GetResponse()
		objXML.Load(objResponse.GetResponseStream())
	Catch ex As Exception
		lblStatus.Text = &quot;Error querying YouTube Data API. Message: &quot; &amp; ex.Message
	End Try

	'send XML Document
	Return objXML
End Function
</pre>
<div class="aside"><strong>A note about error trapping:</strong> The error trapping I have used here does not check whether or not the YouTube Data API returns a sensible result. It only checks that we formed a request and the API responded.</p>
<p>If there is a problem with the query string you send to the YouTube Data API, or your request is somehow malformed, the API will return to you the 25 most popular videos for the day, as of the time of the request.</p>
<p>You can check to see if the YouTube Data API is seeing your request properly by looking for the /feed/link rel=&#8217;self&#8217; node:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:media='http://search.yahoo.com/mrss/' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:yt='http://gdata.youtube.com/schemas/2007' gd:etag='W/&amp;quot;CkYNSH07cSp7I2A9WhVSGEg.&amp;quot;'&gt;
	&lt;!-- ... previous nodes --&gt;
	&lt;link rel='self' type='application/atom+xml' href='https://gdata.youtube.com/feeds/api/videos?q=%22Miss+Maine%22&amp;amp;start-index=1&amp;amp;max-results=12&amp;amp;duration=short&amp;amp;safeSearch=strict&amp;amp;orderby=relevance_lang_en&amp;amp;v=2'/&gt;
	&lt;!-- additional nodes ... --&gt;
&lt;/feed&gt;
</pre>
<p>If the URL in that node doesn&#8217;t resemble the one you sent, most likely your querystring is malformed; but possibly, there are other errors in your request URL.
</p></div>
<h3>Creating The Query String</h3>
<p>You&#8217;ll notice that I am not very specific about the query string argument passed to the previous function. That&#8217;s because I want to give you maximum flexibility, and the best way to do that is to allow for a free-form query string to be supplied. </p>
<p>So let&#8217;s look at how I&#8217;ll build my sample query string. I&#8217;ll do that, of course, with key-value pairs. That is, I will specify the parameter I want to send, and set it as equal to something.</p>
<p>First up, the search term. We&#8217;re going to use &#8220;Miss Maine.&#8221; So, the first part of our query string is:</p>
<pre class="brush: plain; title: ; notranslate">q=&quot;Miss Maine&quot;</pre>
<div class="aside">Note that the YouTube Data API says all parameters should be URL encoded. Our function will take care of that for us when we create the WebRequest, so don&#8217;t bother encoding your query string in advance, or you&#8217;ll get errors. Just pass it to the function as natural text.</div>
<p>Technically, we can stop here and let the default API request variables take over. But I want to be more specific about my search results, so let&#8217;s add some more parameters.</p>
<p>Next, I&#8217;ll limit my responses to 12 records, by appending that key-value pair to my string:</p>
<pre class="brush: plain; title: ; notranslate">q=&quot;Miss Maine&quot;&amp;max-results=12</pre>
<p>I&#8217;d like only short (under 4 minutes) videos:</p>
<pre class="brush: plain; title: ; notranslate">q=&quot;Miss Maine&quot;&amp;max-results=12&amp;duration=short</pre>
<p>To cull at least some offensive material, I&#8217;ll use strict safeSearch:</p>
<pre class="brush: plain; title: ; notranslate">q=&quot;Miss Maine&quot;&amp;max-results=12&amp;duration=short&amp;safeSearch=strict</pre>
<p>Finally, I&#8217;m going to specifically ask for English language videos that best match my search term. So my completed query string is:</p>
<pre class="brush: plain; title: ; notranslate">q=&quot;Miss Maine&quot;&amp;max-results=12&amp;duration=short&amp;safeSearch=strict&amp;orderby=relevance_lang_en</pre>
<div class="aside">You may be wondering why I am not using the <a href="http://code.google.com/p/google-gdata/" target="_blank">GData .NET Library</a> to accomplish this search. That&#8217;s an excellent option in general, but it involves installing components on your local machine and Web server. </p>
<p>For many Web developers, adding DLLs to a Web server or installing assemblies on a workstation can be problematic, if not prohibited outright. So I want to use as many built-in resources as possible. However, if you can install the GData API, consider going that route.</p></div>
<h3>Examining The XML Response</h3>
<p>Assuming our request goes through &#8212; that is, our Web server actually delivers the request to YouTube, which in turn sends a response back &#8212; we now have an XML document in storage that contains the information we requested. (Or, in the event of a malformed request, the default results set previously described.)</p>
<p>You can see the XML document returned for my demo query string here: <a href="http://www.dougv.net/demos/youtube_data_api_thumbs/videos.xml" target="_blank">http://www.dougv.net/demos/youtube_data_api_thumbs/videos.xml</a></p>
<p>In our case, we want some specific data for each video:</p>
<ul>
<li>Its title;</li>
<li>the default thumbnail; and</li>
<li>the URL to its player page on youtube.com.</li>
</ul>
<p>We get back lots more useful information in the XML response: The name of the uploader, the run time of the video in seconds, its likes and dislikes count, the categories and keywords assigned to the video, the date and time it was uploaded, its view count, etc. But for this solution, we&#8217;ll only use the video&#8217;s title, thumbnail and URL.</p>
<p>Although the actual XML document contains much more data per entry, for our purposes, the relevant structure of the document looks like this (I&#8217;ve stripped out extraneous attributes):</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;feed&gt;
	&lt;entry&gt;
		&lt;title&gt;&lt;/title&gt;
		&lt;link rel='alternate' /&gt;
		&lt;media:group&gt;
			&lt;media:thumbnail /&gt;
		&lt;/media:group&gt;
	&lt;/entry&gt;
&lt;/feed&gt;
</pre>
<p>In practice, the parts of an entry (that is, an individual record) that we want to use look like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;entry gd:etag='W/&amp;quot;DU8AQ347eCp7I2A9WhRWEEQ.&amp;quot;'&gt;
	&lt;title&gt;Miss Maine USA 2011&lt;/title&gt;
	&lt;link rel='alternate' type='text/html' href='https://www.youtube.com/watch?v=STm4GUqwLVo&amp;amp;feature=youtube_gdata'/&gt;
	&lt;media:group&gt;
		&lt;media:thumbnail url='http://i.ytimg.com/vi/STm4GUqwLVo/default.jpg' height='90' width='120' time='00:00:43.500' yt:name='default'/&gt;
	&lt;/media:group&gt;
&lt;/entry&gt;
</pre>
<h3>Traversing The XML Response Document</h3>
<div class="aside">There are a number of ways in ASP.NET to traverse / select nodes from an XML document. </p>
<p>The way most Web resources will tell you to do it is with LINQ to XML. LINQ allows us to make a SQL-like query of the XML document, and receive in return a SQL-like recordset, which we can then use to ouput our data.</p>
<p>LINQ to XML is definitely the way to go if you&#8217;re going to work with a large XML document, or need to extract data in a very complicated way (e.g, get various node attributes; select nodes based on data contained in other nodes). </p>
<p>LINQ to XML would work here, too, but I think it&#8217;s a bit of overkill, considering we only need three values from 12 records. So I&#8217;m just going to use the built-in parsing functions that are part of XmlDocument, a class we have already encumbered. Also, I&#8217;m more used to using XPath than I am LINQ.</p>
<p>Another way is to create an XML Stylesheet (<a href="http://www.w3schools.com/xsl/" target="_blank">XSLT</a>) which will &#8220;flattened out&#8221; the XML document into 12 nodes (each representing one record) with three attributes (each representing the title, URL and thumbnail for that record). I describe that methodology at &#8220;<a href="http://www.dougv.com/2006/11/11/using-national-weather-service-xml-feeds-with-aspnet-adonet-and-xsl/" title="Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL" target="_blank">Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL</a>.&#8221; </p>
<p>But I am trying to limit the number of things you have to learn at one time to accomplish this task. In my estimation, it&#8217;s a bit easier to hack together an XPath expression than to write an XSLT, so this is how I&#8217;m proceeding.</p></div>
<p>We&#8217;ll need three XPath expressions that will give us, for each of the 12 videos returned:</p>
<ol>
<li>the inner text of title,</li>
<li>the inner text of the link node that has the attribute &#8216;alternate&#8217;, and </li>
<li>the url attribute of whichever media:thumbnail node that has the additional attribute of yt:name=&#8217;default&#8217;.</li>
</ol>
<p>The XML returned by the YouTube Data API uses several namespaces (atom, media, yt, etc.). Therefore, we first have to make reference to those namespaces in order to traverse the response XML.</p>
<p>We do that by creating an XmlNamespaceManager, then adding the specification URLs to it:</p>
<pre class="brush: vb; title: ; notranslate">
'add namespaces so we can traverse this thing
Dim xmlNSM As New XmlNamespaceManager(xmlDoc.NameTable)
xmlNSM.AddNamespace(&quot;atom&quot;, &quot;http://www.w3.org/2005/Atom&quot;)
xmlNSM.AddNamespace(&quot;media&quot;, &quot;http://search.yahoo.com/mrss/&quot;)
xmlNSM.AddNamespace(&quot;yt&quot;, &quot;http://gdata.youtube.com/schemas/2007&quot;)
</pre>
<p>(We got these URLs from the root (&#8220;feed&#8221;) node&#8217;s attributes. That&#8217;s where they always appear, any time an XML document references namespace(s).</p>
<div class="aside">An <a href="http://www.w3.org/TR/REC-xml-names/" target="_blank">XML namespace</a> is basically a description of what elements an XML document will have, the kinds of data each node will contain, and other useful technical information that helps a parser understand what it is looking at and how to consume it.</div>
<p>Now that we have the namespaces referenced, we can go ahead and create our XPath arguments. Here they are:</p>
<pre class="brush: vb; title: ; notranslate">
'let's get our entry node values
Dim xmlTitleNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/atom:title&quot;, xmlNSM)
Dim xmlURLNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/media:group/media:player&quot;, xmlNSM)
Dim xmlThumbNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/media:group/media:thumbnail[@yt:name='default']&quot;, xmlNSM)
</pre>
<p>Note that I use the namespace:node syntax to select the nodes I want. If I didn&#8217;t do that, the XML parser wouldn&#8217;t understand what I meant if I said simply, &#8220;feed&#8221;, for example. I have to let the parser know which namespace the element &#8220;feed&#8221; belongs to, so it can find it.</p>
<p>With our nodes on hand, we just need to iterate each XmlNodeList, get our values, and pass them to a subroutine that adds hyperlinked thumbnails to our page.</p>
<p>We can use a simple For loop here, because by design, the number of title, thumbnail and hyperlink nodes will be the same, and the nodes will be in the same order in all three XmlNodeLists. (That is, the first node in each XmlNodeList will be for the first record; the title, URL and thumbnail values will match up, because they were listed in order in the XML document.)</p>
<pre class="brush: vb; title: ; notranslate">
'For loop will iterate them; by definition, counts are the same for each XmlNodeList
For I = 0 To xmlTitleNodes.Count - 1
	strTitle = xmlTitleNodes.Item(I).InnerText
	strURL = xmlURLNodes.Item(I).Attributes(&quot;url&quot;).Value
	strThumb = xmlThumbNodes.Item(I).Attributes(&quot;url&quot;).Value

	CreateHyperlinkedThumb(strTitle, strURL, strThumb)
Next
</pre>
<p>Here&#8217;s what the entire subroutine looks like:</p>
<pre class="brush: vb; title: ; notranslate">
Sub MakeThumbnailLinks(ByVal strAPIKey As String, ByVal strQuery As String)
	'create XML document we will parse
	Dim xmlDoc As New XmlDocument()
	xmlDoc = QueryYouTubeDataAPI(strAPIKey, strQuery)

	'add namespaces so we can traverse this thing
	Dim xmlNSM As New XmlNamespaceManager(xmlDoc.NameTable)
	xmlNSM.AddNamespace(&quot;atom&quot;, &quot;http://www.w3.org/2005/Atom&quot;)
	xmlNSM.AddNamespace(&quot;media&quot;, &quot;http://search.yahoo.com/mrss/&quot;)
	xmlNSM.AddNamespace(&quot;yt&quot;, &quot;http://gdata.youtube.com/schemas/2007&quot;)

	'let's get our entry node values
	Dim xmlTitleNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/atom:title&quot;, xmlNSM)
	Dim xmlURLNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/media:group/media:player&quot;, xmlNSM)
	Dim xmlThumbNodes As XmlNodeList = xmlDoc.SelectNodes(&quot;/atom:feed/atom:entry/media:group/media:thumbnail[@yt:name='default']&quot;, xmlNSM)

	'for debugging, we'll also get the url that represents what the Data API actually used
	Dim objNode As XmlNode = xmlDoc.SelectSingleNode(&quot;/atom:feed/atom:link[@rel='self']&quot;, xmlNSM)
	lblStatus.Text = &quot;&lt;strong&gt;Request URL returned by YouTube Data API:&lt;/strong&gt; &quot; &amp; Server.HtmlEncode(objNode.Attributes(&quot;href&quot;).Value)

	'strings to store values
	Dim strTitle As String
	Dim strURL As String
	Dim strThumb As String

	'looping variable
	Dim I As Integer

	'For loop will iterate them; by definition, counts are the same for each XmlNodeList
	For I = 0 To xmlTitleNodes.Count - 1
		strTitle = xmlTitleNodes.Item(I).InnerText
		strURL = xmlURLNodes.Item(I).Attributes(&quot;url&quot;).Value
		strThumb = xmlThumbNodes.Item(I).Attributes(&quot;url&quot;).Value

		CreateHyperlinkedThumb(strTitle, strURL, strThumb)
	Next
End Sub
</pre>
<h3>Creating Thumbs From Results</h3>
<p>The CreateHyperlinkedThumb subroutine takes the title, URL and thumbnail strings we got, applies them as properties to a Hyperlink control, and adds those controls to a Panel on our page.</p>
<pre class="brush: vb; title: ; notranslate">
Sub CreateHyperlinkedThumb(strTitle As String, strURL As String, strThumb As String)
	'create hyperlink
	Dim ctlLink As New HyperLink()

	'set values
	ctlLink.Text = strTitle
	ctlLink.ToolTip = strTitle
	ctlLink.NavigateUrl = strURL
	ctlLink.ImageUrl = strThumb
	ctlLink.CssClass = &quot;margin-5&quot;
	ctlLink.Target = &quot;video&quot;

	'add to panel
	pnlThumbs.Controls.Add(ctlLink)
End Sub
</pre>
<p>And with that, we&#8217;re done!</p>
<p>To invoke, we simply call the MakeThumbnailLinks subroutine, passing to it our YouTube Data API developer key and the querystring we built:</p>
<pre class="brush: vb; title: ; notranslate">MakeThumbnailLinks(&quot;YOUTUBE_DATA_API_DEVELOPER_KEY&quot;, &quot;q=&quot;&quot;Miss Maine&quot;&quot;&amp;max-results=12&amp;duration=short&amp;safeSearch=strict&amp;orderby=relevance_lang_en&quot;)</pre>
<p>You can see a working demo here: <a href="http://www.dougv.net/demos/youtube_data_api_thumbs/Example2.aspx" target="_blank">http://www.dougv.net/demos/youtube_data_api_thumbs/Example2.aspx</a></p>
<p>The code for this solution, as well as &#8220;<a href="http://www.dougv.com/2012/03/08/displaying-selected-youtube-video-thumbnails-on-an-asp-net-web-forms-page/" title="Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page" target="_blank">Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page</a>,&#8221; can be downloaded here: <a href='http://www.dougv.com/wp-content/uploads/2012/03/youtube_data_api_thumbs.zip'>http://www.dougv.com/wp-content/uploads/2012/03/youtube_data_api_thumbs.zip</a></p>
<p>All links in this post on delicious: <a href="http://delicious.com/dougvdotcom/displaying-selected-youtube-data-api-thumbnails-on-a-web-page-via-asp-net-web-forms" target="_blank">http://delicious.com/dougvdotcom/displaying-selected-youtube-data-api-thumbnails-on-a-web-page-via-asp-net-web-forms</a></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2012/03/08/displaying-selected-youtube-video-thumbnails-on-an-asp-net-web-forms-page/" rel="bookmark">Displaying Selected YouTube Video Thumbnails On An ASP.NET Web Forms Page</a> (64.7)</li>
				<li><a href="https://www.dougv.com/2011/04/24/automatically-hash-tagging-text-with-asp-net-web-forms-vb-net/" rel="bookmark">Automatically Hash Tagging Text With ASP.NET Web Forms (VB.NET)</a> (24.5)</li>
				<li><a href="https://www.dougv.com/2011/12/25/parent-child-dropdownlist-controls-in-asp-net-web-forms-vb-net/" rel="bookmark">Parent-Child DropDownList Controls In ASP.NET Web Forms (VB.NET)</a> (23.9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/bit-ly/" title="bit.ly" rel="tag">bit.ly</a>, <a href="https://www.dougv.com/tag/google/" title="Google" rel="tag">Google</a>, <a href="https://www.dougv.com/tag/microsoft/" title="Microsoft" rel="tag">Microsoft</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a>, <a href="https://www.dougv.com/tag/rss/" title="RSS" rel="tag">RSS</a>, <a href="https://www.dougv.com/tag/xpath/" title="XPath" rel="tag">XPath</a>, <a href="https://www.dougv.com/tag/xslt/" title="XSLT" rel="tag">XSLT</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2012/03/15/displaying-selected-youtube-data-api-thumbnails-on-a-web-page-via-asp-net-web-forms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting QueryString Values From A Rewritten URL / ASP.NET Routing URL</title>
		<link>https://www.dougv.com/2010/12/10/getting-querystring-values-from-a-rewritten-url-asp-net-routing-url/</link>
		<comments>https://www.dougv.com/2010/12/10/getting-querystring-values-from-a-rewritten-url-asp-net-routing-url/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 03:15:51 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[rewrite]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=3445</guid>
		<description><![CDATA[During today&#8217;s similcast of the ASP.NET Firestarter in Atlanta, G. Andrew Duthie discussed .NET 4&#8242;s new support for routing &#8212; or, what everyone in Web development calls &#8220;URL rewriting.&#8221; * Someone online asked, &#8220;If I use routing, can I access query string variables using JavaScript?&#8221; The question isn&#8217;t as confused as it sounds on the [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/06/22/going-to-a-new-url-via-a-drop-down-list-javascript-and-dom-php-aspnet/" rel="bookmark">Going To A New URL Via A Drop-Down List: JavaScript And DOM, PHP, ASP.NET</a> (25.2)</li>
				<li><a href="https://www.dougv.com/2009/08/12/new-url-for-asp-net-demos-dougv-net/" rel="bookmark">New URL For ASP.NET Demos: dougv.net</a> (24.6)</li>
				<li><a href="https://www.dougv.com/2009/06/13/retaining-values-in-a-form-following-php-postback-and-clearing-form-values-after-successful-php-form-processing/" rel="bookmark">Retaining Values In A Form Following PHP Postback And Clearing Form Values After Successful PHP Form Processing</a> (19)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>During today&#8217;s <a href="http://www.microsoft.com/events/series/simulcasts.aspx?tab=videos&amp;id=43352">similcast of the ASP.NET Firestarter in Atlanta</a>, <a href="http://www.devhammer.net" target="_blank">G. Andrew Duthie</a> discussed .NET 4&#8242;s new support for routing &#8212; or, what everyone in Web development calls &#8220;<a href="http://en.wikipedia.org/wiki/Rewrite_engine" target="_blank">URL rewriting</a>.&#8221; *</p>
<p>Someone online asked, &#8220;If I use routing, can I access query string variables using JavaScript?&#8221;</p>
<p>The question isn&#8217;t as confused as it sounds on the surface. Of course, if one uses routing / URL rewriting, it&#8217;s to remove query string variable and make them part of what appears to be a permanent file structure.</p>
<p>In other words, this:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/path/to/file.aspx?v1=foo&amp;v2=bar</pre>
<p>Becomes this:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/path/to/file/v1/foo/v2/bar/</pre>
<p>The questioner really means, is there a way, after rewriting a URL, to extract key-&gt;value pairs from it via JavaScript? The answer is yes; rather than using the <a href="http://w3schools.com/jsref/prop_loc_search.asp" target="_blank">location.search</a> property, which allows JavaScript to get the querystring parameters of a URL, we use <a href="http://w3schools.com/jsref/prop_loc_pathname.asp" target="_blank">location.pathname</a> to get the part of the URL that follows the domain, and use that to create our key-&gt;value pairs.</p>
<p><span id="more-3445"></span>In the case of query strings, one can, in JavaScript, use location.search to get query string pairs from the current URL.</p>
<pre class="brush: jscript; title: ; notranslate">alert(location.search);</pre>
<p>If we invoke this JavaScript on the first URL, we get the entire query string, including the question mark:</p>
<p><img class="alignnone size-full wp-image-3448" title="Query string alert" src="http://www.dougv.com/wp-content/uploads/2010/12/alert01.jpg" alt="" width="355" height="117" /></p>
<p>Then, to get the key-value pairs, we&#8217;d simply strip off the leading question mark, then split the remaining string into an associative array, like so:</p>
<pre class="brush: jscript; title: ; notranslate">
//get key-&gt;value pairs
var qs = location.search;
qs = qs.substring(1);
var a = qs.split('&amp;');

var b;
var i;
var output = new Array();

for(i = 0; i &lt; a.length; i++) {
	//split each key-&gt;value pair
	b = a[i].split('=');
	//add each pair to output array
	output[b[0]] = b[1];
}
</pre>
<p>Of course, we can&#8217;t use location.search to get query string variables if we&#8217;ve made those variables part of the file path, as in a URL rewrite / Routing. We get a null string if we try:</p>
<p><img class="alignnone size-full wp-image-3449" title="No query string" src="http://www.dougv.com/wp-content/uploads/2010/12/alert02.jpg" alt="" width="355" height="117" /></p>
<p>But we can use location.pathname to get the URL to our file, and modify our JavaScript to create key-&gt;value pairs from that URL:</p>
<pre class="brush: jscript; title: ; notranslate">
//get key-&gt;value pairs from URL
var qs = location.pathname;
//strip leading path slash
qs = qs.substring(1);

var a = qs.split('/');
var i;
var output = new Array();

for(i = 0; i &lt; a.length; i += 2) {
	//append key-&gt;value pairs to output array
	output[a[i]] = a[i + 1];
}
</pre>
<h3>Alternative: A URL That Does Not Begin With Key-&gt;Value Pairs</h3>
<p>The example above assumes that we have a URL patterned specifically after key-value pairs, and that those pairs begin at the start of the URL. In other words, the above rewritten / routed URL and JavaScript would create an array like:</p>
<pre class="brush: jscript; title: ; notranslate">
output['v1'] == 'foo';
output['v2'] == 'bar';
</pre>
<p>So we&#8217;d need to modify this JavaScript if the rewritten / routed URL does not begin immediately with key-&gt;value pairs. For example, suppose this is our rewritten URL:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/store/category/toys/type/dolls/maker/mattel/</pre>
<p>In this case, let&#8217;s suppose that &#8220;store&#8221; isn&#8217;t part of the key-&gt;value chain we want. Or, to make it plainer, if we were using a query string, this is how the URL would look:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/store.php?category=toys&amp;type=dolls&amp;maker=mattel/</pre>
<p>In that case, we&#8217;d need to adjust our for loop to skip over &#8220;store,&#8221; since it isn&#8217;t relevant to the key-&gt;value pair extraction. We can do that quite easily by simply starting the for loop at 1, rather than zero:</p>
<pre class="brush: jscript; title: ; notranslate">
//get key-&gt;value pairs from URL
var qs = location.pathname;
//strip leading path slash
qs = qs.substring(1);

var a = qs.split('/');
var i;
var output = new Array();

for(i = 1; i &lt; a.length; i += 2) {
	//append key-&gt;value pairs to output array
	output[a[i]] = a[i + 1];
}
</pre>
<p>If the URL looked like this:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/site/store/category/toys/type/dolls/maker/mattel/</pre>
<p>And &#8220;site&#8221; and &#8220;store&#8221; aren&#8217;t part of the key-&gt;value array we want to build, then we would start the for loop at 2, rather than 0.</p>
<p>Note that we can also end the for loop early, if the URL has trailing path information that shouldn&#8217;t be considered part of the key-&gt;values array.</p>
<h3>Keyless Array</h3>
<p>Another option here is to rewrite / route our URLs without keys.</p>
<p>Let&#8217;s look at the store URL sample, above. We know that we want to get values for category, type and maker. But probably every URL our JavaScript will process is always going to have those elements in the same order.</p>
<p>In other words, every URL that comes to our page is going to have category first, then type, then maker. So do we even need keys? Our URL could be much shorter and simpler if we eliminated them:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">http://www.server.com/toys/dolls/mattel/</pre>
<p>Our JavaScript is also much simpler: We can now use the initial split of the filepath variable.</p>
<pre class="brush: jscript; title: ; notranslate">
//get key-&gt;value pairs from URL
var qs = location.pathname;
//strip leading path slash
qs = qs.substring(1);

var output = qs.split('/');
//output[0] == 'toys'
//output[1] == 'dolls'
//output[2] == 'mattel'
</pre>
<h3>The Right Rewriting / Routing Rules Make A Big Difference</h3>
<p>If you&#8217;ve chosen the proper URL rewrite / routing rules, you shouldn&#8217;t have to even work this hard to extract your former query string key-&gt;value pairs. The right pattern is key.</p>
<p>I distribute this code under the GNU GPL version 3.</p>
<p>All links in this post on delicious: <a href="http://www.delicious.com/dougvdotcom/getting-querystring-values-from-a-rewritten-url-asp-net-routing-url" target="_blank">http://www.delicious.com/dougvdotcom/getting-querystring-values-from-a-rewritten-url-asp-net-routing-url</a></p>
<p><em>* Why Microsoft feels the need to re-brand common technologies is beyond me. It took them forever to adopt URL rewriting officially; and while &#8220;routing&#8221; is technically a correct description of what a rewrite engine does, it only makes it harder for developers to discuss patterns and practices with others when Microsoft insists on calling roses by other names.</em></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/06/22/going-to-a-new-url-via-a-drop-down-list-javascript-and-dom-php-aspnet/" rel="bookmark">Going To A New URL Via A Drop-Down List: JavaScript And DOM, PHP, ASP.NET</a> (25.2)</li>
				<li><a href="https://www.dougv.com/2009/08/12/new-url-for-asp-net-demos-dougv-net/" rel="bookmark">New URL For ASP.NET Demos: dougv.net</a> (24.6)</li>
				<li><a href="https://www.dougv.com/2009/06/13/retaining-values-in-a-form-following-php-postback-and-clearing-form-values-after-successful-php-form-processing/" rel="bookmark">Retaining Values In A Form Following PHP Postback And Clearing Form Values After Successful PHP Form Processing</a> (19)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/microsoft/" title="Microsoft" rel="tag">Microsoft</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a>, <a href="https://www.dougv.com/tag/rewrite/" title="rewrite" rel="tag">rewrite</a>, <a href="https://www.dougv.com/tag/seo/" title="SEO" rel="tag">SEO</a>, <a href="https://www.dougv.com/tag/visual-studio/" title="Visual Studio" rel="tag">Visual Studio</a>, <a href="https://www.dougv.com/tag/web-server/" title="web server" rel="tag">web server</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2010/12/10/getting-querystring-values-from-a-rewritten-url-asp-net-routing-url/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MSDN Northeast Roadshow, Augusta, ME, May 11, 2010 Recap</title>
		<link>https://www.dougv.com/2010/05/12/msdn-northeast-roadshow-augusta-me-may-11-2010-recap/</link>
		<comments>https://www.dougv.com/2010/05/12/msdn-northeast-roadshow-augusta-me-may-11-2010-recap/#comments</comments>
		<pubDate>Wed, 12 May 2010 20:23:36 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[Chris Bowen]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[coding standards]]></category>
		<category><![CDATA[developer tools]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[Jim O'Neil]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[MSDN]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Sharepoint]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[Windows Server]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=3125</guid>
		<description><![CDATA[After the nearly complete disappointment of Launch 2010 Boston, I had given serious thought to not going to the MSDN Northeast Roadshow stop in Augusta, ME on Tuesday, May 11. I figured it would be little more than a regurgitation of what happened at last month&#8217;s event. I&#8217;m glad I decided to go. What a [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/08/14/msdn-northeast-roadshow-sept-24-in-augusta-me/" rel="bookmark">MSDN Northeast Roadshow: Sept. 24 in Augusta, ME</a> (67.1)</li>
				<li><a href="https://www.dougv.com/2009/03/05/msdn-roadshow-in-augusta-march-19-well-worth-the-time/" rel="bookmark">MSDN Roadshow In Augusta, March 19: Well Worth The Time</a> (50.1)</li>
				<li><a href="https://www.dougv.com/2010/04/14/visual-studio-2010-net-4-events-for-maine-based-developers/" rel="bookmark">Visual Studio 2010 / .NET 4 Events For Maine-Based Developers</a> (28.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://www.dougv.com/2010/04/29/live-from-the-microsoft-launch-2010-event-in-boston/" target="_blank">the nearly complete disappointment of Launch 2010 Boston</a>, I had given serious thought to not going to the MSDN Northeast Roadshow stop in Augusta, ME on Tuesday, May 11. I figured it would be little more than a regurgitation of what happened at last month&#8217;s event.</p>
<p>I&#8217;m glad I decided to go. What a huge difference.</p>
<p>In  half the time, <a href="http://blogs.msdn.com/jimoneil/" target="_blank">Jim O&#8217;Neil</a> and <a href="http://blogs.msdn.com/cbowen/" target="_blank">Chris Bowen</a> provided immeasurably more valuable and interesting information about <a href="http://msdn.microsoft.com/en-us/vstudio/default.aspx" target="_blank">Visual Studio 2010</a> and changes to <a href="http://www.silverlight.net" target="_blank">Silverlight</a>, multithreading, <a href="http://www.asp.net" target="_blank">ASP.NET</a> and an overview of <a href="http://developer.windowsphone.com" target="_blank">Windows Phone 7</a>. Here&#8217;s a recap.</p>
<div id="attachment_3126" class="wp-caption alignnone" style="width: 610px"><img class="size-full wp-image-3126 " title="MSDN Northeast Roadshow, May 11, 2010, Augusta, ME" src="http://www.dougv.com/wp-content/uploads/2010/05/2010-05-11-13.30.57.jpg" alt="MSDN Northeast Roadshow, May 11, 2010, Augusta, ME" width="600" height="286" /><p class="wp-caption-text">Jim O&#39;Neil describes Silverlight 4&#39;s new video / webcam support features.</p></div>
<p><strong>Silverlight 4</strong>: Lately, listening to Microsoft describe a new Web technology brings to mind the phrase &#8220;a day late and a dollar short.&#8221; That&#8217;s certainly the case with Silverlight 4.</p>
<p>Admittedly, Microsoft has shifted the emphasis behind Silverlight to be less a clone of <a href="http://www.adobe.com/devnet/flash/" target="_blank">Flash</a> and more an extension to the Web of <a href="http://msdn.microsoft.com/en-us/library/ms754130.aspx" target="_blank">Windows Presentation Foundation</a>. But the &#8220;new features&#8221; O&#8217;Neil described on Tuesday were very much old technologies for Flash, and pretty much obsolete tech given <a href="http://en.wikipedia.org/wiki/HTML5" target="_blank">HTML5</a>.</p>
<p>Specifically, Silverlight 4 supports Web cams and microphones; TCP/UDP; printing; and a multiple-trust-level model that includes access to the file system, cross-domain requests and COM integration. Additionally, the <a href="http://msdn.microsoft.com/en-us/library/ms752059.aspx" target="_blank">XAML</a> one writes to render Silverlight, while still different from WPF XAML, is a lot more like WPF.</p>
<p>Silverlight is, therefore, weaker than Flash and stronger than it at the same time. But it seems mostly moot, given that Flash itself is falling out of favor in response to the HTML5 specification&#8217;s API support for audio, video and other complex objects. Admittedly, there are things one can do in Silverlight &#8212; namely, presenting stored data and integrating existing COM components, such as text-to-speech or an interface to a proprietary business object / program &#8212; that one cannot do directly in HTML5.</p>
<p>That seems to me more likely to matter when making a corporate intranet or the like. I didn&#8217;t see much hope for Silverlight when it was introduced in 2007, and I still don&#8217;t see a future for it.</p>
<p><span id="more-3125"></span><strong>Parallel Programming:</strong> I admit I&#8217;m not as up-to-speed as I should be with <a href="http://msdn.microsoft.com/en-us/concurrency/default.aspx" target="_blank">parallel programming</a>, largely because 99 out of 100 things I program are Web apps. So maybe Bowen&#8217;s presentation on .NET 4&#8242;s revisions to multithreading aren&#8217;t that exciting, but I found them fascinating.</p>
<p>One of the most interesting things .NET does is employ local work-stealing queues. In other words, each thread can queue, specific to it, tasks to perform; but if a neighboring thread has nothing to do, it can reach into that other thread&#8217;s queue and process the job, too. Basically, that means optimizing each thread to work almost constantly, which is, of course, a wholesale improvement in processing efficiency.</p>
<p>A couple of neat tricks Bowen showed that can be easily integrated into a current .NET project are <a href="http://www.lovethedot.net/2009/02/parallelfor-deeper-dive-parallel.html" target="_blank">Parallel.For</a> and <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.invoke.aspx" target="_blank">Parallel.Invoke</a>. Parallel.For effectively lets you multithread a standard for loop; Parallel.Invoke lets you multithread a series of method / function calls.</p>
<p><strong>ASP.NET 4 and Windows Azure:</strong> Once again, I get the feeling that Microsoft is a bit behind the times when it comes to Web development technologies. And while integrating <a href="http://www.microsoft.com/windowsazure/getstarted/" target="_blank">Azure</a>, Microsoft&#8217;s cloud computing service, into Web development is pretty progressive, the rest of the improvements to ASP.NET, especially Web forms, is more fixing things that were broken than making things better.</p>
<p>Notable in ASP.NET 4 Web forms is the ability to disable viewstate at the page level, but enable it on a per-control level; previously, one could disable viewstate for a specific control while enabling it on the page level.</p>
<p><a href="http://www.iis.net/" target="_blank">IIS 7</a> also more closely integrates the ASP.NET engine, so that services such as membership can be extended to plain HTML pages.</p>
<p>Web forms also has a slightly improved client-side naming convention for rendered controls, but in all honesty, it&#8217;s still a mess to address, via JavaScript, individual elements of, say, a GridView.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/cc488469.aspx" target="_blank">Dynamic Data</a> sites are improved by adding <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.entitydatasource.aspx" target="_blank">EntityDataSource</a> to the list of available data sources; and the MVC aspects of ASP.NET have been improved, although a lack of time prevented O&#8217;Neil from getting into them in detail.</p>
<p>He did have an opportunity to briefly go over using Azure to host both the application and data for a Web site, which looks interesting; but given how cheap Web hosting is, and that most Web apps can happily live on a shared hosting solution, or on a third-hand server that would otherwise be junked, I don&#8217;t see Azure Web programming being of much use to most folks.</p>
<p><strong>Windows Phone 7: </strong>Due to previous presentations running long, Bowen ran short of time to talk about Windows Phone 7; I think &#8220;abortive&#8221; is a good one-word description of how this presentation went.</p>
<p>Fortunately, Windows Phone 7 won&#8217;t hit the market until Christmas time, so maybe he&#8217;ll get another crack at it before then. Until then, check out <a href="http://developer.windowsphone.com" target="_blank">developer.windowsphone.com</a> to get the tools (including an emulator), see tutorials, etc.</p>
<p><strong>Swag And Final Thoughts:</strong> This event included the same T-shirt and VS 2010 Ultimate trial disc as Launch 2010 Boston, but an upgraded notebook and pen. I declined them. But I did win an awesome, insulated lunch bag at the end of the event:</p>
<div id="attachment_3134" class="wp-caption alignnone" style="width: 610px"><img class="size-full wp-image-3134" title="The &quot;Heroes Happen Here&quot; insulated lunch bag I won" src="http://www.dougv.com/wp-content/uploads/2010/05/2010-05-12-12.51.15.jpg" alt="The &quot;Heroes Happen Here&quot; insulated lunch bag I won" width="600" height="461" /><p class="wp-caption-text">The &quot;Heroes Happen Here&quot; lunch bag I won at the end of the May 11, 2010 MSDN Northeast Roadshow event in Augusta.</p></div>
<p>Note the &#8220;Heroes Happen Here&#8221; tag, which indicates this was a giveaway related to the VS 2008 / <a href="http://www.microsoft.com/windowsserver2008/en/us/default.aspx" target="_blank">Windows Server 2008</a> / <a href="http://www.microsoft.com/sqlserver/2008/en/us/" target="_blank">SQL Server 2008</a> launch. Oh, the irony.</p>
<p>I swear my shining opinion of this Roadshow event has nothing to do with winning the lunch bag. Statistically speaking, it was difficult <em>not </em>to win; I&#8217;d put the ratio of prizes to people at 4-1. The giveaways included two copies of VS 2010 Professional, several Windows mobile mouses, books, totes and other very cool stuff.</p>
<p>So yes, it&#8217;s nice to have won something cool (no pun intended), but it&#8217;s far better to have had my time rewarded with useful information. This event really renewed my faith in MSDN support for developers and took a lot of the sting out of the disappointment of Launch 2010 Boston.</p>
<p>Let&#8217;s hope Microsoft continues to support the Northeast Roadshow for a long time to come, because it is, by far, the most valuable resource I&#8217;ve found for learning about Microsoft tools and technologies.</p>
<p><strong>Materials and Links:</strong> You can get the Powerpoints O&#8217;Neil and Bowen used at <a href="http://tinyurl.com/NERDShow0510" target="_blank">http://tinyurl.com/NERDShow0510</a>. Eventually, screencasts will be available at <a href="http://code.msdn.microsoft.com/northeast" target="_blank">http://code.msdn.microsoft.com/northeast</a>.</p>
<p>I recommend joining the <a href="http://www.facebook.com/group.php?gid=4825423963" target="_blank">Northeast Roadshow&#8217;s Facebook group</a>. But remember, group Wall posts aren&#8217;t included in your news stream, so you have to physically go to the group&#8217;s page to see what&#8217;s happening.</p>
<p>All links in this post on delicious: <a href="http://delicious.com/dougvdotcom/msdn-northeast-roadshow-augusta-me-may-11-2010-recap" target="_blank">http://delicious.com/dougvdotcom/msdn-northeast-roadshow-augusta-me-may-11-2010-recap</a></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/08/14/msdn-northeast-roadshow-sept-24-in-augusta-me/" rel="bookmark">MSDN Northeast Roadshow: Sept. 24 in Augusta, ME</a> (67.1)</li>
				<li><a href="https://www.dougv.com/2009/03/05/msdn-roadshow-in-augusta-march-19-well-worth-the-time/" rel="bookmark">MSDN Roadshow In Augusta, March 19: Well Worth The Time</a> (50.1)</li>
				<li><a href="https://www.dougv.com/2010/04/14/visual-studio-2010-net-4-events-for-maine-based-developers/" rel="bookmark">Visual Studio 2010 / .NET 4 Events For Maine-Based Developers</a> (28.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/chris-bowen/" title="Chris Bowen" rel="tag">Chris Bowen</a>, <a href="https://www.dougv.com/tag/cloud-computing/" title="cloud computing" rel="tag">cloud computing</a>, <a href="https://www.dougv.com/tag/coding-standards/" title="coding standards" rel="tag">coding standards</a>, <a href="https://www.dougv.com/tag/developer-tools/" title="developer tools" rel="tag">developer tools</a>, <a href="https://www.dougv.com/tag/iis/" title="IIS" rel="tag">IIS</a>, <a href="https://www.dougv.com/tag/jim-oneil/" title="Jim O&#039;Neil" rel="tag">Jim O&#039;Neil</a>, <a href="https://www.dougv.com/tag/microsoft/" title="Microsoft" rel="tag">Microsoft</a>, <a href="https://www.dougv.com/tag/mobile/" title="mobile" rel="tag">mobile</a>, <a href="https://www.dougv.com/tag/msdn/" title="MSDN" rel="tag">MSDN</a>, <a href="https://www.dougv.com/tag/productivity/" title="productivity" rel="tag">productivity</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a>, <a href="https://www.dougv.com/tag/sharepoint/" title="Sharepoint" rel="tag">Sharepoint</a>, <a href="https://www.dougv.com/tag/silverlight/" title="Silverlight" rel="tag">Silverlight</a>, <a href="https://www.dougv.com/tag/visual-studio/" title="Visual Studio" rel="tag">Visual Studio</a>, <a href="https://www.dougv.com/tag/windows-phone/" title="Windows Phone" rel="tag">Windows Phone</a>, <a href="https://www.dougv.com/tag/windows-server/" title="Windows Server" rel="tag">Windows Server</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2010/05/12/msdn-northeast-roadshow-augusta-me-may-11-2010-recap/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Shortening URLs With The bit.ly API Via ASP.NET</title>
		<link>https://www.dougv.com/2009/07/02/shortening-urls-with-the-bit-ly-api-via-asp-net/</link>
		<comments>https://www.dougv.com/2009/07/02/shortening-urls-with-the-bit-ly-api-via-asp-net/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 04:25:27 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[XPath]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2390</guid>
		<description><![CDATA[After yesterday&#8217;s post on using the Twitter API to post status updates on Twitter from an ASP.NET application, a follower of my client suggested using a URL shortening service to link to the articles headlines being posted as tweets. That was an excellent idea of which I should have thought in the first place. And [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/" rel="bookmark">Posting Status Updates (Tweets) To A Twitter Profile Via ASP.NET</a> (15)</li>
				<li><a href="https://www.dougv.com/2006/11/11/using-national-weather-service-xml-feeds-with-aspnet-adonet-and-xsl/" rel="bookmark">Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL</a> (12.6)</li>
				<li><a href="https://www.dougv.com/2008/08/21/displaying-an-image-stored-in-a-sql-server-database-on-an-aspnet-page-using-vbnet/" rel="bookmark">Displaying An Image Stored In A SQL Server Database On An ASP.NET Page Using VB.NET</a> (11.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>After yesterday&#8217;s post on <a href="http://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/">using the Twitter API to post status updates on Twitter from an ASP.NET application</a>, a follower of my client suggested using a URL shortening service to link to the articles headlines being posted as tweets.</p>
<p>That was an excellent idea of which I should have thought in the first place. And thanks to the extreme simplicity of the REST-like <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation">bit.ly API</a>, shortening URLs is as simple as sending a request URL laced with querystring variables.</p>
<p>So here is a quick and simple ASP.NET subroutine, written in VB.NET, to shorten URLs with the bit.ly API:</p>
<pre class="brush: vb; title: ; notranslate">
Sub BitlyIt(ByVal strUser As String, ByVal strAPIKey As String, ByVal strLongUrl As String)
	'This subroutine requires your page to have a label control named lblStatus

	'build URL to shorten method resource
	Dim strUri As New StringBuilder(&quot;http://api.bit.ly/shorten?&quot;)
	strUri.Append(&quot;version=2.0.1&quot;)
	'we want to get an XML response back from bit.ly, not the default JSON
	strUri.Append(&quot;&amp;format=xml&quot;)
	strUri.Append(&quot;&amp;longUrl=&quot;)
	strUri.Append(Server.HtmlEncode(strLongUrl))
	strUri.Append(&quot;&amp;login=&quot;)
	strUri.Append(Server.HTMLEncode(strUser))
	strUri.Append(&quot;&amp;apiKey=&quot;)
	strUri.Append(Server.HTMLEncode(strAPIKey))

	'create request for shorten resource
	Dim objRequest As HttpWebRequest = WebRequest.Create(strUri.ToString())
	'since we are passing querystring variables, our method is get
	objRequest.Method = &quot;GET&quot;
	'act as though we are sending a form
	objRequest.ContentType = &quot;application/x-www-form-urlencoded&quot;
	'don't wait for a 100 Continue HTTP response from bit.ly
	objRequest.ServicePoint.Expect100Continue = False
	'since we are using get, we need not send a request body; set content-length to 0
	objRequest.ContentLength = 0

	'we need to capture the XML being sent in response
	'read the response into a new XML document
	Dim objResponse As WebResponse = objRequest.GetResponse()
	Dim objXML As New XmlDocument()
	objXML.Load(objResponse.GetResponseStream())

	'the response will have three node values we're primarily interested in
	'the errorCode node will contain a numeric error code; 0 means success
	Dim nErrorCode As XmlNode = objXML.SelectSingleNode(&quot;//errorCode&quot;)
	'if there was an error, the errorMessage node will contain a user-friendly message useful for debugging
	Dim nErrorMsg As XmlNode = objXML.SelectSingleNode(&quot;//errorMessage&quot;)
	'if all went well, shortUrl will contain the full short URL created for our link
	Dim nShortUrl As XmlNode = objXML.SelectSingleNode(&quot;//shortUrl&quot;)

	'if we didn't get an errorCode value of 0, there was a problem; report the user-friendly message
	'on success, report the short URL for our resource
	If nErrorCode.InnerText &lt;&gt; &quot;0&quot; Then
		lblStatus.Text = &quot;Error returned. Code: &quot; &amp; nErrorCode.InnerText &amp; &quot;; Message: &quot; &amp; nErrorMsg.InnerText
	Else
		lblStatus.Text = nShortUrl.InnerText
	End If
End Sub
</pre>
<p><span id="more-2390"></span></p>
<p>Note the extensive similarity in shortening URLs with the bit.ly API to posting status updates with the Twitter <a href="http://en.wikipedia.org/wiki/Application_programming_interface">API</a>. That&#8217;s one of the many benefits of <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>; the basic approach to retrieving, adding, updating and deleting data tends to be similar for all RESTful applications.</p>
<p><strong>Aside:</strong> At some point, I plan to explain, in plain English, how REST works. It&#8217;s also worth noting that neither the Twitter nor bit.ly APIs are truly RESTful; that&#8217;s something I will explain in a future post. <em>End of aside.</em></p>
<p>A few notes about the bit.ly API and the code above:</p>
<ul>
<li>This code requires the <a href="http://msdn.microsoft.com/en-us/library/system.net.aspx">System.Net</a>, <a href="http://msdn.microsoft.com/en-us/library/system.io.aspx">System.IO</a> and <a href="http://msdn.microsoft.com/en-us/library/system.xml.aspx">System.Xml</a> namespaces. Chances are, if you built your Web application in Visual Studio, these namespaces are already referenced in your web.config file.</li>
<li>This code should work for ASP.NET versions 1.1 forward.</li>
<li>As the comment on Line 5 states, by default the bit.ly API will return its response as <a href="http://json.org/">JSON</a>. In the case of server-side programming, it&#8217;s easier to work with XML, so we need to explicitly instruct bit.ly to respond with XML.</li>
<li>I use a <a href="http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx">StringBuilder</a> to form the request URL in order to be very explicit about the components of the URL, especially in terms of from where its parts are drawn and what each part does. This is another case of <a href="http://www.dougv.com/2009/06/25/how-i-code-on-this-blog-elegance-vs-transparency/">choosing transparency over elegance</a>. You can replace the StringBuilder with string concatenation if you want.</li>
<li>To authenticate yourself in the bit.ly API, you can either send your bit.ly username and your API key as querystring variables, or use basic HTTP authentication. I am using the querystring variables method for simplicity&#8217;s sake, but it is rather less secure than basic authentication. This would be more of a concern if we were using an AJAX solution that exposed both your username and API key directly to end users.</li>
<li>Your bit.ly API key can be found on your bit.ly account page (log in to the Web site and click the Account link in the upper right-hand corner). Do not send your bit.ly password when you attempt to authenticate via querystring; use your API key only. Don&#8217;t replace apiKey with password, don&#8217;t substitute your password for the apiKey value, etc.</li>
<li>Your long URL must be a fully qualified URL. For example, don&#8217;t send server.com/page.html, send http://www.server.com/page.html.</li>
<li>We need not set any content for our request; we&#8217;ll be sending everything we need to send via the header. Thus, we set the ContentLength property for the request to 0, so that bit.ly doesn&#8217;t sit around waiting for data that&#8217;s never coming.</li>
<li>In order to get back from bit.ly the shortened URL it creates, we need to capture the XML response it sends. In my previous tutorial about the Twitter API, my code pretty much ignored the returned XML, because I simply assume the tweet went through. If you want to take a more pessimistic view of tweeting via the API, you can use the same methods I use here to access return values.</li>
<li>Thankfully, when bit.ly responds via XML to a shorten request, it always sends the nodes errorCode, errorMessage and shortUrl, regardless of the success of the request. Even more fortunate for us, there are only one of each of those nodes in every response. Therefore, we can use a combination of the the <a href="http://msdn.microsoft.com/en-us/library/fb63z0tw.aspx">SelectSingleNode</a> method, and the <a href="http://www.w3schools.com/XPath/xpath_syntax.asp">XPath selector //{node}</a> (where {node} is the local name of the node), to get the values contained in errorCode, errorMessage and shortUrl.</li>
<li>Once again, I am using a label with the ID of lblStatus to report the results of the request. You can change this code however you like to handle success or failure.</li>
<li>This time, I&#8217;m not using a <a href="http://msdn.microsoft.com/en-us/library/fk6t46tz.aspx">try-catch block</a> to see if there are problems with the request or response. You may find this code throws exceptions if you are sending bad querystring parameters, especially malformed longUrl parameters (for example, you send an incomplete URL as your longUrl value.) You can add a try-catch block if you want.</li>
</ul>
<p>If you have a user name of foobar, an API key of R_bar123456abcd90876poi, and a long URL of http://www.helloworld.com, you would call this subroutine out-of-the box thus:</p>
<pre class="brush: vb; title: ; notranslate">BitlyIt(&quot;foobar&quot;, &quot;R_bar123456abcd90876poi&quot;, &quot;http://www.helloworld.com&quot;)</pre>
<p>The same methodologies I discussed in the Twitter API post for using a button, letting people shorten URLs with their own accounts via a form, storing your bit.ly account information in your web.config file, etc. all can be applied to this solution; I&#8217;ll trust that most people can adapt those methodologies to this code, but if there are requests to clarify, I will visit those tasks in the comments.</p>
<p>Finally, like the Twitter API, the bit.ly API has a rate limit; in this case, no more than five simultaneous connections.</p>
<p>In theory, your server should disconnect from the bit.ly API servers immediately after making its shorten request, but it is possible your server&#8217;s requests will be kept alive for whatever reason, and the ASP.NET garbage collector won&#8217;t come by quickly enough to clean them up. That&#8217;s highly improbable, so rate limits shouldn&#8217;t be an issue here.</p>
<p>Even so, again I am not posting a working demo. I have tested this code and it does work. I distribute all code under the GNU GPL version 3.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/" rel="bookmark">Posting Status Updates (Tweets) To A Twitter Profile Via ASP.NET</a> (15)</li>
				<li><a href="https://www.dougv.com/2006/11/11/using-national-weather-service-xml-feeds-with-aspnet-adonet-and-xsl/" rel="bookmark">Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL</a> (12.6)</li>
				<li><a href="https://www.dougv.com/2008/08/21/displaying-an-image-stored-in-a-sql-server-database-on-an-aspnet-page-using-vbnet/" rel="bookmark">Displaying An Image Stored In A SQL Server Database On An ASP.NET Page Using VB.NET</a> (11.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a>, <a href="https://www.dougv.com/tag/xpath/" title="XPath" rel="tag">XPath</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/07/02/shortening-urls-with-the-bit-ly-api-via-asp-net/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Posting Status Updates (Tweets) To A Twitter Profile Via ASP.NET</title>
		<link>https://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/</link>
		<comments>https://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 05:03:24 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2379</guid>
		<description><![CDATA[Update, 16 Feb 2011: Please note that this routine will no longer work with the Twitter API. It is retained solely to prevent negative search engine rankings. I have a client that posts several news stories to its Web site every day. So it makes tremendous sense for them to post the headlines to Twitter [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/11/11/using-national-weather-service-xml-feeds-with-aspnet-adonet-and-xsl/" rel="bookmark">Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL</a> (12.9)</li>
				<li><a href="https://www.dougv.com/2008/08/21/displaying-an-image-stored-in-a-sql-server-database-on-an-aspnet-page-using-vbnet/" rel="bookmark">Displaying An Image Stored In A SQL Server Database On An ASP.NET Page Using VB.NET</a> (11.9)</li>
				<li><a href="https://www.dougv.com/2006/11/14/an-aspnet-subroutine-to-locally-store-the-national-weather-service-current-observations-xml-feeds/" rel="bookmark">An ASP.NET Subroutine To Locally Store The National Weather Service Current Observations XML Feeds</a> (11.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<div class="aside"><strong>Update, 16 Feb 2011: Please note that this routine will no longer work with the Twitter API. </strong>It is retained solely to prevent negative search engine rankings.</div>
<p>I have a client that posts several news stories to its Web site every day. So it makes tremendous sense for them to post the headlines to <a href="http://www.twitter.com/dougvcom">Twitter</a> as tweets, so that followers might be informed of breaking news, or just what&#8217;s new on the site.</p>
<p>The <a href="http://apiwiki.twitter.com/">Twitter API</a> makes <a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses%C2%A0update">posting status updates</a> (tweets) to Twitter as simple as invoking a <a href="http://msdn.microsoft.com/en-us/library/system.net.webrequest.aspx">WebRequest</a>. Unfortunately, most of the ASP.NET examples on the Web that aim to show you how to post status updates are either written in C#, have coding errors, simply will not work, or all three.</p>
<p>So here&#8217;s a simple VB.NET subroutine that will post tweets.</p>
<pre class="brush: vb; title: ; notranslate">
Sub TwitIt(ByVal strUser As String, ByVal strPass As String, ByVal strMessage As String)
	'this subroutine requires your ASP.NET page to have a label control with an ID of lblStatus

	'create post variable for tweet
	Dim strTweet As String = &quot;status=&quot; &amp; Server.HtmlEncode(strMessage)
	'convert post variable to byte array for transmission purposes
	Dim bRequest As Byte() = System.Text.Encoding.ASCII.GetBytes(strTweet)

	Try
		'create HttpWebRequest to status update API resource
		Dim objRequest As HttpWebRequest = WebRequest.Create(&quot;http://twitter.com/statuses/update.xml&quot;)
		'pass basic authentication credentials
		objRequest.Credentials = New NetworkCredential(strUser, strPass)
		'set method to post and pass request as a form
		objRequest.Method = &quot;POST&quot;
		objRequest.ContentType = &quot;application/x-www-form-urlencoded&quot;
		'tell the server it will not receive a 100 Continue HTTP response
		objRequest.ServicePoint.Expect100Continue = False
		'set content length of request
		objRequest.ContentLength = bRequest.Length

		'capture the stream (content) of the request
		Dim objStream As Stream = objRequest.GetRequestStream()
		'put the bytes into request
		objStream.Write(bRequest, 0, bRequest.Length)
		'close the stream to complete the request
		objStream.Close()

		'uncomment line below to report success
		'lblStatus.Text = &quot;Tweet sent!&quot;

		'You can also capture the XML response Twitter sends back
		'uncomment lines below to capture responses
		'Dim objResponse As WebResponse = objRequest.GetResponse()
		'Dim objReader As New StreamReader(objResponse.GetResponseStream())
		'lblStatus.Text = objReader.ReadToEnd()

	Catch ex As Exception
		'uncomment line below to report ASP.NET errors
		'lblStatus.Text = ex.Message
	End Try
End Sub
</pre>
<p><span id="more-2379"></span></p>
<p><strong>Update, July 19, 2009:</strong> I have moved the XML response block up into the try block, to avoid an error you will get if the API request returns an error. <a href="http://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/#comment-2606">Thanks to Rob for noting this issue</a>.</p>
<p>Some important notes about the code above:</p>
<ul>
<li>This code requires the <a href="http://msdn.microsoft.com/en-us/library/system.net.aspx">System.Net</a> and <a href="http://msdn.microsoft.com/en-us/library/system.io.aspx">System.IO</a> namespaces. Chances are strong, if you used Visual Studio to create your Web application, those namespaces are already referenced in your web.config file.</li>
<li>This code should work for ASP.NET versions 1.1 and later.</li>
<li>Twitter <a href="http://apiwiki.twitter.com/OAuth-FAQ">prefers you use the OAuth protocol</a> to authenticate your API requests and will eventually require it. However, they also say that they have not set a date at which they will no longer allow basic HTTP authentication requests. Since it&#8217;s far more concise, and generally secure enough, to use basic authentication, that&#8217;s what I am using here. Using <a href="http://oauth.net/">OAuth</a> to authenticate both requires you to get a key from Twitter and write about twice as much code.</li>
<li>The message you send is restricted to the standard length of a tweet (<a href="http://help.twitter.com/forums/10711/entries/15367">140 characters</a>).</li>
<li>You need to set the <a href="http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.expect100continue.aspx">Expect100Continue property</a> (at Line 16) to false because otherwise, the <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx">HttpWebRequest</a> will first send the request headers, then wait for a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">100 HTTP status code</a> from Twitter before proceeding with the body of the request (that is, the tweet). It will wait in vain; Twitter will not send a 100 Continue HTTP response; so Twitter will thus wait in vain for the rest of the message, unless you set Expect100Continue to false.</li>
<li>I have commented out several lines that set the text for a label ID&#8217;ed lblStatus. I always include such a label on my ASP.NET pages for debugging purposes. If you choose to uncomment those lines, remember to add a label to your ASP.NET page with the ID of lblStatus.</li>
<li>Every request to the XML version of the Twitter API will be answered with an XML reply that <a href="http://apiwiki.twitter.com/Return-Values">describes the results</a> of the request. If you are having problems, consider uncommenting the code at the end of the subroutine to have the XML document echoed back to your page (and remember to add a label with the ID of lblStatus to your page).</li>
</ul>
<p>This subroutine takes three arguments: Your Twitter username, your Twitter password, and the tweet. (Note that Twitter usernames and passwords are case-sensitive.) So, assuming your Twitter username is foobar, your password is barfoo, and your tweet is Hello World!, you would invoke the subroutine thus:</p>
<pre class="brush: vb; title: ; notranslate">TwitIt(&quot;foobar&quot;, &quot;barfoo&quot;, &quot;Hello World!&quot;)</pre>
<p>Suppose you want to have a form on your page that sends a user-supplied tweet to your Twitter account. The form would look like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;form ID=&quot;form1&quot; runat=&quot;server&quot;&gt;
	&lt;label&gt;Enter your Tweet: &lt;/label&gt;
	&lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbTweet&quot; Columns=&quot;50&quot; MaxLength=&quot;140&quot; /&gt;
	&lt;asp:RequiredFieldValidator runat=&quot;server&quot; ID=&quot;rfvTweet&quot; ControlToValidate=&quot;tbTweet&quot; ErrorMessage=&quot;Please provide a tweet!&quot; Display=&quot;Dynamic&quot; /&gt;
	&lt;br /&gt;
	&lt;asp:Button runat=&quot;server&quot; ID=&quot;btnSubmit&quot; OnClick=&quot;btnSubmit_click&quot; Text=&quot;Tweet!&quot; /&gt;
&lt;/form&gt;
</pre>
<p>Your OnClick handler would be:</p>
<pre class="brush: vb; title: ; notranslate">
Sub btnSubmit_click(ByVal Sender As Object, ByVal E As EventArgs)
	TwitIt(&quot;foobar&quot;, &quot;barfoo&quot;, tbTweet.Text)
End Sub
</pre>
<p>And you could also give people a gateway to post tweets to their own accounts:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;form ID=&quot;form1&quot; runat=&quot;server&quot;&gt;
	&lt;label&gt;Enter your Twitter Username: &lt;/label&gt;
	&lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbUser&quot; Columns=&quot;20&quot; MaxLength=&quot;20&quot; /&gt;
	&lt;asp:RequiredFieldValidator runat=&quot;server&quot; ID=&quot;rfvUser&quot; ControlToValidate=&quot;tbUser&quot; ErrorMessage=&quot;Please provide your user name!&quot; Display=&quot;Dynamic&quot; /&gt;
	&lt;br /&gt;
	&lt;label&gt;Enter your Twitter Password: &lt;/label&gt;
	&lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbPass&quot; TextMode=&quot;Password&quot; Columns=&quot;20&quot; MaxLength=&quot;20&quot; /&gt;
	&lt;asp:RequiredFieldValidator runat=&quot;server&quot; ID=&quot;rfvPass&quot; ControlToValidate=&quot;tbPass&quot; ErrorMessage=&quot;Please provide a password!&quot; Display=&quot;Dynamic&quot; /&gt;
	&lt;br /&gt;
	&lt;label&gt;Enter your Tweet: &lt;/label&gt;
	&lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbTweet&quot; Columns=&quot;50&quot; MaxLength=&quot;140&quot; /&gt;
	&lt;asp:RequiredFieldValidator runat=&quot;server&quot; ID=&quot;rfvTweet&quot; ControlToValidate=&quot;tbTweet&quot; ErrorMessage=&quot;Please provide a tweet!&quot; Display=&quot;Dynamic&quot; /&gt;
	&lt;br /&gt;
	&lt;asp:Button runat=&quot;server&quot; ID=&quot;btnSubmit&quot; OnClick=&quot;btnSubmit_click&quot; Text=&quot;Tweet!&quot; /&gt;
&lt;/form&gt;
</pre>
<pre class="brush: vb; title: ; notranslate">
Sub btnSubmit_click(ByVal Sender As Object, ByVal E As EventArgs)
	TwitIt(tbUser.Text, tbPass.Text, tbTweet.Text)
End Sub
</pre>
<p>It&#8217;s important to note that <a href="http://apiwiki.twitter.com/Rate-limiting">there are usage limits for the Twitter API</a>; if you run an open application that lets people post tweets from your Web site, there&#8217;s a strong chance your site will be blacklisted by Twitter for exceeding the API rate limits.</p>
<p>Or, you could also <a href="http://www.4guysfromrolla.com/articles/053102-1.aspx">add your Twitter username and password to your web.config file</a>, remove them as arguments to the TwitIt() function, and just pass along the tweet as an argument:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;appSettings&gt;
	&lt;add key=&quot;TwitterUsername&quot; value=&quot;foobar&quot; /&gt;
	&lt;add key=&quot;TwitterPassword&quot; value=&quot;barfoo&quot; /&gt;
&lt;/appSettings&gt;
</pre>
<pre class="brush: vb; title: ; notranslate">
Sub TwitIt(ByVal strMessage As String)
	Dim strTweet As String = &quot;status=&quot; &amp; Server.HtmlEncode(strMessage)
	Dim bRequest As Byte() = System.Text.Encoding.ASCII.GetBytes(strTweet)

	Dim objRequest As HttpWebRequest = WebRequest.Create(&quot;http://twitter.com/statuses/update.xml&quot;)
	objRequest.Credentials = New NetworkCredential(ConfigurationManager.AppSettings(&quot;TwitterUsername&quot;), ConfigurationManager.AppSettings(&quot;TwitterPassword&quot;))
	objRequest.Method = &quot;POST&quot;
	objRequest.ContentType = &quot;application/x-www-form-urlencoded&quot;
	objRequest.ServicePoint.Expect100Continue = False
	objRequest.ContentLength = bRequest.Length

	Dim objStream As Stream = objRequest.GetRequestStream()
	objStream.Write(bRequest, 0, bRequest.Length)
	objStream.Close()
End Sub
</pre>
<p>And that&#8217;s all there is to it. I don&#8217;t have a working example (because of the API rate limits) but I have tested this code and know it works. I distribute all code under the GNU GPL version 3.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/11/11/using-national-weather-service-xml-feeds-with-aspnet-adonet-and-xsl/" rel="bookmark">Using National Weather Service XML Feeds With ASP.NET, ADO.NET And XSL</a> (12.9)</li>
				<li><a href="https://www.dougv.com/2008/08/21/displaying-an-image-stored-in-a-sql-server-database-on-an-aspnet-page-using-vbnet/" rel="bookmark">Displaying An Image Stored In A SQL Server Database On An ASP.NET Page Using VB.NET</a> (11.9)</li>
				<li><a href="https://www.dougv.com/2006/11/14/an-aspnet-subroutine-to-locally-store-the-national-weather-service-current-observations-xml-feeds/" rel="bookmark">An ASP.NET Subroutine To Locally Store The National Weather Service Current Observations XML Feeds</a> (11.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/07/01/posting-status-updates-tweets-to-a-twitter-profile-via-asp-net/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Most Code Downloads Restored; Some Articles Deleted</title>
		<link>https://www.dougv.com/2009/06/03/most-code-downloads-restored-some-articles-deleted/</link>
		<comments>https://www.dougv.com/2009/06/03/most-code-downloads-restored-some-articles-deleted/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 15:47:10 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/2009/06/03/most-code-downloads-restored-some-articles-deleted/</guid>
		<description><![CDATA[I&#8217;ve restored about two-thirds of the code downloads on the site, especially for the most popular articles on this site. I&#8217;ve also had to delete some articles that were either based on images I can no longer locate or were, to be blunt, badly written. Bear with me; I should have the last of the [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2008/09/12/my-experience-getting-a-code-signing-certificate-from-comodo/" rel="bookmark">My Experience Getting A Code Signing Certificate From Comodo</a> (10.6)</li>
				<li><a href="https://www.dougv.com/2009/05/27/downloadable-code-images-gone/" rel="bookmark">Downloadable Code, Images Gone</a> (10.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve restored about two-thirds of the code downloads on the site, especially for the most popular articles on this site. I&#8217;ve also had to delete some articles that were either based on images I can no longer locate or were, to be blunt, badly written.</p>
<p>Bear with me; I should have the last of the code downloads reinstated over the next few days.</p>
<p>Also, be aware that certain trackback / inline links on this site may now be dead, as a result of the aforementioned post prunings.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2008/09/12/my-experience-getting-a-code-signing-certificate-from-comodo/" rel="bookmark">My Experience Getting A Code Signing Certificate From Comodo</a> (10.6)</li>
				<li><a href="https://www.dougv.com/2009/05/27/downloadable-code-images-gone/" rel="bookmark">Downloadable Code, Images Gone</a> (10.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/06/03/most-code-downloads-restored-some-articles-deleted/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Describing &#8216;Red&#8217; To A Blind Man: The Dilemma Of Ontology</title>
		<link>https://www.dougv.com/2008/09/03/describing-red-to-a-blind-man-the-dilemma-of-ontology/</link>
		<comments>https://www.dougv.com/2008/09/03/describing-red-to-a-blind-man-the-dilemma-of-ontology/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 03:40:45 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=875</guid>
		<description><![CDATA[Recently asked on Yahoo! Answers: How to map a keyword to a category? I have a bunch of general categories, such as: Games, Modeling, Business, Finance, etc. My question is, how can I take a keyword such as &#8220;Xbox 360&#8243; and automatically map it to a category such as &#8220;Games&#8221;? This is an easy example, [...]<div class="yarpp">
	<h5>Related Posts</h5>
		
No related posts.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Recently asked on Yahoo! Answers:</p>
<blockquote><p><a href="http://answers.yahoo.com/question/index?qid=20080903191752AAJ0gr8" target="_blank"><strong>How to map a keyword to a category?</strong></a><br />
I have a bunch of general categories, such as: Games, Modeling, Business, Finance, etc.</p>
<p>My question is, how can I take a keyword such as &#8220;Xbox 360&#8243; and automatically map it to a category such as &#8220;Games&#8221;? This is an easy example, and I did figure out ways to do this, but if I take a harder example such as &#8220;Tyra Banks&#8221;, I am unable to map it to a category of mine such as &#8220;Modeling&#8221; or &#8220;Tv Shows&#8221;.</p>
<p>I have been thinking of this for a very long time, and I can&#8217;t come up with a concrete solution. I have also searched the web and found nothing that would provide this service.</p>
<p>Any ideas?</p></blockquote>
<p>Basically, computers develop <a href="http://dictionary.reference.com/browse/semantic" target="_blank">semantic</a> understanding the same way we people do, only far less efficiently: Repetition of example. (In computer science, semantics are called <em><a href="http://en.wikipedia.org/wiki/Ontology_(information_science)" target="_blank">ontology</a></em>.)</p>
<p>The reason we are far more efficient is that we more easily create connections between things, and more quickly process those connections, than computers can manage.</p>
<p>For example, suppose I give you three categories: colloid, coagulant, polymer. Now, place &#8220;chocolate milk&#8221; into the proper category.</p>
<p><span id="more-875"></span></p>
<p>The problem for most people is, although they&#8217;re 100 percent aware of what chocolate milk is, they don&#8217;t know what colloids, coagulants or polymers are. (If you do, pretend you don&#8217;t and bear with me.)</p>
<p>Chocolate milk is a <a href="http://en.wikipedia.org/wiki/Colloid" target="_blank">colloid</a>; that is, a uniform distribution of solids in a liquid.</p>
<p><em>Colloid </em>is a word most people have never heard, so it has no meaning (semantic) associated with it in most people&#8217;s minds.</p>
<p>However, now that you know what a colloid is, you can very quickly come up with two more: Pepsi and coffee. They, too, are uniform distributions of solids inside a liquid base.</p>
<p>You can make this association because even if you don&#8217;t drink them regularly, you&#8217;ve at least seen Pepsi and coffee on thousands of occasions. You are intimately aware of their properties and you can easily define how they are similar.</p>
<p>So because you know literally everything there is to know about Pepsi, coffee and chocolate milk, when I tell you that chocolate milk is a colloid, you automatically know that Pepsi and coffee are, too.</p>
<p>However, you also know that chocolate milk, coffee and Pepsi are not exactly the same thing. For example, you know that Pepsi is most often served cold, coffee is most often served hot and chocolate milk, when not served cold, is often called &#8220;cocoa.&#8221;</p>
<p>These are the kinds of relationships that are brutally difficult for computers to make. And it is difficult for many programmers, such as the questioner above, to get computers to handle this depth of semantic, in large part, due to our own inability to forget everything we know about everything.</p>
<h4>Ontology Today</h4>
<p>The most common form of semantic understanding in computer programming is frequency. That is, &#8220;how many times does <em>Jesus</em> occur in the New Testament?&#8221; If it&#8217;s a lot, then clearly the New Testament is about Jesus.</p>
<p>This is the basic methodology employed by search engines: If the word or phrase you seek appears often, and in the context of grammatically correct sentences, on a Web page, then the Web page is probably about the word or phrase you entered; if the URL, title or description of the page contains that word or phrase, then it&#8217;s even more likely the page applies to your search term.</p>
<p>(There&#8217;s more to weighting a search query than that, but let&#8217;s keep it basic for simplicity&#8217;s sake.)</p>
<p>I&#8217;m no math whiz, so I can&#8217;t really explain (or fully understand) the methodologies used by, say, the full-text or natural-language query searches that most modern databases can perform.</p>
<p>The interesting thing is that as time has gone by, Google and Yahoo! are more likely to return Web pages that contain what you <em>meant </em>to find, rather than what you specifically asked to get; today&#8217;s search engine results are a far cry from the results you&#8217;d get not even five years ago.</p>
<p>Of course, some of that is better, faster machines and more experienced programmers. But a lot of it has to do with the copious amounts of data now available to make the connections between what I asked for, the links I got and what I wound up clicking.</p>
<p>In other words, because there are so many Web searches for so many different terms, and Google / Yahoo! can analyze what people click on once they get their results, they can &#8220;teach&#8221; their systems how to make better semantic connections between search words and what people meant when they used them.</p>
<h4>Forget Everything You Know, Then Ignore Everything You Learn</h4>
<p>The problem for the programmer is that almost always, any new leap into ontology begs the question.</p>
<p>That is, you can&#8217;t get past the fact that you already understand the relationship between the words you are trying to link. You can&#8217;t forget them or even ignore them, no matter how hard you try, because pretty much the only thing your brain does is semantics.</p>
<p>Because you know the relationship, trying to establish how to create it becomes exceedingly difficult. As is the case with our drinks example, relationships often become complex and depend on variables that are in flux or are matters of understanding or circumstances &#8212; understanding and circumstances that often are as difficult to define as the relationship you&#8217;re trying to create.</p>
<p>The benefit of having voluminous amounts of data, such as Yahoo! and Google have at their disposal, is they can provide initially simplistic relationships, toss them into the lake, see which ones swim, and narrow the next set of results by promoting the ones that swam best.</p>
<p>With small amounts of data, such as this questioner has at his disposal, it&#8217;s nearly impossible to instruct a computer on how to make a relationship. The amount of data you&#8217;d need to use, in order for the computer to be able to come up with anything approaching reliable results, would be so overwhelming as to entirely defeat the purpose of writing the algorithm in the first place.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<p>No related posts.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/google/" title="Google" rel="tag">Google</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2008/09/03/describing-red-to-a-blind-man-the-dilemma-of-ontology/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>An Open Letter To A Programming Noob</title>
		<link>https://www.dougv.com/2007/08/23/an-open-letter-to-a-programming-noob/</link>
		<comments>https://www.dougv.com/2007/08/23/an-open-letter-to-a-programming-noob/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 20:54:34 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Transact-SQL]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[data types]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[XSLT]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/2007/08/23/an-open-letter-to-a-programming-noob/</guid>
		<description><![CDATA[Recently received in my e-mail: Hi There Found your email on your blog via the contact me which is linked to on your [Yahoo! Answers] profile. I was curious as to what languages you program in as I am keen to get into programming and wanted any advise or recomendations for books. I have done [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/05/26/the-three-keys-to-successful-self-employment-in-programming-and-consulting-introduction/" rel="bookmark">The Three Keys To Successful Self-Employment In Programming And Consulting: Introduction</a> (18.1)</li>
				<li><a href="https://www.dougv.com/2007/01/20/a-new-approach-to-yahoo-answers/" rel="bookmark">A New Approach To Yahoo! Answers</a> (6)</li>
				<li><a href="https://www.dougv.com/2007/05/12/the-value-of-relational-databases-a-case-study/" rel="bookmark">The Value Of Relational Databases: A Case Study</a> (5.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Recently received in my e-mail:</p>
<blockquote><p>Hi There</p>
<p>Found your email on your blog via the contact me which is linked to on your <a href="http://answers.yahoo.com/my/profile?show=AA11434745">[Yahoo! Answers] profile</a>.</p>
<p>I was curious as to what languages you program in as I am keen to get into programming and wanted any advise or recomendations for books.</p>
<p>I have done quite a bit of visual basic 6 which I know is not OOP.</p>
<p>Would be good to either do vb 2005 or c++ or java</p>
<p>Thanks</p>
<p>Shane</p></blockquote>
<p>My response to this e-mail follows.</p>
<p><span id="more-270"></span></p>
<blockquote><p>I was curious as to what languages you program in as I am keen to get into programming and wanted any advise or recomendations for books.</p></blockquote>
<p>I program in several languages. Primarily I work in VB.NET but I also work in C#. In terms of scripting languages, I use PHP, JavaScript, Perl, ASP 3.0 and some ColdFusion. I know Transact-SQL and MySQL intimately and have some experience with PL/SQL. I know XHTML, XML and XSLT extensively.</p>
<p>In re: books for beginners, if you are a true noob &#8212; that is, you have little to no programming experience &#8212; I am a fan of the &#8220;For Dummies&#8221; series of books, which do an excellent job of walking you through the basics.</p>
<p>If you want to quickly learn how to use Microsoft Visual Studio to make programs in .NET, such as ASP.NET, VB.NET or C# &#8212; I am a big fan of the Step By Step series by Microsoft Press, such as Visual Basic .NET 2005 Step By Step. They focus on using Visual Studio to solve specific programming problems, such as working with databases, collecting user input via forms, etc.</p>
<p>You can see books I recommend at <a href="http://astore.amazon.com/dhvrm-20">my Amazon.com aStore</a>.</p>
<blockquote><p>I have done quite a bit of visual basic 6 which I know is not OOP.</p></blockquote>
<p>Actually, Visual Basic 6 is object-oriented. &#8220;Object-oriented&#8221; means many things, but to be really simple about it, it fundamentally means you create classes &#8212; aka objects &#8212; to accomplish programming goals.</p>
<p>While you can certainly write VB 6 programs as sequence-based code &#8212; like you write old-school ASP 3.0 or PHP programs &#8212; it is really designed to use objects. In fact, you could, in theory, write VB.NET programs as structured code, although it is harder to do since even the data types, such as strings, integers, etc., are designed to act like classes.</p>
<p>If you&#8217;d like more of an understanding of how classes / object-oriented programming work, check out this post on my blog:</p>
<p><a href="http://www.dougv.com/2006/12/22/objects-classes-explained-in-very-simple-terms/">http://www.dougv.com/2006/12/22/objects-classes-explained-in-very-simple-terms/</a></p>
<blockquote><p>Would be good to either do vb 2005 or c++ or java</p></blockquote>
<p>In re: which programming languages are &#8220;good&#8221; or &#8220;best,&#8221; there isn&#8217;t one. Each language has its strong points and its weak points. Which you choose should be a question of which you want to learn or find more comfortable, because there&#8217;s plenty of work to be had in all of them.</p>
<p>The only &#8220;required&#8221; language, as far as I am concerned, is SQL &#8212; no matter what programming language you learn, at some point you&#8217;re going to need a good understanding of SQL, since almost all applications come down to manipulating data somehow.</p>
<p>There are many variations of SQL &#8212; Transact-SQL (Microsoft), PL/SQL (Oracle), MySQL, PostGRE SQL, etc. &#8212; but if you understand ANSI SQL fairly well, then you can work out the quirks of each variation on the language easily.</p>
<p>I generally recommend to noobs that they at least give a crack at C++. I recommend that for several reasons:</p>
<ol>
<li>It&#8217;s by far the most common programming language, which means finding peers to help you with it is very easy.</li>
<li>If you decide you want to get a formal postsecondary education in programming, almost every school out there will start you in C++; if you start with it before you start your formal education, you&#8217;ll have a head-start on most people.</li>
<li>Because ANSI C was one of the first programming languages and was embraced early by both Microsoft and Unix / Linux, it&#8217;s served as a model for many other programming languages &#8212; including C++, C#, Java, JavaScript, PERL, PHP and more. If you can understand C++ and its concepts, you&#8217;ll find it easier to grasp most other programming languages.</li>
</ol>
<p>But again, what language you learn should be a matter of your personal choices and interests, not what other people think. You&#8217;re the person who will be doing the work, and your success will come from your happiness and confidence. If you don&#8217;t like a language or don&#8217;t feel competent using it, you won&#8217;t be successful.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/05/26/the-three-keys-to-successful-self-employment-in-programming-and-consulting-introduction/" rel="bookmark">The Three Keys To Successful Self-Employment In Programming And Consulting: Introduction</a> (18.1)</li>
				<li><a href="https://www.dougv.com/2007/01/20/a-new-approach-to-yahoo-answers/" rel="bookmark">A New Approach To Yahoo! Answers</a> (6)</li>
				<li><a href="https://www.dougv.com/2007/05/12/the-value-of-relational-databases-a-case-study/" rel="bookmark">The Value Of Relational Databases: A Case Study</a> (5.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/data-types/" title="data types" rel="tag">data types</a>, <a href="https://www.dougv.com/tag/linux/" title="Linux" rel="tag">Linux</a>, <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a>, <a href="https://www.dougv.com/tag/visual-studio/" title="Visual Studio" rel="tag">Visual Studio</a>, <a href="https://www.dougv.com/tag/xslt/" title="XSLT" rel="tag">XSLT</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2007/08/23/an-open-letter-to-a-programming-noob/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A New Approach To Yahoo! Answers</title>
		<link>https://www.dougv.com/2007/01/20/a-new-approach-to-yahoo-answers/</link>
		<comments>https://www.dougv.com/2007/01/20/a-new-approach-to-yahoo-answers/#comments</comments>
		<pubDate>Sat, 20 Jan 2007 05:23:57 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Help Desk]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/2007/01/20/a-new-approach-to-yahoo-answers/</guid>
		<description><![CDATA[Those of you who know me from Yahoo! Answers may be wondering why you don&#8217;t see quite as much of my answers around. As recently as last week, I was answering as many as 60 questions a day. Part of that is now that the holidays have passed, I&#8217;m busier with paying projects. But a [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/15/yahoo-answers-flash-badge-change-the-default-display-to-your-answers/" rel="bookmark">Yahoo! Answers Flash Badge: Change The Default Display To Your Answers</a> (28.7)</li>
				<li><a href="https://www.dougv.com/2006/12/17/death-taxes-and-bad-web-sites-for-review-on-yahoo-answers/" rel="bookmark">Death, Taxes And Bad Web Sites For Review On Yahoo! Answers</a> (22.7)</li>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (21.6)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Those of you who know me from <a href="http://answers.yahoo.com">Yahoo! Answers</a> may be wondering why you don&#8217;t see quite as much of my answers around. As recently as last week, I was answering as many as 60 questions a day.</p>
<p>Part of that is now that the holidays have passed, I&#8217;m busier with paying projects. But a bigger reason is that I&#8217;ve rethought which questions I am going to answer. It occurred to me recently that there&#8217;s a huge difference between quantity and quality, and in addition, I&#8217;m taking a bit more offense than I should with poorly worded questions, stupid questions and people who reward wrong answers with &#8220;Best Answer.&#8221;</p>
<p>I know full well when I answer a question whether the questioner even understands what he is asking, nonetheless the answer I give. And I know, even better, the cliche that one should never teach pigs to sing, because it wastes your time and annoys the pig.</p>
<p>I also know better than to answer when it&#8217;s not needed or counterproductive, and it occurs to me that not following my own common sense makes me a fool.</p>
<p><span id="more-122"></span></p>
<p>So, from here on out, I&#8217;m using these basic guidelines for Yahoo! Answers:</p>
<p><strong>If your question makes no sense whatsoever, I&#8217;m not going to try to figure out what you are talking about.</strong> And I&#8217;m not just referring to the surfeit of Indians trying to ask complex programming questions when they know all of five English words. I&#8217;m talking about questions that clearly indicate total confusion on a subject.</p>
<p>It&#8217;s one thing, for example, to call JavaScript &#8220;Java&#8221; or ask what &#8220;codes&#8221; you need to, say, get a certain recordset from a database. It&#8217;s quite another to ask, &#8220;<a href="http://answers.yahoo.com/question/index?qid=20070119115208AAqxzt8">Vb code for create database ADO with the help of coding help me plz.?</a>&#8220;, which, not coincidentally, is the question that, as I was answering it, made me realize I was on a fool&#8217;s errand and needed to rethink which questions I should answer.</p>
<p><strong>If a question already has a correct answer, I&#8217;ll thumbs-up the correct answer and move on.</strong> Nothing is more annoying, or potentially more confusing, than providing the same answer to a question that&#8217;s been answered correctly. More likely than not, the subtle differences between two right answers will only serve to confuse the questioner, and that&#8217;s contrary to the idea. So, if I see a good answer, I&#8217;ll mark it as such and move on to the next thing.</p>
<p><strong>If a questioner clearly cannot fathom a correct answer, I&#8217;ll skip answering it.</strong> This may come off as arrogant, but I do an exceptional job of explaining complex things in simple terms. But I can only dumb things down so far, or hold your hand so long; you have to have the capacity and desire to learn. Nothing pisses me off more than giving a correct answer that I&#8217;m certain can be understood, only to have the retard who asked the question, because he doesn&#8217;t even understand what he asked, nonetheless any of the answers he got, vote as Best Answer something that is utter nonsense.</p>
<p>For example, there&#8217;s <a href="http://answers.yahoo.com/question/index?qid=20070114072623AAAaBsu">this dipshit</a>, who gave Best Answer to someone who simply <a href="http://dictionary.reference.com/browse/filibuster">filibustered</a>, even though I gave him a <a href="http://www.dougv.com/2007/01/14/display-a-random-image-with-javascript-dom/trackback/">downloadable code and a full discourse</a>, just as he asked. There&#8217;s also <a href="http://answers.yahoo.com/question/index?qid=20070111111413AAjleu6">this idiot</a>, who voted for the guy who simply plagiarized my earlier answer, and got the parts he added to my answer wrong. And just to prove this is no anomaly, there&#8217;s <a href="http://answers.yahoo.com/question/?qid=20070109230943AA2Z7BM">this moron</a>, who gave Best Answer to a person who spewed anti-intellectual diarrhea all over the place.</p>
<p><strong>If you don&#8217;t speak English, or use <a href="http://en.wikipedia.org/wiki/Leet">1337</a> / <a href="http://en.wikipedia.org/wiki/StudlyCaps">StUdLyCaPs</a>, or otherwise prove yourself a functional illiterate, I&#8217;ll move on.</strong> If you cannot, or do not, make yourself understood when you are seeking help, you cannot, or will not, understand my answers.</p>
<p><strong>No more stupid questions (and yes, there <em>are</em> stupid questions).</strong> If your question could easily be answered with a simple search engine query, or by anyone who&#8217;s worked a computer for more than 30 seconds, I&#8217;ll move on. For example: Where can I find <a href="http://search.yahoo.com/search?p=free+message+boards">free message boards</a>? How do I change the background picture on my screen? Where can I find <a href="http://search.yahoo.com/search?p=dreamweaver+tutorials">tutorials for Dreamweaver</a>?</p>
<p><strong>No more non-programming questions.</strong> There are plenty of computer questions that aren&#8217;t related to programming but which are complicated. And there are hundreds of help desk people in the <a href="http://answers.yahoo.com/dir/?link=list&#038;sid=396545660">Computers &amp; Internet</a> section of Yahoo! Answers. They can handle questions about how to restore icons or what may be causing a given error. I&#8217;ll stick with what I know. There are also lots of people who can write basic HTML, JavaScript and SQL; I&#8217;ll start ignoring those questions, too.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/15/yahoo-answers-flash-badge-change-the-default-display-to-your-answers/" rel="bookmark">Yahoo! Answers Flash Badge: Change The Default Display To Your Answers</a> (28.7)</li>
				<li><a href="https://www.dougv.com/2006/12/17/death-taxes-and-bad-web-sites-for-review-on-yahoo-answers/" rel="bookmark">Death, Taxes And Bad Web Sites For Review On Yahoo! Answers</a> (22.7)</li>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (21.6)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2007/01/20/a-new-approach-to-yahoo-answers/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Stupid Web Site Tricks</title>
		<link>https://www.dougv.com/2007/01/14/stupid-web-site-tricks/</link>
		<comments>https://www.dougv.com/2007/01/14/stupid-web-site-tricks/#comments</comments>
		<pubDate>Sun, 14 Jan 2007 03:09:40 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/2007/01/14/stupid-web-site-tricks/</guid>
		<description><![CDATA[Recently asked on Yahoo! Answers: Is background music on websites to unprofessional? [snip; was a URL] that is my website I am working on for my uncle I was thinking about putting some background music on it (just a piano playin in background) is this a good idea or should I not do it? and [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (16.8)</li>
				<li><a href="https://www.dougv.com/2006/12/17/death-taxes-and-bad-web-sites-for-review-on-yahoo-answers/" rel="bookmark">Death, Taxes And Bad Web Sites For Review On Yahoo! Answers</a> (7.2)</li>
				<li><a href="https://www.dougv.com/2006/12/14/changing-css-styles-via-javascript-based-on-the-users-web-browser/" rel="bookmark">Changing CSS Styles Via JavaScript, Based On The User&#039;s Web Browser</a> (6)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Recently asked on Yahoo! Answers:</p>
<blockquote><p><strong><a href="http://answers.yahoo.com/question/index?qid=20070113153650AABqZMz">Is background music on websites to unprofessional?</a></strong></p>
<p><em>[snip; was a URL]</em></p>
<p>that is my website I am working on for my uncle<br />
I was thinking about putting some background music on it<br />
(just a piano playin in background)</p>
<p>is this a good idea or should I not do it?</p>
<p>and what changes can I make to the site to make it look better? what can I add, what should I take off? </p></blockquote>
<p>Which provides me with an excellent <a href="http://dictionary.reference.com/browse/segue">segue</a> to point out all the annoying crap people on Yahoo! Answers insist on putting into their Web sites. I&#8217;ve listed the annoyances in order, from worst to simply just offensive.</p>
<p>If you do any of the following on your Web site, your site is awful. If you do more than one, you should immediately remove your site altogether, because it&#8217;s a crime.</p>
<p><span id="more-117"></span></p>
<p><strong>Gizmos for the sake of having gizmos:</strong> If you want to add things to your Web site because you think your Web site is not interesting, maybe you should go do something or discover something interesting and put that on your site.</p>
<p>Because counters, games, flashing what-nots, chat, whatever, don&#8217;t make a Web site interesting and useful. <em>Saying something useful and interesting makes a Web site useful and interesting.</em></p>
<p><strong>A &#8220;splash&#8221; page, for any reason:</strong> I don&#8217;t care if your Web site is in 150 different languages, or you have 10 different versions depending on browser / Flash capability, or if you have the coolest logo ever designed. Splash pages are plain old stupid.</p>
<p>A splash page says one of the following:</p>
<ul>
<li>You haven&#8217;t bothered making a home page that tells me anything about your site. Thus, your site isn&#8217;t worth reading. Goodbye!</li>
<li>You&#8217;re far more interested in showing me some crappy Flash animation or logo than you are in telling me why I should waste any more time on your site. Goodbye!</li>
<li>You&#8217;re too damn lazy to properly program your Web site to determine a Web browser&#8217;s capabilities. Thus, all the gizmos I&#8217;m likely to run across on your site will be poorly programmed and crash my browser. Goodbye!</li>
</ul>
<p>Whatever the case, &#8220;splash page&#8221; translates as &#8220;stop sign.&#8221; If you use it, your site is crap.</p>
<p><strong>Flashing or moving text:</strong> The purpose behind a Web site is to say something. It&#8217;s harder to read text if it flashes or moves; worse, it makes the text next to whatever else is flashing or moving hard to read, as well. If your Web site has flashing or moving text, you&#8217;re wasting both our time.</p>
<p>By design, the HTML <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a> has elements that imply importance: H1 through H6. It also includes elements that set aside important parts of inline text: STRONG and EM. If you use those in the place of flashing or moving text, your site will index better with search engines.</p>
<p>Better yet, people won&#8217;t close their browser windows because your text is making them seasick.</p>
<p><strong>Embedded music or video files without a warning:</strong> You are a serious ass if you embed a background music file on your site without warning people, and not just because doing it chews up bandwidth. True, these days, most people have broadband, but some don&#8217;t, and it&#8217;s wrong to attack such users just because they refuse to leap into the 21st Century or move to civilization, where cheap broadband is plentiful.</p>
<p>Most people expect Web pages to be silent. If you don&#8217;t tell them you are about to break the silence with your polyphonic rendition of &#8220;<a href="http://en.wikipedia.org/wiki/The_Merry-Go-Round_Broke_Down">The Merry-Go-Round Broke Down</a>,&#8221; it&#8217;s going to come as a shock to them. And no matter how popular your audio clip is, I assure you, many, many people who visit your site are going to hate it.</p>
<p>It&#8217;s even worse when you embed an MPG or other video file, because those are even larger, taking even longer to download, and almost always are a waste of time.</p>
<p>If your video is any good, put it on <a href="http://www.youtube.com">YouTube</a> like a normal person does and embed the YouTube player on your site. It, at least, doesn&#8217;t start downloading until the person decides they want to view the video, and <a href="http://en.wikipedia.org/wiki/FLV">FLV</a> tends to be a more efficienct video compression than MPG or even AVI, making the video download and play faster.</p>
<p>Not only does that save you bandwidth, it makes it a lot more friendly for visitors.</p>
<p>Whatever you do, warn people <strong>before</strong> they run into media clips. If I opened a book and a 20-inch TV fell out of it and onto my foot, I&#8217;d be pissed. I have the same reaction when I run into unannounced video or audio on a Web site.</p>
<p>And while I&#8217;m at it, if you feed a video file off your Web site, such as an MPG, which isn&#8217;t in a <a href="http://en.wikipedia.org/wiki/List_of_streaming_media_systems">streaming media format</a>, you&#8217;re a double-jackass. I don&#8217;t have to turn my TV on at 4:30 p.m. to watch the 6 o&#8217;clock news; I shouldn&#8217;t have to wait 5 minutes for the stupid video of you and your friends imitating the OK Go treadmill dance to start playing, either.</p>
<p><strong>Meaningless <a href="http://www.adobe.com/flash">Flash</a>:</strong> Believe me, all your Flash animation is saying is, &#8220;I&#8217;ve learned enough Flash to waste your time and bandwidth, by animating some words and stock images into a 30-second loop that simply spits out meaningless slogans at best.&#8221; And I&#8217;m going to laugh at you if it takes 30 seconds for that animation to load.</p>
<p>Truth is, you don&#8217;t know enough about Flash and graphic design to use it well. I don&#8217;t know you from Adam and I can guarantee that&#8217;s the case. In the highly unlikely case I&#8217;m wrong, and you&#8217;ve put in the thousands of man-hours it takes to get good at both, you&#8217;ll still never find a circumstance where Flash was a better choice than vanilla HTML, JPGs and GIFs. I don&#8217;t know your client base from Eve, and I know that.</p>
<p>Here&#8217;s a tip: Don&#8217;t use Flash unless you are making a game or another interactive component. Here&#8217;s another tip: Even if you are making a game or another interactive component, don&#8217;t use Flash. Here&#8217;s a final tip: Flash sucks. Don&#8217;t use it, period.</p>
<p>One of the best bits of Web design advice I ever heard was this: <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.com%2F&#038;tag=dhvrm-20&#038;linkCode=ur2&#038;camp=1789&#038;creative=9325">Amazon.com</a> spends bucketloads of money every year to research what makes a Web site customer-friendly. If you don&#8217;t see it on Amazon.com, don&#8217;t do it.</p>
<p>You&#8217;ll find plenty of AJAX, XHTML, dynamically displayed layers and the like on Amazon.com. And you may even see Flash in a banner or used to display book page samples. But you won&#8217;t see a single Flash animation used for navigation, and especially not to simply &#8220;pretty things up&#8221;, <a href="http://dictionary.reference.com/browse/QED">QED</a>.</p>
<p><strong>Linking to non-HTML documents without warning:</strong> This is especially a problem with PDF files but also with Word documents, Excel spreadsheets and the like. Nothing is more annoying than being very close to finding the information I want, only to have the next link I click launch my copy of Acrobat 7 &#8212; which takes about two minutes to load and pretty much prevents me from doing anything else with my Web browser.</p>
<p>Sure, I could disable PDF reading in my browser. But I want to be able to read PDF documents in it. What I don&#8217;t want is to have some moron link to what I expect to be a Web page, so that I stumble upon PDFs unexpectedly.</p>
<p>It takes you all of 5 keystrokes to add (PDF) inside the hyperlinked text to your damn PDF document. Let me have a choice between viewing it now and downloading it. Seize my computer up with unexpected content types and I&#8217;ll never visit your crappy Web site again.</p>
<p><strong>Background images that aren&#8217;t simply small tiles:</strong> If you use an actual image as a background on a Web page, I have news for you: It&#8217;s 2007, and that crap is straight out of 1998. Don&#8217;t do it. It&#8217;s just distracting. Enough said.</p>
<p><strong>Animated GIFs:</strong> Those, too, are totally ghetto geek. Unless the animation does a better job of explaining something than words would do, you&#8217;re just distracting me from your message. The same is true of &#8230;</p>
<p><strong>Large, pointless images:</strong> Pictures may speak 1,000 words, but believe me, that scan of a black-velvet painting of a nearly naked warrior princess riding a winged unicorn is shouting, &#8220;You are a loser and an annoying ass.&#8221; Again, images should augment your site, not dictate it.</p>
<p><strong>Using depricated HTML <a href="http://www.w3.org/TR/html4/index/elements.html">elements</a> or <a href="http://www.w3.org/TR/html4/index/attributes.html">attributes</a>:</strong> If your site contains a single FONT, CENTER or U tag, or an &#8220;align&#8221; attribute in any text element, you&#8217;re a retard. Stop trying to learn HTML from Web pages written in 1996. Get a copy of <a href="http://www.amazon.com/gp/product/0764507516?ie=UTF8&#038;tag=dhvrm-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0764507516">XHTML for Dummies (With CD-ROM)</a><img src="http://www.assoc-amazon.com/e/ir?t=dhvrm-20&#038;l=as2&#038;o=1&#038;a=0764507516" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> and get up-to-date. It&#8217;s well worth the $20, and considering your woeful skill level if you&#8217;re still using those tags, probably your only hope for redemption.</p>
<p><strong>Manipulating the DOM for the sake of manipulating the DOM:</strong> I don&#8217;t want to see a bunch of stars following my cursor across the screen, or have things I&#8217;m not expecting to change suddenly do just that for no apparent reason, or have to deal with your nonsensical attempts to block me from right-clicking on your page.</p>
<p>Again, at best you&#8217;re simply annoying me. At worse, you&#8217;re encouraging me to leave your site immediately &#8212; after I read the source code and steal everything you didn&#8217;t want me to steal.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (16.8)</li>
				<li><a href="https://www.dougv.com/2006/12/17/death-taxes-and-bad-web-sites-for-review-on-yahoo-answers/" rel="bookmark">Death, Taxes And Bad Web Sites For Review On Yahoo! Answers</a> (7.2)</li>
				<li><a href="https://www.dougv.com/2006/12/14/changing-css-styles-via-javascript-based-on-the-users-web-browser/" rel="bookmark">Changing CSS Styles Via JavaScript, Based On The User&#039;s Web Browser</a> (6)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/rest/" title="REST" rel="tag">REST</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2007/01/14/stupid-web-site-tricks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

