<?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>Nathanael Jones &#187; General Programming</title>
	<atom:link href="http://nathanaeljones.com/category/general-programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://nathanaeljones.com</link>
	<description>Ramblings of a computer linguist</description>
	<lastBuildDate>Mon, 04 Jan 2010 21:12:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Performance killer: Disk I/O</title>
		<link>http://nathanaeljones.com/153/performance-killer-disk-io/</link>
		<comments>http://nathanaeljones.com/153/performance-killer-disk-io/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 11:44:05 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[General Programming]]></category>
		<category><![CDATA[computerlinguist.com]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=153</guid>
		<description><![CDATA[Many people think of "performance tuning" as optimizing loops, algorithms, and memory use. In truth, however, you don't get the huge performance gains from optimizing CPU and memory use (which is good), but from eliminating I/O calls.]]></description>
			<content:encoded><![CDATA[<p>Many people think of &#8220;performance tuning&#8221; as optimizing loops, algorithms, and memory use. In truth, however, you don&#8217;t get the huge performance gains from optimizing CPU and memory use (which is good), but from eliminating I/O calls.</p>
<p>Disk I/O is responsible for almost all slow websites and desktop applications. It&#8217;s true. Watch your CPU use next time you open a program, or your server is under load. CPUs aren&#8217;t the bottleneck anymore &#8211; your hard drive is. At the hardware level, the hard drive is the slowest component by an incredibly large factor. Today&#8217;s memory ranges between <a href="http://en.wikipedia.org/wiki/DDR2_SDRAM"> 3200 and 10400 MB/s</a>. In contrast, today&#8217;s desktop hard drive speeds average about 50 MB/s (Seagate 500GB), with high-end drives getting 85MB/s (WD 640, Seagate 1TB). If you&#8217;re looking at bandwidth, hard drives are 200-300 times slower. Bandwidth, though, isn&#8217;t the killer &#8211; it&#8217;s the latency. Few modern hard drives have latencies under 13 milliseconds &#8211; while memory latency is usually about 5 <em>nanoseconds</em> &#8211; 2,000 times faster.</p>
<p>You&#8217;re probably looking at these numbers and thinking, &#8220;13ms is quite fast enough for me, and my app is only dealing with small files&#8221;. However, I have a question: what other applications are using that drive? If you&#8217;re on a shared server, the odds are high that between 25 and 2500 ASP.NET apps are being run on the same drive.</p>
<p>CPU, bandwidth, and memory throttling is becoming more and more common on shared servers and virtualization systems, but practical disk throttling isn&#8217;t even on the horizon from what I can tell. Improper I/O usage from <em>any</em> app affects <em>everybody</em>.</p>
<p>Since hard drives are slow, pending operations go into a queue. So even if your app only needs a single byte of data from the hard drive, it still has to wait its turn. It&#8217;s quite common for disk operations to take several <em><strong>seconds</strong></em> on a shared server under heavy load. If any application on the server is paging to disk from exessive memory use, it can take several minutes, causing a timeout.</p>
<p>Realistic I/O performance is really hard to simulate in a development environment. On a dedicated development machine, disk queues are short, and response times are usually near the optimal 13ms, which tends to give software developers gravely incrorrect ideas about the performance characteristics of their application.</p>
<h2>Load test!</h2>
<p>A good way to acid test your code is to run it on a cheap, overloaded shared server. Webhost4life.com has $10/month plans that are excellent for this purpose. I&#8217;m actually using Webhost4life.com for this site, and while I/O calls consistently take around 1 second each, page views are decently quick since everything is in memory. I can&#8217;t seem to get more than 30-40KB/s bandwidth though, so I&#8217;m probably going to switch hosts soon.</p>
<p>Stress testing can also be accomplished with load testing tools like the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=e2c0585a-062a-439e-a67d-75a89aa36495&amp;displaylang=en">Web Application Stress Tool</a>. Getting realistic results often means multiplying user load by a factor of 1000 or more, since I/O speeds can vary by that much on a production server. So, if you want to handle 50 concurrent users gracefully, test with 50,000.</p>
<p>One good way to make sure your app can handle high load is to get your per-request time very low. There is an <a href="http://www.recommendedwebtools.com/index.php/594/test-your-website-loading-speed-with-lori-firefox-extension/">extension for Firefox</a> that provides TTFB (time-to-first-byte) information that will help you measure this. (Trace.axd is an invaluable tool here also). If requests complete in 13 milliseconds, the odds are good that you can handle 100 of those requests per second.</p>
<h2>Cache smart</h2>
<p>It&#8217;s not too hard to cache files in memory. Here&#8217;s one approach that uses ASP.NET&#8217;s built in caching system:</p>
<pre class="brush:c-sharp">namespace fbs.Filesystem
{
    /// &lt;summary&gt;
    /// Provides cached read access to small, frequently used files. Use carefully!
    //// Uses HostingEnvironment.Cache (same as app cache).
    /// &lt;/summary&gt;
    public static class CachedFileAccess
    {
        /// &lt;summary&gt;
        /// Retrieves the file from the cache, or from disk if neccessary. Exceptions from IO.File.ReadAllText are not caught.
        /// Make sure the file exists and can be accessed before attempting this function.
        /// &lt;/summary&gt;
        /// &lt;param name="file"&gt;Standard pathname (C:\..&lt;/param&gt;
        /// &lt;param name="encoding"&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static string ReadAllText(string file, Encoding encoding)
        {

            if (HostingEnvironment.Cache == null) throw new InvalidOperationException("HostingEnvironment.Cache is null");
            string key = "cached_file(" + encoding.EncodingName + ")_" + file.ToLowerInvariant().GetHashCode();

            string value = HostingEnvironment.Cache[key] as string;
            if (value == null)
            {
                value = System.IO.File.ReadAllText(file, encoding);
                HostingEnvironment.Cache.Add(key, value, new System.Web.Caching.CacheDependency(file),
                    System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Low,null);

            }
            return value;
        }
    }
}</pre>
<p>If you must do I/O, File.Exists and File.GetLastWriteTimeUtc are much faster that actually opening a file. The filesystem &#8216;tables&#8217; are <em>often</em> cached in memory, and therefore have much higher <em>average</em> performance.</p>
<p>Don&#8217;t do memory leaks. In-memory caching is good, but if you have a memory leak the app&#8217;s memory space will get moved to disk, effectively slowing all memory access down the hard disk speeds. Not good. And you&#8217;re going to kill everyone else on the same disk. Make sure there is a finite and reasonable limit to what will be cached (especially if you&#8217;re using static variables instead of the ASP.NET cache object).</p>
<h3>Asynchronous=good, synchronous=evil.</h3>
<p>In any application, asynchronous IO calls should be used whenever possible. There&#8217;s a reason that I/O and web service calls in well-built applcations are async &#8211; it is impossible to predict how long I/O operations will take. Any  hard drive operation can take seconds to minutes &#8211; and there is no way to insure a responsive experience to users unless you make sure all I/O calls are out-of-band.</p>
<p>One nice thing about the web is that HTTP request are by nature  async &#8211; so if you have any I/O calls that *must* be made, you can  do them with AJAX later instead of holding up the entire page while they execute.</p>
<h2>Databases are a Good Thing</h2>
<p>Databases are Good. Build the right indexes, and queries will be quick. Most engines cache as much data as possible in memory (usually indexes get priority caching), so a well-designed database will almost alwasy beat standard I/O.</p>
<h2>Hybrid approaches can get the best of both worlds</h2>
<p>Being able to edit your files on disk is really nice &#8211; it tempts people away from database-driven websites all the time. But &#8211; you can have both ease-of-use and performance. nathanaeljones.com can be completely managed through an FTP connection and Notepad, if needed. It&#8217;s nice to drag-and drop files when I need to upload a bunch. It&#8217;s nice to use VS when I want to do some tricky coding.</p>
<p>Every few minutes, a ~1.5 second syncronization routine does a quick GetLastWriteTimeUTC check on the .aspx files that start with an ID, and pushes any changes to the database. The database is read only &#8211; basically a cache of the filesystem. But it allows instant, flexible querying/searching of all the articles, and provides the best of both worlds.</p>
<p>I don&#8217;t edit files manually much anymore, although it does come in handy. Right now I&#8217;m using the web-based article editor to write this &#8211; most of my work occurs through my online ASP.NET markup editor. But for those who like the comfort of Dreamweaver or VS, they can edit their articles in WYSIWYWYG mode all day long <img src='http://nathanaeljones.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>It can be difficult to write a filesystem to database synchronization system properly &#8211; there are a lot of wrong ways to go about it. Done properly, it can scale up to at least 50,000 articles. The routine must be located on a separate thread, and must use a ReaderWriterLock to prevent reads while database is build batch updated with SqlBulkCopy calls. A single call is used to get the listing of .aspx files: System.IO.Directory.GetFiles(appRoot, &#8220;*.aspx&#8221;, System.IO.SearchOption.AllDirectories); A database call downloads the paths and last-modified dates from the database, and the two are cross-referenced to compile a list of created, moved, changed, and deleted files. These changes are then commited to the database using SqlBulkCopy, as well as being logged. Changed files are compared with the SQL copy to generate a Diff report for the log.</p>
<h2>Filesystem state</h2>
<p>Another factor in disk performance is the state of the filesystem. While filesystems are usually built using very smart algorithms, all algorithms slow down as they have to crunch more data. The more files you get on a disk, the slower file lookup and access becomes. I&#8217;ve compared identical 15k disks with no difference except the number of files, and the response time difference would <em>almost</em> make you suspect the one with 500,000 files to be a floppy drive.</p>
<h2>In conclusion</h2>
<p>Disk performance slightly increases each year and SSDs are promising, but physical disks never seem to catch up to our need for space and speed. I/O operations on shared or highly-active servers will probably be slow for many years to come.</p>
<p>Think carefully before you use System.IO, and make sure there aren&#8217;t any alternatives. Pretend you&#8217;re calling a web service each time you use the File class, and be kind to your users.</p>
<p>Say NO to IO</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/153/performance-killer-disk-io/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Query String</title>
		<link>http://nathanaeljones.com/118/the-query-string/</link>
		<comments>http://nathanaeljones.com/118/the-query-string/#comments</comments>
		<pubDate>Tue, 20 May 2008 18:10:46 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=118</guid>
		<description><![CDATA[The query string is handled differently from the rest of the virtual path. It is neither URL decoded or case-normalized before it reaches ASP.NET, although each name-value pair is URL decoded before being stored in the Request.QueryString collection.]]></description>
			<content:encoded><![CDATA[<p>The query string is handled differently from the rest of the virtual path. It is neither URL decoded or case-normalized before it reaches ASP.NET, although each name-value pair is URL decoded before being stored in the Request.QueryString collection.</p>
<p>For the query string to be parsed correctly, the delimiters ?, &amp;, and = <em>cannot</em> be percent-encoded. Both names and values in the Request.QueryString collection go through exactly one URLDecode pass. Other properties in the Request class include the querystring in its original, URLEncoded form (if they were originally URL (percent) encoded).</p>
<p>Also, any strings that aren&#8217;t parsed correctly are added to Request.QueryString[null] in comma-delimited format. (You can also access them as a string[] array using Request.QueryString.GetValues(null)). The NameValueCollection class isn&#8217;t a string-to-string dictionary. It&#8217;s more like an informal string-to-string[] dictionary. When you set a value like nvc["thiskey"]=&#8221;thisvalue&#8221; , you are in overwrite mode. When you use nvc.add(&#8220;thiskey&#8221;,&#8221;thisvalue&#8221;), you are in append mode. Calling nvc.add(&#8220;thiskey&#8221;,&#8221;firstvalue&#8221;), then nvc.add(&#8220;thiskey&#8221;,&#8221;lastvalue&#8221;) will leave nvc["thiskey"] == &#8220;firstvalue,lastvalue&#8221;.</p>
<h3>Related links</h3>
<ul class="list">
<li><a href="~/10941">URI Design</a></li>
<li><a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier">Wikipedia: Uniform Resource Identifier</a></li>
<li><a href="http://en.wikipedia.org/wiki/URL_normalization">Wikipedia: URL Normalization</a></li>
<li><a href="http://en.wikipedia.org/wiki/Percent-encoding ">Wikipedia: Percent encoding</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/118/the-query-string/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing URIs</title>
		<link>http://nathanaeljones.com/99/designing-uris/</link>
		<comments>http://nathanaeljones.com/99/designing-uris/#comments</comments>
		<pubDate>Fri, 09 May 2008 00:10:13 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=99</guid>
		<description><![CDATA[One of the most critical steps in designing a web site is choosing your URI structure for the site. Clean, friendly URIs make visitors more comfortable and help them keep track of where they are on the site,]]></description>
			<content:encoded><![CDATA[<p><!-- #content ul{ list-style-type:disc; padding-left:25px; } span.path{color:red;} h2{ margin-bottom:1.5em; margin-top:2em; } h3{ margin-bottom:.4em; margin-top:1.2em; } div.note{ padding:15px; border:1px solid #94A83F;</p>
<p>color:#505050; background-color:#e4e4e4; margin-top:.8em; margin-bottom:.8em; } .noteBoxRight{ width:200px; padding:10px; float:right; } .pathPart{ color:red; } h1.spaced{ margin-top:4em; margin-bottom:2em; } .codeBox{ line-height:1.1em; }</p>
<p>--></p>
<p>ASP.NET is essentially an advanced request-processing framework.<br />
Naturally, the URI is the most important part of any request (or should be).<br />
URIs should be well designed, and should <strong>represent the requested content accurately and succinctly</strong>.<br />
Unfortunately, they are frequently misused, which causes browsers, users,<br />
and search engines no end of trouble.</p>
<div class="noteBoxRight">Although you can&#8217;t change the main portion of the URI without reloading the page, you can modify the <a href="http://en.wikipedia.org/wiki/Fragment_identifier">fragment</a> to your heart&#8217;s content with Javascript. Adobe has released a <a href="http://labs.adobe.com/wiki/index.php/Flex_3:Feature_Introductions:_Deep_Linking">BrowserManager class that makes &#8220;deep linking&#8221; easier</a>, and vastly improves the <em>user</em>&#8217;s experience on all-flash sites.</div>
<p>Some misuse URIs by making them too generic;<br />
some sites have everything on the home page.<br />
Flash, AJAX, and frames are the biggest culprits here,<br />
as they are capable of making big changes to the current content of the page without affecting the address bar.<br />
Users of this type of site are frustrated because if they bookmark a buried page in the site,<br />
it only records the address of the home page.<br />
The back button also betrays them &#8211; it doesn&#8217;t undo their actions anymore,<br />
but plops them completely off the site.</p>
<p>Search engines dislike these sites because either (1) they can&#8217;t access buried content due to its form<br />
(JavaScript or Flash) or (2) they can access it, but all keywords are diluted from the massive amount<br />
of content available on one page.</p>
<p>Some developers take the misuse to the opposite end.<br />
The feel that the address bar is the <em>perfect</em> place to store all variables, interface state data,<br />
and user preferences. They, too, cause problems for both users and search engines.<br />
Users bookmarking or e-mailing such links often find that they no longer work after their session has expired,<br />
or after a change was made on the site.<br />
Their length and lack of simplicity also makes them hard to understand,<br />
as many users depend on the address bar to understand where they are located on the site. URLs longer than 80 characters are also a pain to e-mail. Many e-mail clients will break the URL in half, making it unusable.</p>
<p>Search engines find these type confusing, because they see (and rank) each unique URI as a separate page, and dilute ranking accordingly.</p>
<h2>So, you ask, what makes a good URI?</h2>
<ul>
<li>It should be as short as possible. Don&#8217;t sacrifice consistency or obviousness, but be brief.</li>
<li>Organize and name things logically. ASP.NET isn&#8217;t always helpful in keeping a clean structure,<br />
so I highly recommend that you use a URL rewriting module. <a href="http://www.useit.com/alertbox/990321.html">URIs should be &#8216;hackable&#8217;</a>.</li>
<li>URIs should be deterministic.
<ul>
<li>No two URIs should ever display the same page</li>
<li>The same URI should always display the same content.</li>
</ul>
</li>
<li>The query string should only contain data that AFFECTS THE QUERY.<br />
If it doesn&#8217;t describe the content, it doesn&#8217;t belong. Keep the <em>query string</em> for queries, please.</li>
<li>
<div class="noteBoxRight">Tip: Don&#8217;t try to spam URLs with keywords.<br />
Density algorithms are applied here, also. As with page titles, pick 1 keyword and stick with it.</div>
<p>The URI path should not rely on cryptic or numerical identifiers.<br />
If it does, it should also provide a human-readable title.<br />
It&#8217;s really nice to be able to look at a URL and guess what it contains -<br />
especially when you have a long list of them.<br />
As a bonus, search engines absolutely love URIs that match keywords.</li>
</ul>
<p>Further reading (by Tim Berners-Lee):<br />
<a href="http://www.w3.org/Provider/Style/URI">http://www.w3.org/Provider/Style/URI</a>.</p>
<p>I strongly suggest that all ASP.NET projects use some kind of URL rewriting library, such as <a href="http://www.urlrewriting.net/149/en/home.html">UrlRewritingNet</a>. Even if you only need a single rewrite, I still recommend using a library instead of trying to do it yourself. UrlRewritingNet helps you overcome the bugs in the framework seamlessly.</p>
<h3>Bad examples:</h3>
<ul>
<li>/Default.aspx?tabid=3</li>
<li>/Products/ShowProduct.aspx?prodid=4982</li>
<li>/showblog.aspx?articleid=98</li>
</ul>
<h3>Better examples:</h3>
<ul>
<li>/Default.aspx?tabid=3&amp;title=ContactUs</li>
<li>/Products/ShowProduct.aspx?id=4982&amp;product=Nokia_Wall_Adpater_12V</li>
<li>/showblog.aspx?articleid=98&amp;title= Why_you_should_never_concatenate_SQL_commands</li>
</ul>
<h3>Even better:</h3>
<ul>
<li>/contact/</li>
<li>/products/4982_Nokia_Wall_Adapter_12v</li>
<li>/blog/98_Why_you_should_never_concatenate_SQL_commands</li>
</ul>
<h2>WWW</h2>
<p>The famous &#8220;www&#8221; prefix is actually pointless. You can still have <strong>ftp</strong>, <strong>mail</strong>, and <strong>smtp</strong> subdomains without forcing your website to use <strong>www</strong>. The <strong>www</strong> convention came into being since servers were typically named after their role, and HTTP was just starting out.</p>
<p>Since web browsers only speak HTTP, you should really point your second-level domain (example.com) directly to your web server. Realize that some search engines will index <strong>www.example.com</strong> and <strong>example.com</strong> separately, since they are different locations. To prevent SSL cert and cross-domain flakiness in Flash, you should standardize on one or the other. You can force this by checking for www in Global.asax, and calling Response.Redirect() with the &#8220;fixed&#8221; version of the requested URI.</p>
<h1 class="spaced">URIs in the HTTP  protocol</h1>
<p><strong>Let&#8217;s look at how URI is sent to the server using HTTP</strong> Here is a basic GET request. The first line consists of the <strong>HTTP method,<br />
followed by a root-relative path, then the protocol version</strong>. The subsequent lines contain the header collection,<br />
in the form of simple <strong>name-colon-value pairs</strong>.<br />
<strong>The two parts of the URI here are the path (/blog?page=2), and the HOST-header (youngfoundations.org).</strong><br />
We know that the scheme is probably &#8220;http&#8221; since we are communication using the HTTP protocol.<br />
IIS tells us which port the request arrived on, so between the pieces we can reconstruct the original URI somewhat accurately.</p>
<div class="noteBoxRight">Note: there are LOTS of schemes out there that use the HTTP protocol, like firefoxurl://, etc.</div>
<div class="noteBoxRight">Note: The HOST header is important, since some servers host dozens of domains,<br />
and this allows IIS to forward the request to the appropriate application in shared hosting situations.<br />
Multiple domains (hostnames) can be pointed to a single application.</div>
<p>The path and the query are divided by the first question mark.</p>
<h2>GET Request</h2>
<div class="codeBox prewrap">GET <strong>/blog?page=2</strong> HTTP/1.1[CRLF]<br />
Host: <strong>youngfoundations.org</strong>[CRLF]<br />
Connection: close[CRLF]<br />
Accept-Encoding: gzip[CRLF]</p>
<p>Accept: text/xml,application/xml,application/xhtml+xml,text/html; q=0.9,text/plain; q=0.8,image/png,*/*;q=0.5[CRLF]<br />
Accept-Language: en-us,en;q=0.5[CRLF]<br />
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7[CRLF]<br />
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.5; .NET CLR 2.0.50727) Gecko/20070713 Firefox/2.0.0.5 Web-Sniffer/1.0.24[CRLF]<br />
Referer: http://web-sniffer.net/[CRLF]</p></div>
<p>The client can send content with <em>any</em> request, although it is typically sent with the POST method.<br />
The header collection is separated from the request body by the character sequence [CRLF][CRLF] (2 newlines).<br />
The content in the request body is described by the <strong>content-type</strong> and <strong>content-length</strong> HTTP headers.</p>
<h2>POST Request</h2>
<div class="codeBox prewrap">POST <strong>/blog</strong> HTTP/1.1[CRLF]<br />
Host: <strong>youngfoundations.org</strong>[CRLF]<br />
Connection: close[CRLF]<br />
Accept-Encoding: gzip[CRLF]<br />
Accept: text/xml,application/xml,application/xhtml+xml,text/html; q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5[CRLF]<br />
Accept-Language: en-us,en;q=0.5[CRLF]<br />
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7[CRLF]<br />
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.5; .NET CLR 2.0.50727) Gecko/20070713 Firefox/2.0.0.5 Web-Sniffer/1.0.24[CRLF]<br />
Referer: http://web-sniffer.net/[CRLF]<br />
Content-type: <strong>text/html; charset=utf-8</strong> [CRLF]<br />
Content-length: <strong>19</strong>[CRLF]<br />
[CRLF]<br />
Sample content body</div>
<h2>Response</h2>
<p>The HTTP response generated by your ASP.NET application looks slightly different that the request that prompted it.<br />
The general format remains, but the first line is now [HTTP Version]   [Status-code] [Status code description].<br />
<a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">Http status codes</a> are very important, but are beyond the scope of this article.</p>
<div class="codeBox prewrap">HTTP/1.1 301 Moved Permanently [CRLF]<br />
Connection: close [CRLF]<br />
Date:Fri, 03 Aug 2007 00:36:57 GMT [CRLF]<br />
Server:Microsoft-IIS/6.0 [CRLF]<br />
X-Powered-By:ASP.NET [CRLF]<br />
Location:http://www.microsoft.com [CRLF]<br />
Content-Length:31 [CRLF]<br />
Content-Type:text/html [CRLF]<br />
Set-Cookie:ASPSESSIONIDSSSBDQAT=PIJAGJDBFFLFAALAJDCGBAMI; path=/CRLFCache-control:private [CRLF]<br />
[crlf]<br />
[Content-body]</div>
<p>Important note: If you have multiple domains pointing to one website,<br />
make sure they are all 301 redirected to precisely one host name.<br />
Otherwise you will sabotage your search engine placement by (1) diluting your page rank, and<br />
(2) being penalized for duplicate content.</p>
<h1 class="spaced">URIs versus URLs</h1>
<p>The term URL (Uniform Resource Locator) has been considered obsolete by w3c for a long time.<br />
In its place stands the URI (the Uniform Resource Identifier).<br />
Strictly speaking, a URL must  provide <em>all</em> of the information required to located and retrieve a resource,<br />
while a URI is only required to identify it in relation to the current context.<br />
Thus, a URL is a URI that &#8220;in addition to identifying a resource, [provides] a means of locating the resource<br />
by describing its primary access mechanism (e.g., its network &#8216;location&#8217;).&#8221;. Most people aren&#8217;t aware of the difference, and use them interchangeably.</p>
<dl>
<dt><strong>For example, the following URI is also a URL:</strong></dt>
<dd>
<ul>
<li>http://www.mysite.com:54321/ folder/virtualfolder/default.aspx? param1=thisisatest&amp;param2=test2</li>
</ul>
</dd>
<dt><strong>However, these are not:</strong></dt>
<dd>
<ul>
<li>../css/shared.css  [URI relative to the location of the parent document]</li>
<li>/images/banner.jpg [URI relative to the current network location (usually termed 'absolute')]</li>
<li>Logo.gif [URI relative to the location of the parent document.]</li>
<li> #requirements [URI fragment relative to current document.]</li>
</ul>
</dd>
</dl>
<h3>Fragments</h3>
<p>Fragments describe a section, place, or entity in the current document.<br />
In HTML, they usually refer to a certain anchor tag (by name or ID).<br />
The window is usually scrolled to the location of the anchor tag.<br />
Fragments are never sent to the server computer, and only function as a display instruction to the client.<br />
If a fragment isn&#8217;t understood, it is ignored.<br />
Fragments are pretty much free-form.</p>
<p>If the current document is <strong>http://mysite.com/home.html</strong> and a link to<br />
<strong>http://mysite.com/home.html#part3</strong> is clicked, the browser (or user-agent),<br />
is not supposed to ask the server for http://mysite.com/home.html again, but older clients may.<br />
Relative fragments like <strong>#part3</strong> are handled more reliably.</p>
<p><strong>Now let us dissect the following URL:</strong></p>
<p>http://www.mysite.com:54321/folder/virtualfolder/default.aspx? param1=thisisatest&amp;param2=test2</p>
<p>http  The scheme (protocol).  The protocol determines how the client should talk to the server (basically the language, or grammar).</p>
<p>www.mysite.com The computer the resource is located on (DNS, WINS, or IP Address)</p>
<p>:54321 The port number to communicate with on the computer.</p>
<p>Instead of trying to sort out incoming packets and route them to the right application on the server computer, ports are used.<br />
Certain default ports are assumed for some protocols.<br />
Http requests are sent to port 80 by default.<br />
Https requests are sent to port 443, and FTP requests are sent to port 21.<br />
If an application is not listening on that port (or the request packets are blocked by a firewall), no response will be given.</p>
<p>Additional sorting is sometimes performed, as in the case of WCF (.NET 3.0) port sharing,<br />
or when multiple sites are hosted on a single server. When an HTTP request is sent to a server,<br />
it is accompanied by the original hostname from the address bar. An unlimited number of DNS (Domain Name System)<br />
addresses can point to a single computer, which is convenient for web hosting providers. IIS (Internet Information Services)<br />
can be configured to look at this host header, and forward the request to whichever site is configured to receive requests for<br />
that particular hostname (DNS address).</p>
<p>For information about DNS, read <a href="http://en.wikipedia.org/wiki/Domain_name_system">http://en.wikipedia.org/wiki/Domain_name_system</a>.</p>
<h1 class="spaced">Super-simplified view of DNS</h1>
<p>DNS addresses are hierarchical, and levels (domains) are separated by a period.<br />
Domains progress from most specific to least specific.</p>
<p>For example, in resolving www.mysite.com, the following steps would be taken:</p>
<ul class="list">
<li>Ask computer &#8216;COM&#8217; where computer &#8216;MYSITE&#8217; is at (what its IP address is).</li>
<li>Ask computer MYSITE where computer &#8216;WWW&#8217; is at.</li>
</ul>
<p>DNS is used for a whole lot more that just web browsing,<br />
so the company at mysite.com might have a whole bunch of computers, such as ftp.mysite.com, mail.mysite.com, pop.mysite.com,<br />
telnet.mysite.com, as well as www.mysite.com.<br />
WWW usually points to the web server for the company.<br />
Please note, however that the WWW part is completely unnecessary,<br />
and is just a commonly followed convention.</p>
<p>Note: In www.mysite.com, &#8220;com&#8221; is a TLD (Top-level domain),<br />
and &#8220;mysite&#8221; is a SLD (Second-level domain)</p>
<p>SLDs usually cost a registration fee, as the poor owner of the &#8220;COM&#8221; computer has tremendous bandwidth bills.<br />
Third-level domains can be freely created if the parent SLD is under your control.</p>
<p>One of the most critical steps in designing a web site is choosing your URI structure for the site. Clean, friendly URIs make visitors more comfortable and help them keep track of where they are on the site. Short URLs don&#8217;t get wrapped as badly, are easier to type, and just look nicer.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/99/designing-uris/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
