<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.encosia.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Encosia</title>
	
	<link>http://encosia.com</link>
	<description>ASP.NET and AJAX code, ideas, and examples.</description>
	<lastBuildDate>Sun, 29 Apr 2012 21:35:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.encosia.com/Encosia" /><feedburner:info uri="encosia" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><meta xmlns="http://pipes.yahoo.com" name="pipes" content="noprocess" /><feedburner:emailServiceId>Encosia</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.encosia.com/Encosia" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.encosia.com%2FEncosia" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><item>
		<title>REST vs. RPC in ASP.NET Web API? Who cares; it does both.</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/F30kspI4CFo/</link>
		<comments>http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 16:32:04 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web API]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1333</guid>
		<description><![CDATA[It&#8217;s probably an understatement to say that ASP.NET Web API has sparked a bit of debate about RESTful design lately. Web API&#8217;s new features like content negotiation, flexible media formatters, and improved JSON formatter are great, but they&#8217;ve been presented as features that are tied to the REST paradigm. That may seem troubling if you&#8217;re [...]
Related posts:<ol>
<li><a href='http://encosia.com/databinding-class-data/' rel='bookmark' title='Databinding Class Data'>Databinding Class Data</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s probably an understatement to say that <a href="http://codebetter.com/glennblock/2012/02/28/why-are-there-2-controllers-in-the-asp-net-web-api-contactmanager-example-rest-has-nothing-to-with-it-2/" target="_blank">ASP.NET Web API has sparked a bit of debate about RESTful design</a> lately.</p>
<p>Web API&#8217;s new features like content negotiation, flexible media formatters, and <a href="http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/">improved JSON formatter</a> are great, but they&#8217;ve been presented as features that are tied to the REST paradigm. That may seem troubling if you&#8217;re more accustomed to .NET&#8217;s RPC endpoints like ASMX, WCF, and even the way ASP.NET MVC controller actions are often used as a makeshift API.</p>
<p>A couple months after the new incarnation of Web API was announced, I&#8217;m still seeing a lot of confusion and unhappiness about Web API&#8217;s apparent push toward REST. However, what almost everyone has overlooked so far is that <strong>Web API supports RPC just as well as REST</strong>.</p>
<h3>Over-simplifying the difference between REST and RPC</h3>
<p>When I say REST, I don&#8217;t mean a peaceful afternoon napping in a hammock by the beach, but <a href="http://en.wikipedia.org/wiki/Representational_state_transfer" target="_blank" rel="nofollow">Representational State Transfer</a>. A RESTful API exposes its data as resources (or nouns) at <a href="http://ajaxian.com/archives/uri-vs-url-whats-the-difference" target="_blank">URI</a>s that clients interact with via HTTP methods like GET and POST (or verbs).</p>
<p>On the other hand, <a href="http://en.wikipedia.org/wiki/Remote_procedure_call" target="_blank" rel="nofollow">remote procedure call</a> (RPC) refers an API style where endpoints perform arbitrary actions, not necessarily tied to a particular resource. Typically, RPC service methods combine the noun and verb in one method name (e.g. GetPosts or SendInvoice). If you&#8217;re using ASMX or WCF today, you&#8217;re probably using the RPC approach.</p>
<p>In the context of ASP.NET Web API, the key distinction between REST and RPC is that in a RESTful approach your API consumers interact with public methods corresponding to HTTP verbs (e.g. <code>Get()</code> or <code>Delete(int Id)</code>). If a method doesn&#8217;t map to an HTTP verb, it doesn&#8217;t fit into a RESTful API.</p>
<h3>ASP.NET Web API routing basics</h3>
<p>Part of ASP.NET Web API&#8217;s magic is that it automatically routes requests to your API methods by convention, matching the request&#8217;s HTTP verb to a correspondingly named method in your API class.</p>
<p>For example, this default routing setup in the ASP.NET MVC 4 project template:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">routes.<span style="color: #0000FF;">MapHttpRoute</span><span style="color: #000000;">&#40;</span>
  name<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;DefaultApi&quot;</span>,
  routeTemplate<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;api/{controller}/{id}&quot;</span>,
  defaults<span style="color: #008000;">:</span> <span style="color: #008000;">new</span> <span style="color: #000000;">&#123;</span> id <span style="color: #008000;">=</span> RouteParameter.<span style="color: #0000FF;">Optional</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Means that you could write a class like this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyApiController<span style="color: #008000;">:</span> ApiController <span style="color: #000000;">&#123;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Get<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #666666;">&quot;Hello World&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>And then access that <code>Get()</code> method via HTTP by making a GET request to <code>/api/myapi</code>. Similarly, HTTP requests using the POST, PUT, and DELETE verbs would execute methods with names matching those verbs too.</p>
<h3>No coloring outside the lines</h3>
<p>That automatic RESTful routing is handy, but what if you wanted to add a method that doesn&#8217;t correspond to an HTTP verb, like <a href="http://linguapragma.com/blog/2012/04/foo-bar-and-baz-not-having-it/" target="_blank">good &#8216;ol FooBar</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyApiController<span style="color: #008000;">:</span> ApiController <span style="color: #000000;">&#123;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Get<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #666666;">&quot;Hello World&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #000000;">&#125;</span>
&nbsp;
  <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> FooBar<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #666666;">&quot;FooBar&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Confusingly enough, a GET request to <code>/api/myapi/foobar</code> returns <em>Hello World</em> instead of <em>FooBar</em>. The reason for that is because our default Web API route sends that request to MyApi with an <code>{id}</code> of <em>FooBar</em> and then Web API executes the <code>Get()</code> method since the request was an HTTP GET.</p>
<h3>Web API supports RPC too</h3>
<p>Easy REST support by convention is nice, but what&#8217;s not obvious in any of the samples I&#8217;ve seen is that <strong>Web API supports RPC-style routing too</strong>.</p>
<p>By adding an <code>{action}</code> parameter to the route, you can override Web API&#8217;s default HTTP verb-based routing:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">routes.<span style="color: #0000FF;">MapHttpRoute</span><span style="color: #000000;">&#40;</span>
  name<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;DefaultApi&quot;</span>,
  routeTemplate<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;api/{controller}/{action}/{id}&quot;</span>,
  defaults<span style="color: #008000;">:</span> <span style="color: #008000;">new</span> <span style="color: #000000;">&#123;</span> id <span style="color: #008000;">=</span> RouteParameter.<span style="color: #0000FF;">Optional</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>With this routing configuration, the previous GET request to <code>/api/myapi/</code> returns a 404, but requests to <code>/api/myapi/get</code> via any HTTP verb return <em>Hello World</em>. That&#8217;s not incredibly useful by itself, but it means we can extend the API with arbitrary RPC methods now:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyApiController<span style="color: #008000;">:</span> ApiController <span style="color: #000000;">&#123;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Get<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #666666;">&quot;Hello World&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #000000;">&#125;</span>
&nbsp;
  <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> FooBar<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #666666;">&quot;FooBar&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Now, requests to <code>/api/myapi/foobar</code> will return <em>FooBar</em> instead of <em>Hello World</em>.</p>
<h3>Gradually migrating from RPC to REST</h3>
<p>Since &#8220;switching&#8221; from REST to RPC was just a routing change, it stands to reason that you could combine both approaches easily enough. Indeed, it&#8217;s as simple as using a pair of routes like these:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">routes.<span style="color: #0000FF;">MapHttpRoute</span><span style="color: #000000;">&#40;</span>
  name<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;RestApi&quot;</span>,
  routeTemplate<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;api/{controller}/{id}&quot;</span>,
  defaults<span style="color: #008000;">:</span> <span style="color: #008000;">new</span> <span style="color: #000000;">&#123;</span> id <span style="color: #008000;">=</span> RouteParameter.<span style="color: #0000FF;">Optional</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
routes.<span style="color: #0000FF;">MapHttpRoute</span><span style="color: #000000;">&#40;</span>
  name<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;RpcApi&quot;</span>,
  <span style="color: #008080; font-style: italic;">// I like &quot;services&quot; as the path prefix for this since it's</span>
  <span style="color: #008080; font-style: italic;">//  where I usually stored ASMX services in the past, but </span>
  <span style="color: #008080; font-style: italic;">//  you can use anything you want. &quot;rpc&quot; would be good too.</span>
  routeTemplate<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;services/{controller}/{action}&quot;</span>
<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>One important caveat with this approach is that you need to name your controllers carefully. Even if they&#8217;re in different namespaces, you&#8217;ll get an ambiguity error if both folders contain an API controller with the same class name.</p>
<p>It should be possible to resolve that issue by adding a <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.route.constraints(v=vs.108).aspx" target="_blank" rel="nofollow">constraint</a> to the route, but I haven&#8217;t been able to get that working with <code>MapHttpRoute</code>. If you know how to make that work with Web API, please let me know.</p>
<h3>Combining both REST and RPC</h3>
<p>If you want to live dangerously, you can even mix both approaches in the same API controller. If you include an <em>optional</em> <code>{action}</code> parameter in your API route definition, you get Web API&#8217;s verb-based routing <strong>and</strong> the option to augment those basic methods with specified RPC-style methods.</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">routes.<span style="color: #0000FF;">MapHttpRoute</span><span style="color: #000000;">&#40;</span>
  name<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;RestPCApi&quot;</span>,
  routeTemplate<span style="color: #008000;">:</span> <span style="color: #666666;">&quot;api/{controller}/{action}&quot;</span>,
  defaults<span style="color: #008000;">:</span> <span style="color: #008000;">new</span> <span style="color: #000000;">&#123;</span> action <span style="color: #008000;">=</span> RouteParameter.<span style="color: #0000FF;">Optional</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Using the previous Get/FooBar class, making GET requests to <code>/api/myapi/</code> return <em>Hello World</em>, while making a request via any HTTP verb to <code>/api/myapi/foobar</code> will return <em>FooBar</em>. Nifty.</p>
<p>I will say that I haven&#8217;t tried using this same-controller hybrid approach in any real code yet, so tread lightly (and please leave a comment on this post if you do try this with or without success).</p>
<h3>Why bother? Isn&#8217;t REST better?</h3>
<p>The prevailing popular opinion these days is clearly in favor of RESTful APIs. REST does make for a nice, clean API when it fits well. That&#8217;s especially true for relatively simple public-facing APIs (e.g. services like Twitter and Flickr), where everyone benefits from following common conventions.</p>
<p>On the other hand, private APIs sometimes don&#8217;t need a full CRUD implementation for every resource. When you only need a few combinations of noun and verb, a simple RPC API is a perfectly valid alternative to the cartesian product of nouns and verbs that a truly RESTful API requires you to implement.</p>
<p>More importantly, <strong>RPC routing support means you don&#8217;t need to be afraid of Web API</strong>, even if you&#8217;re heavily invested in ASMX or WCF services.</p>
<p>You can upgrade to Web API&#8217;s goodness without completely revamping your existing services (I recently updated one of my largest ASMX-based projects to ASP.NET Web API in less than a day using this RPC routing approach). That means you can maintain RPC support for those older services, while implementing new services in a RESTful style going forward, and migrate at your own pace without any of your services being stuck on a legacy technology.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/databinding-class-data/' rel='bookmark' title='Databinding Class Data'>Databinding Class Data</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/">REST vs. RPC in ASP.NET Web API? Who cares; it does both.</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=F30kspI4CFo:mkZMugnvJdg:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=F30kspI4CFo:mkZMugnvJdg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=F30kspI4CFo:mkZMugnvJdg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=F30kspI4CFo:mkZMugnvJdg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/F30kspI4CFo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/</feedburner:origLink></item>
		<item>
		<title>Facebook is retaining Instagram’s users, not acquiring them</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/XUUJhriWyE0/</link>
		<comments>http://encosia.com/facebook-is-retaining-instagrams-users-not-acquiring-them/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 21:27:13 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[Short]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1330</guid>
		<description><![CDATA[There&#8217;s been plenty of cynical talk going around about today&#8217;s news that Facebook is acquiring Instagram for $1 billion in cash and stock. One of the most salient points is the simple arithmetic on how much Facebook is paying for each of Instagram&#8217;s roughly 30 million users. With Facebook paying somewhere in the neighborhood of [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been plenty of cynical talk going around about today&#8217;s news that <a href="https://www.facebook.com/zuck/posts/10100318398827991" target="_blank">Facebook is acquiring Instagram for $1 billion in cash and stock</a>. One of the most salient points is the simple arithmetic on how much Facebook is paying for each of Instagram&#8217;s roughly 30 million users. With Facebook paying somewhere in the neighborhood of $33 per Instagram user, that seems fairly pricey compared to <a href="http://techinsidr.com/exactly-much-is-each-facebook-linkedin-user-worth/" target="_blank">Facebook&#8217;s own valuation of roughly $120 per user</a>.</p>
<p>What&#8217;s missing from that math is that Facebook users spend a huge amount of their time sharing and viewing photos. According to <a href="http://socialfresh.com/facebook-newsfeed-time-spent/" target="_blank">recent Comscore data</a>, Facebook users are spending 17% of their time viewing photos on Facebook. <strong>Photos are incredibly important to Facebook</strong>.</p>
<p><img src="http://encosia.com/blog/wp-content/uploads/2012/04/facebook-time-spent-seg.png" alt="Time spent on Facebook by type of activity." width="490" height="286" class="alignnone size-full wp-image-1331" style="border: 1px solid #ccc;" /></p>
<p>Thinking of how I use Facebook and how I&#8217;ve seen others use it, I&#8217;d even make a case for the photos being a crucial part of drawing users into the remaining 83%.</p>
<p>Almost overnight, Instagram&#8217;s social network of photo enthusiasts gave it a solid beachhead into some 17% of Facebook&#8217;s social stronghold. Perhaps maybe even more importantly, Instagram is entirely focused on mobile (<a href="http://mashable.com/2011/01/25/facebook-cto-mobile/" target="_blank">where Facebook sees its future</a>). Maybe Instagram had no intention of ever competing head-to-head with Facebook, but I believe Instagram actually posed a greater potential threat than Google+ has yet.</p>
<p>Though it&#8217;s hard to fathom a $1 billion valuation for such a simple app and service, maybe that&#8217;s a reasonable price to quash potential competition to the unimaginable windfall that is Facebook. <strong>Facebook isn&#8217;t buying new users, but paying a premium to retain the union of Facebook and Instagram&#8217;s shared users and redirecting this aspect of their engagement back toward Facebook</strong>.</p>
<p>No related posts.</p><hr />

<p>You've been reading <a href="http://encosia.com/facebook-is-retaining-instagrams-users-not-acquiring-them/">Facebook is retaining Instagram&#8217;s users, not acquiring them</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/facebook-is-retaining-instagrams-users-not-acquiring-them/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=XUUJhriWyE0:an963OpMlZM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=XUUJhriWyE0:an963OpMlZM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=XUUJhriWyE0:an963OpMlZM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=XUUJhriWyE0:an963OpMlZM:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/XUUJhriWyE0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/facebook-is-retaining-instagrams-users-not-acquiring-them/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://encosia.com/facebook-is-retaining-instagrams-users-not-acquiring-them/</feedburner:origLink></item>
		<item>
		<title>Someone should copy these 4 features from the Zenbook</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/H_NdmJpPNoA/</link>
		<comments>http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 22:17:58 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1318</guid>
		<description><![CDATA[It’s been a few months since I began reviewing ASUS’ Zenbook UX31 based on day-to-day use, and it’s time to wrap the process up with a third and final post. The original plan for this series of reviews was that I’d write three posts about the Zenbook, finishing with one that summarized my experience using [...]
Related posts:<ol>
<li><a href='http://encosia.com/the-asus-zenbook-ux31-initial-impressions/' rel='bookmark' title='The ASUS Zenbook UX31: Initial impressions'>The ASUS Zenbook UX31: Initial impressions</a></li>
<li><a href='http://encosia.com/a-month-with-my-zenbook-ux31/' rel='bookmark' title='A month with my Zenbook UX31'>A month with my Zenbook UX31</a></li>
<li><a href='http://encosia.com/exploring-one-of-ms-ajaxs-often-overlooked-features/' rel='bookmark' title='Exploring one of MS AJAX&#8217;s often overlooked features.'>Exploring one of MS AJAX&#8217;s often overlooked features.</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0075.jpg" rel="attachment"><img style="border: 1px solid #ccc;" src="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0075-small.jpg" width="490" height="327"></a></p>
<p>It’s been a few months since <a href="http://encosia.com/the-asus-zenbook-ux31-initial-impressions/" target="_blank">I began reviewing ASUS’ Zenbook UX31</a> based on day-to-day use, and it’s time to wrap the process up with a third and final post. The original plan for this series of reviews was that I’d write three posts about the Zenbook, finishing with one that summarized my experience using it regularly for a few months.</p>
<p>Unfortunately, the trouble I had with its keyboard sabotaged that plan. If you haven’t been following along, <a href="http://encosia.com/a-month-with-my-zenbook-ux31/" target="_blank">a month with the Zenbook’s keyboard was all I could endure</a>. However, almost every other aspect of the UX31 put it solidly in the running as a successor to my MacBook Air.</p>
<p>Rather than ending on that sour note about the keyboard, this last post in the series will cover a few things that the Zenbook did well. So well, I’ll be looking for these features in whichever Ultrabook™ ultimately does replace my MacBook Air.</p>
<h3>Life’s too short to wait on a computer</h3>
<p>I mentioned this in my last post in this series, but the Zenbook’s resume-from-sleep delay is the shortest I’ve ever experienced. I always thought my MacBook Air was pretty quick on that front, but it feels impossibly sluggish after using the Zenbook for a month.</p>
<p>Resume speed sounds like a trivial feature, but I think it’s similar to how a machine’s physical fit and finish affects how you perceive that machine’s innards even though they’re unrelated. When I open the lid on my laptop, I’m doing that because I want to use the thing right away. Repeatedly poking around at the touchpad to determine whether I’m looking at a glorified splash screen façade or working OS makes me feel like this guy sometimes:</p>
<p><iframe height="363" src="http://www.youtube-nocookie.com/embed/OPwPo-IAQ-E?rel=0" frameborder="0" width="492" allowfullscreen=""></iframe></p>
<p>I hope that I can ultimately find an Ultrabook™ that satisfies my other requirements (read: a keyboard that works) while still including the Zenbook’s impressively quick resume time.</p>
<h3>USB+ charging</h3>
<p>When I’m mobile, my phone is my lifeline and its battery is the power source I care most about keeping charged. It’s irritating if my laptop runs out of juice, but I’m dead in the water without my phone.</p>
<p>In fact, if you’ve been to a conference with me in the past few years, you might have seen me sitting in an afternoon session, laptop barely cracked open, screen dimmed, charging my phone. Of course, that’s an inefficient way to transfer power from one battery to the other since most of the power flowing out of the laptop’s battery is wasted running the laptop itself in that scenario.</p>
<p>So, I was pleasantly surprised by the UX31’s USB Charger+ feature.</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/04/usb-charger-plus.png" rel="attachment"><img style="margin: 0px 10px 5px 0px; border: 1px solid #ccc;" alt="A screenshot of the USB Charger+ control panel" align="left" src="http://encosia.com/blog/wp-content/uploads/2012/04/usb-charger-plus-sm.png" width="200" height="230"></a>With USB Charger+ enabled, <strong>the Zenbook will charge USB devices even while the laptop is in sleep mode, hibernated, or shut down</strong>. You can even set a threshold for exactly how much of the Zenbook’s battery capacity will passively transfer, so you don’t accidentally run the laptop’s battery dead in the process.</p>
<p>While I didn’t use my Zenbook long enough to make heavy use of USB Charger+, I’m sure that I would use it regularly if my next laptop had a similar feature.</p>
<h3>Quality construction</h3>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0103.jpg" rel="attachment"><img style="border: 1px solid #ccc;" alt="zenbook-0103-small" src="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0103-small.jpg" width="490" height="327"></a></p>
<p>The MacBook’s unibody aluminum case was part of the reason that I originally purchased my Air. Certainly, conventional wisdom dictates that Apple’s laptops set the standard for quality construction, right?</p>
<p>On the contrary, I was surprised to find that <strong>the Zenbook felt even more solid than my Air</strong>. In particular, the relatively flexible top of the Air’s lid has always bothered me. It feels like you’re pressing the case right into the back of the LCD if you squeeze it there to pick it up.</p>
<p>Handling a laptop with a creaky, flexible case is one of my pet peeves, so the Zenbook’s rock-solid construction was one of my favorite things about it. Even its slightly heavier heft, though a detriment when comparing specs on paper, was just the right amount to make it feel robust without being heavy enough to comfortably hold from a front edge or corner.</p>
<h3>Great built-in audio</h3>
<p>I mentioned this in my last post too, but the Bang &amp; Olufsen internal sound system in the UX31 is impressive. I can’t remember ever regularly listening to music on any of my previous laptops’ speakers, but found myself doing that often during my month with the Zenbook when I was using it in private.</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0090.jpg" rel="attachment"><img style="border: 1px solid #ccc" title="zenbook-0090-small" alt="zenbook-0090-small" src="http://encosia.com/blog/wp-content/uploads/2012/04/zenbook-0090-small.jpg" width="490" height="327"></a></p>
<p>A laptop&#8217;s speakers definitely aren&#8217;t as important as the display, touchpad, or keyboard, but the laptop’s built-in audio system will be something I pay attention to in the future. If I can find a MacBook Air successor that does have internal sound comparable to the Zenbook’s, I’ll be happy about that.</p>
<h3>Don&#8217;t feed the lawyers</h3>
<p><em>Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”</em></p>
<h3>Conclusion</h3>
<p>Of course, there were other aspects where the Zenbook performed well. The Core i5 processor, high resolution display, and responsive touchpad were all welcome features, for example. However, the preceding four features were where the UX31 truly distinguished itself, and I hope that I can eventually find an Ultrabook™ that incorporates those features <em>and</em> the niceties that the Zenbook lacked.</p>
<h4>What do you think?</h4>
<p>In closing, I’m curious if you found this experiment helpful. I know I can’t be alone in wanting to find a Windows-friendly laptop that has great design and quality construction, so I do hope that you found my review of the Zenbook interesting and relevant.</p>
<p>If I get the opportunity to do this again with a different laptop, would you be interested in reading another series of posts about that hardware? Are there any new laptops that you’re particularly interested in seeing reviewed?</p>
<div class="lqm_ad" lqm_publisher="lqm.encosia.site" lqm_zone="ron" lqm_format="1x1"></div>
<p>Related posts:<ol>
<li><a href='http://encosia.com/the-asus-zenbook-ux31-initial-impressions/' rel='bookmark' title='The ASUS Zenbook UX31: Initial impressions'>The ASUS Zenbook UX31: Initial impressions</a></li>
<li><a href='http://encosia.com/a-month-with-my-zenbook-ux31/' rel='bookmark' title='A month with my Zenbook UX31'>A month with my Zenbook UX31</a></li>
<li><a href='http://encosia.com/exploring-one-of-ms-ajaxs-often-overlooked-features/' rel='bookmark' title='Exploring one of MS AJAX&#8217;s often overlooked features.'>Exploring one of MS AJAX&#8217;s often overlooked features.</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/">Someone should copy these 4 features from the Zenbook</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=H_NdmJpPNoA:TQ1u5IOoJLk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=H_NdmJpPNoA:TQ1u5IOoJLk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=H_NdmJpPNoA:TQ1u5IOoJLk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=H_NdmJpPNoA:TQ1u5IOoJLk:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/H_NdmJpPNoA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/</feedburner:origLink></item>
		<item>
		<title>Cooking the books is hard and doesn’t help anyone</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/_xVcPOkSUss/</link>
		<comments>http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/#comments</comments>
		<pubDate>Wed, 21 Mar 2012 14:48:02 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1310</guid>
		<description><![CDATA[My take on the IE team's recent criticism of StatCounter's browser market share data.
Related posts:<ol>
<li><a href='http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/' rel='bookmark' title='Targeting WebKit is not like targeting IE6'>Targeting WebKit is not like targeting IE6</a></li>
<li><a href='http://encosia.com/why-phonegap-1-1-0-broke-jquery-mobiles-back-button/' rel='bookmark' title='Why PhoneGap 1.1.0 broke jQuery Mobile&#8217;s back button'>Why PhoneGap 1.1.0 broke jQuery Mobile&#8217;s back button</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The IE team published <a href="http://windowsteamblog.com/ie/b/ie/archive/2012/03/18/understanding-browser-usage-share-data.aspx" target="_blank">an in-depth post</a> over the weekend, raising a few concerns about StatCounter&#8217;s methodology (or lack thereof) for reporting browser market share. Their points were interesting to consider, but one of them stood out to me:</p>
<blockquote><p>You’ll notice some pretty big differences in the weighting of StatCounter versus Net Applications. First and foremost, the most populous country in the world, China, doesn’t make the top 20 for StatCounter, when in fact it represents the world’s largest internet population.</p>
<p>[...]</p>
<p>To further explore this problem, we re-ran the StatCounter numbers and weighted their publicly reported individual country browser share numbers by the CIA internet population data. This calculation would then represent a true country or geo-weighted view of worldwide browser data based on the actual world’s internet population.</p></blockquote>
<p>It&#8217;s true that we should be wary of methodology issues that can creep into data extracted from analytics services that weren&#8217;t designed with aggregate statistics in mind. StatCounter&#8217;s data is often accepted at face value, without any detailed scrutiny. However, I believe this <em>geo-weighting</em> approach they&#8217;ve explored may be as flawed as the raw, unadjusted data itself.</p>
<h3>Why does it matter?</h3>
<p>What&#8217;s the use in splitting hairs about this? When I finished writing this post, I wondered the same thing. Why did I bother writing 1,000+ words about a random IE marketing post?</p>
<p><strong>Microsoft is an incredibly metrics-driven company</strong>. You can be sure that these numbers are intended to make a case for ignoring certain aspects of Chrome and Firefox, prioritizing particular Internet Explorer features, and/or confirming that Internet Explorer is turning the tide against Chrome and Firefox.</p>
<p>As long as Internet Explorer is the baseline browser that ships with every Windows-based PC, massaging the numbers to downplay the popularity of what Chrome and Firefox are doing hurts us all. So, that&#8217;s why I&#8217;m taking the time to voice my doubts about this recent post.</p>
<h3>What’s an &#8220;Internet user&#8221; anyway?</h3>
<p>The motivation behind this geo-weighting approach seems to be that the CIA World Factbook reports <a href="https://www.cia.gov/library/publications/the-world-factbook/geos/ch.html" target="_blank">China&#8217;s &#8220;Internet users&#8221; at a robust 389 million</a>, compared to <a href="https://www.cia.gov/library/publications/the-world-factbook/geos/us.html" target="_blank">the US&#8217; 245 million</a>, whereas StatCounter only reports about one percent of the traffic it tracks as coming from IE-laden China. So, maybe it&#8217;s reasonable to argue that StatCounter&#8217;s numbers for IE usage should be adjusted proportionally.</p>
<p>Not so fast though. If you&#8217;re like me, you might be curious what actually counts as an &#8220;Internet user&#8221; first. Here&#8217;s <a href="https://www.cia.gov/library/publications/the-world-factbook/docs/notesanddefs.html#2153" target="_blank">the CIA World Factbook&#8217;s definition</a>:</p>
<blockquote><p>The number of users within a country that access the Internet. Statistics vary from country to country and may include users who access the Internet at least several times a week to those who access it only once within a period of several months.</p></blockquote>
<p>Reasonable interpretations of that include counting every person that uses an Internet cafe a few times a year and everyone who checks email from an app on their phone as Internet users. Maybe it&#8217;s just me, but that seems like an incredibly vague statistic to warrant such a significant adjustment.</p>
<p>It gets worse though. Keep that definition in mind for a minute and let&#8217;s talk about another statistic that varies greatly between China and the US.</p>
<h3>You can&#8217;t ignore mobile</h3>
<p>The most current CIA World Factbook stats on mobile phone usage put China at a whopping 859 million subscribers versus 279 million in the US. While Internet access via mobile phone was insignificant in the pre-iPhone US, it has long been the norm in many Eastern countries (<a href="http://www.chinainternetwatch.com/whitepaper/china-internet-statistics/" target="_blank">some research</a> points to a full two-thirds of Chinese Internet access being via mobile phone).</p>
<p>Given that reliance on mobile access and the nearly 600 million mobile subscribers China has on the US, it&#8217;s reasonable to assume that a non-trivial chunk of the &#8220;Internet user&#8221; gap between the US and China is comprised of mobile users. In fact, the data suggests to me that <strong>China&#8217;s higher number of total Internet users may actually represent less access via traditional PC than in the US</strong>.</p>
<p>Speaking of those mobile users, while we&#8217;re swimming in a sea of iOS, Android, and Windows Phone devices in the US, it’s easy to forget that the venerable Nokia feature phone is still the dominant Internet-enabled mobile device in many countries (China included). Behind Nokia, manufacturers like Samsung, LG, Motorola, and Sony Ericsson also sell a combined tens-of-millions of feature phones with Internet capabilities in markets like China each year.</p>
<p>More importantly, only a tiny fraction of mobile phones run any version of Internet Explorer, and no feature phone  that I&#8217;m aware of runs Internet Explorer. When you consider this aspect of the CIA&#8217;s data, it seems plausible that IE&#8217;s market share in Eastern countries may actually need to be adjusted <em>downward</em> if anything.</p>
<h3>Why not version-weighting too?</h3>
<p>The IE team’s blog post specifically mentioning China reminded me of <a href="http://www.ie6countdown.com/" target="_blank">The Internet Explorer 6 Countdown site</a> that Microsoft itself launched last year. One of the datapoints that really stands out there is that China represents a solid majority of Internet Explorer 6’s remaining user base (largely due to pirated copies of Windows XP that can&#8217;t easily be upgraded to IE7+):</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/ie6-global-distribution.jpg" rel="attachment" target="_blank"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/ie6-global-distribution-sm.jpg" class="full-width" /><br />
</a></p>
<p>So, even if you believe that China’s browser share numbers should be adjusted upward to compensate for the potential discrepancy in StatCounter’s data, <strong>nearly a full quarter of those users are still stuck on IE6</strong>. That’s hardly something to be proud of in 2012, but even more embarrassing in a discussion about IE’s market share as compared to <a href="http://royal.pingdom.com/2010/04/08/the-modern-browser-wars-how-well-firefox-ie-and-chrome-succeed-in-getting-their-users-to-upgrade/" target="_blank">Chrome and Firefox&#8217;s rapidly upgrading user base</a>.</p>
<h3>Why so mean?</h3>
<p>My aim here isn&#8217;t to pointlessly bash the Internet Explorer team.</p>
<p>They really are doing some great work on turning IE around. I think IE9 was an inflection point where the Windows team got serious about the web again, and IE10 is poised to bring Internet Explorer forward to a place where it can focus more on moving the entire web platform forward like it did in its heyday 10+ years ago.</p>
<p>Yet, no one benefits from this sort of accounting trick; not even the IE team itself.</p>
<ul>
<li>If they believe that IE9 has similar or higher market share to Chrome, it&#8217;s easier to dismiss features like <a href="http://www.html5rocks.com/en/tutorials/notifications/quick/" target="_blank">HTML5 Notifications</a> as fringe APIs that can wait till later, when implementing them in IE9 or IE10 would&#8217;ve been a win for both developers and users.</li>
<li>If they believe that IE9 is more popular than it is and that IE10 is likely to follow in those footsteps, they might be more inclined to continue ignoring <a href="http://www.w3.org/TR/2011/WD-touch-events-20110505/" target="_blank">the de facto standard touch events API</a> that iOS and Android both support and create <a href="http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx" target="_blank">a proprietary API instead</a>.</li>
<li>If they believe Chrome (and Firefox, to a lesser extent) has been relatively unsuccessful with a rapid release cycle and forced upgrades, it&#8217;s easier to remain confident that Internet Explorer&#8217;s slow release and upgrade cycle is still as viable as ever.</li>
</ul>
<p>Rather, I think if Microsoft wants to truly bring Internet Explorer back to dominance, they need to take stock and reevaluate some of their sacred cows:</p>
<ul>
<li><strong>Multiple versions side-by-side</strong>: A modern browser may either auto-update on a regular basis <em>or</em> be able to install every one of its currently active versions side-by-side. For example, it&#8217;s trivial to test in many versions of Firefox on the same machine and you&#8217;ll never need to test in a year-old version of Chrome.</li>
<li><strong>Support for XP and Vista</strong>: This is related to the previous item, but punting on support for older operating systems is directly responsible for the awful fragmentation that Internet Explorer continues to suffer. Why have Chrome and Firefox figured out how to implement WebGL 3D acceleration on Windows XP, but the company that actually created Windows XP can&#8217;t get IE9&#8242;s <em>2D</em> acceleration to work on it? Come on.</li>
<li><strong>Embrace the platform</strong>: I actually think some of IE9&#8242;s proprietary features are compelling. IE9&#8242;s work on 2D acceleration spurred the rest of the browsers to take that feature more seriously and site pinning leapfrogs Chrome&#8217;s application shortcuts by a long shot. However, that doesn&#8217;t make it okay to ignore de facto standards like the HTML5 Notification API and the touch events API, where other browsers have been playing nice with each other.</li>
</ul>
<h3>What do you think?</h3>
<p>If you&#8217;re part of the 80% of people who visit my site in Firefox or a WebKit browser, what would it take to make Internet Explorer your default browser? Is it possible?</p>
<p>If you&#8217;re part of the 8% of people who visit my site in Internet Explorer, why are you using IE? Corporate policy, or are the rest of us missing out on something?</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/' rel='bookmark' title='Targeting WebKit is not like targeting IE6'>Targeting WebKit is not like targeting IE6</a></li>
<li><a href='http://encosia.com/why-phonegap-1-1-0-broke-jquery-mobiles-back-button/' rel='bookmark' title='Why PhoneGap 1.1.0 broke jQuery Mobile&#8217;s back button'>Why PhoneGap 1.1.0 broke jQuery Mobile&#8217;s back button</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/">Cooking the books is hard and doesn&#8217;t help anyone</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=_xVcPOkSUss:VRCjKHLJIy0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=_xVcPOkSUss:VRCjKHLJIy0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=_xVcPOkSUss:VRCjKHLJIy0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=_xVcPOkSUss:VRCjKHLJIy0:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/_xVcPOkSUss" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		<feedburner:origLink>http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/</feedburner:origLink></item>
		<item>
		<title>jQuery, ASP.NET Web API, and Json.NET walk into a bar…</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/dOINYqTBwFc/</link>
		<comments>http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 14:58:23 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1306</guid>
		<description><![CDATA[There&#8217;s been some confusing back and forth lately about ASP.NET Web API and JSON. During the time between the last WCF Web API preview and the current ASP.NET Web API beta, it&#8217;s clear that effort has gone into smoothing out some of DataContractJsonSerializer&#8217;s (DCJS) quirks. However, while things like DateTime and Enum deserialization have been [...]
Related posts:<ol>
<li><a href='http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/' rel='bookmark' title='Using jQuery to Consume ASP.NET JSON Web Services'>Using jQuery to Consume ASP.NET JSON Web Services</a></li>
<li><a href='http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/' rel='bookmark' title='ASP.NET web services mistake: manual JSON serialization'>ASP.NET web services mistake: manual JSON serialization</a></li>
<li><a href='http://encosia.com/asmx-and-json-common-mistakes-and-misconceptions/' rel='bookmark' title='ASMX and JSON &ndash; Common mistakes and misconceptions'>ASMX and JSON &ndash; Common mistakes and misconceptions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been some confusing back and forth lately about ASP.NET Web API and JSON. During the time between the last WCF Web API preview and the current ASP.NET Web API beta, it&#8217;s clear that effort has gone into smoothing out some of DataContractJsonSerializer&#8217;s (DCJS) quirks. However, while things like DateTime and Enum <em>de</em>serialization have been improved, issues have still persisted with Anonymous Types, Dictionaries, and DateTime serialization.</p>
<p>Unfortunately, the underlying cause of those remaining issues was too fundamental to simply spackle over. One of the most frustrating aspects of DCJS is that it&#8217;s rooted in WCF&#8217;s mindset that all things can be expressed as XML and then translated to other formats. In that world, data like Anonymous Types and simple collections of key/value pairs are uninteresting oddities. So, <strong>as long as ASP.NET Web API is saddled with DCJS, it&#8217;s at a disadvantage in scenarios requiring more flexible JSON serialization</strong>.</p>
<h3>DataContractJsonSerializer: No one likes you!</h3>
<p>Getting away from DCJS is such an obvious first step when using Web API that Microsoft&#8217;s own <a href="https://twitter.com/frystyk" target="_blank">Henrik Nielsen</a>[<a href="#footnote-0">0</a>] published <a href="http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx" target="_blank">a guide</a> to switching from using DCJS to using <a href="https://twitter.com/JamesNK" target="_blank">James Newton-King</a>&#8216;s <a href="http://james.newtonking.com/pages/json-net.aspx" target="_blank">Json.NET</a> last month. This week, Rick Strahl wrote <a href="http://www.west-wind.com/weblog/posts/2012/Mar/09/Using-an-alternate-JSON-Serializer-in-ASPNET-Web-API" target="_blank">a similar post</a> on how to use JavaScriptSerializer <em>or</em> Json.NET with Web API.</p>
<p>In the same vein, Scott Hanselman had <a href="http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx" target="_blank">a good post</a> about the woes of dealing with dates in JSON last week. Dates in JSON are bad enough already[<a href="#footnote-1">1</a>], but the existing JSON serializers built into .NET make them even worse if you&#8217;re not using MicrosoftAjax.js or a compatibility wrapper of some sort. His solution was to use Henrik&#8217;s approach for jettisoning DCJS and switching to using Json.NET (which supports the de facto standard ISO date format).</p>
<p>In that post, Scott casually mentioned some relatively huge news: <strong>Json.NET will be included as the default JSON serializer in Web API by the time it&#8217;s released</strong>.</p>
<h3>Just so we&#8217;re clear</h3>
<p>It seems like the message about Json.NET becoming the default JSON serializer in Web API got muddled a bit, hiding in the middle of Scott&#8217;s post. So, I wanted to hone in on that specifically and hopefully add some clarity.</p>
<p>In fact, I double-checked with <a href="https://twitter.com/coolcsh" target="_blank">Scott Hunter</a>[<a href="#footnote-2">2</a>] first to be sure I wasn&#8217;t adding to the confusion myself. Here&#8217;s what he had to say:</p>
<blockquote><p><strong>We are making Json.net the default moving forward.</strong></p></blockquote>
<p>It doesn&#8217;t get more definitive than that.</p>
<h3>This is a good thing</h3>
<p>Many of us have been trending toward using ASP.NET as a JSON-speaking backend to power client-side JavaScript as much as anything else lately. For that purpose, this is fantastic news that resolves the last few serialization issues that Web API had as compared to current approaches using JavaScriptSerializer.</p>
<p>It may seem troubling that the default DateTime serialization is changing, but the short-term inconvenience of dealing with that will be well worthwhile in the long run. Moves like this that make ASP.NET more flexible and interoperable with other platforms are ultimately a boon for us all.</p>
<p>Further, <strong>isn&#8217;t it great to see Microsoft embracing and leveraging an open source project in the community instead of reinventing that wheel again?</strong> In my mind, this is one of the best examples of Microsoft playing nice with an open source project since they adopted jQuery in 2008.</p>
<h4>Footnotes</h4>
<p>[0]: <em id="footnote-0">It must be nice to just use a Wikipedia link as your Twitter bio.</em></p>
<p>[1]: <em id="footnote-1">Dates in JSON are such a disaster that I was even able to ride their coattails to a miniature round of applause during <a href="http://channel9.msdn.com/Events/MIX/MIX11/EXT13" target="_blank">Crockford&#8217;s talk at MIX11</a> (at the end, in the Q&#038;A). You know it&#8217;s serious business when I&#8217;m the only person other than Crockford to get applause during a Crockford talk!</em></p>
<p>[2]: <em id="footnote-2">Scott is Principal Program Manager Lead on the ASP.NET team. You should <a href="https://twitter.com/coolcsh" target="_blank">follow him</a> if you&#8217;re an ASP.NET developer on Twitter.</em></p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/' rel='bookmark' title='Using jQuery to Consume ASP.NET JSON Web Services'>Using jQuery to Consume ASP.NET JSON Web Services</a></li>
<li><a href='http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/' rel='bookmark' title='ASP.NET web services mistake: manual JSON serialization'>ASP.NET web services mistake: manual JSON serialization</a></li>
<li><a href='http://encosia.com/asmx-and-json-common-mistakes-and-misconceptions/' rel='bookmark' title='ASMX and JSON &ndash; Common mistakes and misconceptions'>ASMX and JSON &ndash; Common mistakes and misconceptions</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/">jQuery, ASP.NET Web API, and Json.NET walk into a bar&#8230;</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=dOINYqTBwFc:sOOvk0jQ1kI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=dOINYqTBwFc:sOOvk0jQ1kI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=dOINYqTBwFc:sOOvk0jQ1kI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=dOINYqTBwFc:sOOvk0jQ1kI:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/dOINYqTBwFc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://encosia.com/jquery-asp-net-web-api-and-json-net-walk-into-a-bar/</feedburner:origLink></item>
		<item>
		<title>A month with my Zenbook UX31</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/cSZMknmOOtA/</link>
		<comments>http://encosia.com/a-month-with-my-zenbook-ux31/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 19:16:39 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1290</guid>
		<description><![CDATA[Note: If you haven&#8217;t read my initial impressions of the Zenbook, you might want to head over and read that first: The ASUS Zenbook UX31: Initial impressions I&#8217;ve been using my ASUS Zenbook for just over a month at this point, and it&#8217;s time for a second review now that I&#8217;ve used it for a [...]
Related posts:<ol>
<li><a href='http://encosia.com/the-asus-zenbook-ux31-initial-impressions/' rel='bookmark' title='The ASUS Zenbook UX31: Initial impressions'>The ASUS Zenbook UX31: Initial impressions</a></li>
<li><a href='http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/' rel='bookmark' title='Someone should copy these 4 features from the Zenbook'>Someone should copy these 4 features from the Zenbook</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0027.jpg" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0027-small.jpg" class="full-width" /></a></p>
<p><em>Note: If you haven&#8217;t read my initial impressions of the Zenbook, you might want to head over and read that first: <a href="http://encosia.com/the-asus-zenbook-ux31-initial-impressions/" target="_blank">The ASUS Zenbook UX31: Initial impressions</a></em></p>
<p>I&#8217;ve been using my ASUS Zenbook for just over a month at this point, and it&#8217;s time for a second review now that I&#8217;ve used it for a while on a day-to-day basis. I&#8217;ve heard from many of you about being eager to read the next installment in this process, so I&#8217;m glad to know that you&#8217;re finding this experiment useful too.</p>
<h3>Component controversy</h3>
<p>First, I want to address something that came up on Twitter a few weeks ago, when it was brought to light that there&#8217;s apparently some variation between the touchpad and SSD hardware components that ASUS used in different builds of the same model Zenbooks. You can read more about that in <a href="http://www.amazon.com/review/R1E2629UNP4R7L/ref=cm_cr_pr_viewpnt#R1E2629UNP4R7L" target="_blank">this Amazon review</a>.</p>
<p>The short of it is that Zenbooks that ship with an ADATA SSD are potentially much faster when it comes to some tasks and models with the ELAN touchpad are usually less quirky when multi-finger gestures come into play. I don&#8217;t know if that&#8217;s an ongoing inconsistency or if all units have the improved hardware going forward, but it&#8217;s something important to keep in mind.</p>
<p><a href="https://twitter.com/#!/LeeDumond/status/163357665236496384">One implication I saw mentioned</a> was that ASUS may have provided us with ADATA/ELAN equipped models in order to elicit the best possible reviews. However, while the model that I received does have the ELAN touchpad, its SSD is the slower Sandisk variant.</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0009.jpg" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0009-small.jpg" class="full-width" /></a></p>
<p>More importantly, <strong>my Zenbook was shipped directly from Amazon, not ASUS. There was no opportunity for that kind of trickery to occur.</strong> If you look closely at the photo above, you can see that we actually happened to capture a photo of the Amazon shipping label during the unboxing.</p>
<p>Further, Intel is sponsoring these reviews, not ASUS. So, any suspicion that ASUS is providing us with the best possible model to review is probably misplaced.</p>
<h3>Terrific touchpad</h3>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0083.jpg" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0083-small.jpg" class="full-width" /></a></p>
<p>Speaking of the ELAN touchpad, I&#8217;ve been pleasantly surprised with how well the touchpad in this UX31 works. I guess I&#8217;ve just sort of resigned myself to PC laptops having cheap, plasticy touchpads and clunky support for multitouch gestures, but the Zenbook has definitely changed my perception of that.</p>
<p>Gestures like two-finger scrolling work as you&#8217;d expect, but it also supports pinching to zoom in and out, three-fingers to the left or right to navigate back and forward, and three-fingers up to invoke Aero Flip 3D. Overall, I found the gestures reliable and quite useful (though I can&#8217;t speak for the zoom and rotate gestures because I don&#8217;t use those).</p>
<p>My one gripe with the touchpad relates to scrolling. Its implementation of two-finger scrolling is responsive and fluid in most applications, but the two-finger momentum scroll gesture results in an awkwardly jerky transition from scrolling to stationary. Since the scrolling is fluid with fingers still on the touchpad, it doesn&#8217;t make sense that it can&#8217;t fluidly come to a halt. However, that ought to be fixable via software tweak, so hopefully a subsequent driver update can cure this problem.</p>
<p>That one quirk aside, even though I was coming from my MacBook Air&#8217;s gesture-laden OS X Lion environment, <strong>I didn&#8217;t feel like I was compromising when it came to the touchpad</strong>. As high as that particular bar is set, that&#8217;s impressive.</p>
<h3>Resume rapidly</h3>
<p>One of the selling points of both the MacBook Air and Ultrabook&trade; lines is how quickly they resume from sleep mode. Years ago, I never really thought that my venerable Dell XPS M1330&#8242;s resume time was a serious issue&#8230; until I started using the MacBook Air.</p>
<p>As quickly as the Air resumes, I found myself pleasantly surprised yet again with the Zenbook. I can&#8217;t remember ever opening the UX31&#8242;s lid and not finding it responsive to input almost immediately, whereas the Air is often unresponsive for several seconds after resuming to the desktop.</p>
<p>While he was taking the unboxing photos, <a href="http://www.35atlanta.com/" target="_blank">Ray</a> also shot this video of how quickly the Zenbook resumes from sleep:</p>
<p><iframe width="492" height="280" src="http://www.youtube-nocookie.com/embed/I2BF1u-E2s0?rel=0" frameborder="0" allowfullscreen></iframe></p>
<p>Pretty impressive, huh?</p>
<p>Once the Windows desktop is visible, the machine is 100% usable. No delays and no compromises. That&#8217;s a welcome improvement compared to the facade of readiness that my MacBook displays for a few seconds before it&#8217;s truly responsive.</p>
<h3>Keyboard kerfuffle</h3>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0122.jpg" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0122-small.jpg" class="full-width" /></a></p>
<p>Unfortunately, <strong>my ongoing effort to acclimate to the UX31&#8242;s keyboard has been unsuccessful</strong>. If I weren&#8217;t mildly obligated to give it a fighting chance, the keyboard would probably have been a deal breaker in the beginning. I&#8217;ve typed on enough keyboards that don&#8217;t require any adjustment period that I don&#8217;t have much patience for one I don&#8217;t get along with.</p>
<p>I believe the fundamental problem is a mechanical one. What I&#8217;ve found is that I can fully depress the corner of a key, even to the point that it gives positive tactile feedback, without anything happening. Typing heavily on the direct center of a key seems to be 100% reliable, but that&#8217;s not how I type; especially when it comes to rectangular keys like shift and enter.</p>
<p>Fighting with a keyboard is difficult enough in any circumstance, but having an unreliable shift key is particularly brutal when you&#8217;re writing code (or writing about code). Just think about how many times you type characters like <code>$</code>, <code>"</code>, <code>{</code>, <code>}</code>, <code>_</code>, <code>+</code>, <code>(</code>, and <code>)</code> during a average day. Now, imagine that about a third of them came out &#8220;unshifted&#8221;. Then, you&#8217;ll be able to picture how infuriating development work has been on this keyboard.</p>
<h4>Another variation in the underlying hardware?</h4>
<p>While I was in Bellevue for the Microsoft MVP Summit last week, I had the opportunity to try typing on two alternate UX31s, <a href="http://weblogs.asp.net/jgalloway/archive/2012/02/28/zenbook-ux31e-follow-up.aspx">Jon Galloway&#8217;s</a> and one in Bellevue&#8217;s Microsoft Store.</p>
<p>The one I tried in the Microsoft Store seemed slightly more responsive when I typed some ad-hoc jQuery code into a sticky note. One thing I did notice is that both of its shift keys had begun permanently sagging on their inside corners, presumably from heavy use in the store. Eventually, normal daily use would probably produce the same result.</p>
<p>On the other hand, Jon&#8217;s worked significantly better than mine. Even to the point that I wonder if this is another case of variance in the components in different batches of the Zenbook.</p>
<h4>But, none of that helps me very much&#8230;</h4>
<p>Maybe I&#8217;m a keyboard snob. I do use <a href="http://www.amazon.com/gp/product/B000J43HJ8/ref=as_li_ss_tl?ie=UTF8&#038;tag=encosia-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=B000J43HJ8" target="_blank" rel="nofollow">a diNovo Edge keyboard</a>, with its &#8220;PerfectStroke key system&#8221;, on my development machine. Or, maybe the Zenbook&#8217;s keyboard just doesn&#8217;t like the cut of my jib.</p>
<p>Either way, we&#8217;re going our separate ways.</p>
<p>Ultimately, <strong>this particular Zenbook&#8217;s keyboard is a deal breaker for me</strong>. I&#8217;m not willing to waste time and money on a trial &#8216;n error process of searching for the occasional Zenbook that I can type well on (and hope that it doesn&#8217;t wear like the one I saw in the Microsoft Store).</p>
<h3>What&#8217;s next?</h3>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0128.jpg" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/03/zenbook-0128-small.jpg" class="full-width" /></a></p>
<p>The original plan was that I would write a total of three posts detailing my impressions of using the Zenbook on a daily basis. However, I&#8217;ve switched back to my MacBook Air as of last week. So, that plan doesn&#8217;t make sense anymore.</p>
<p>Instead, I&#8217;ll be writing a third post about what my month with the Zenbook has shown me that I&#8217;d like to have in my next laptop. Though the keyboard ultimately prevented me from sticking with the Zenbook, it has some great features that I&#8217;ve already missed since switching back to my MacBook Air.</p>
<h3>Photo credit</h3>
<p>As was the case in my previous post, all of the beautiful photos you see above are made possible by my friends at <a href="http://www.35atlanta.com/" target="_blank">35 Atlanta</a> coming over and setting up studio in my house for a few hours. They&#8217;re based here in Atlanta, but they were doing a photo shoot in Cancun last week and have one in Seattle next month. If you need fantastic photos taken of just about any subject, in just about any location, I highly recommend them.</p>
<h3>Disclosure</h3>
<p>In case you&#8217;re reading this post before <a href="http://encosia.com/the-asus-zenbook-ux31-initial-impressions/" target="_blank">my previous one</a>, I want to be clear that I received a complementary UX31 Zenbook in exchange for reviewing it. If there was any question before, this second review should have made it clear that I only recommend products I would actually use myself and that I&#8217;m giving you my fair and honest review. Also, here&#8217;s some legalese:</p>
<p><em>Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the <a href="http://www.access.gpo.gov/nara/cfr/waisidx_03/16cfr255_03.html" target="_blank" rel="nofollow">Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”</a></em></p>
<div class="lqm_ad" lqm_publisher="lqm.encosia.site" lqm_zone="ron" lqm_format="1x1"></div>
<p>Related posts:<ol>
<li><a href='http://encosia.com/the-asus-zenbook-ux31-initial-impressions/' rel='bookmark' title='The ASUS Zenbook UX31: Initial impressions'>The ASUS Zenbook UX31: Initial impressions</a></li>
<li><a href='http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/' rel='bookmark' title='Someone should copy these 4 features from the Zenbook'>Someone should copy these 4 features from the Zenbook</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/a-month-with-my-zenbook-ux31/">A month with my Zenbook UX31</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/a-month-with-my-zenbook-ux31/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=cSZMknmOOtA:IrviYzQXHMA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=cSZMknmOOtA:IrviYzQXHMA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=cSZMknmOOtA:IrviYzQXHMA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=cSZMknmOOtA:IrviYzQXHMA:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/cSZMknmOOtA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/a-month-with-my-zenbook-ux31/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://encosia.com/a-month-with-my-zenbook-ux31/</feedburner:origLink></item>
		<item>
		<title>Targeting WebKit is not like targeting IE6</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/Ffz6E7YV-HI/</link>
		<comments>http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 17:26:46 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[Short]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1288</guid>
		<description><![CDATA[There&#8217;s been a bit of controversy lately concerning the rising dominance of WebKit-based browsers (e.g. Chrome, Safari, and Mobile Safari) and the potential that we&#8217;re repeating past mistakes: Not so long ago, IE6 was the over-dominant browser on the Web. Technically, the Web was full of works-only-in-IE6 web sites and the other browsers, the users [...]
Related posts:<ol>
<li><a href='http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/' rel='bookmark' title='Cooking the books is hard and doesn&#8217;t help anyone'>Cooking the books is hard and doesn&#8217;t help anyone</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a bit of controversy lately concerning the rising dominance of WebKit-based browsers (e.g. Chrome, Safari, and Mobile Safari) and <a href="http://www.glazman.org/weblog/dotclear/index.php?post/2012/02/09/CALL-FOR-ACTION%3A-THE-OPEN-WEB-NEEDS-YOU-NOW" target="_blank">the potential that we&#8217;re repeating past mistakes</a>:</p>
<blockquote><p>Not so long ago, IE6 was the over-dominant browser on the Web. Technically, the Web was full of works-only-in-IE6 web sites and the other browsers, the users were crying. IE6 is dead, this time is gone, and all browsers vendors including Microsoft itself rejoice. Gone? Not entirely&#8230; IE6 is gone, the problem is back.</p></blockquote>
<p>However, I believe there&#8217;s one gigantic difference between IE6 then and WebKit now that&#8217;s being overlooked.</p>
<p>Microsoft put the brakes on Internet Explorer development after IE6 because they realized that they were helping build the runtime for their own competition. If Internet Explorer releases had continued at the same pace, most everyone would probably be using IE15 today and IE6 would be as memorable as Chrome 4 or Firefox 7.</p>
<p>Conversely, Google has a vested interest in Chrome&#8217;s ongoing success (and WebKit&#8217;s success by extension). Instead of threatening Google&#8217;s primary revenue stream, WebKit and Chrome serve to enhance Google&#8217;s golden goose. So, unlike the past situation with Microsoft, Netscape, and IE6, Google has no motivation whatsoever to shutter active development on Chrome and WebKit if it overtakes Internet Explorer and Firefox.</p>
<p>Does that make vendor prefixes and targeting experimental features a great idea? Maybe not. Frankly, I&#8217;m not qualified to speak intelligently about cutting edge CSS features.</p>
<p>What I do know is that just because the current climate <em>seems similar</em> to the one ten years ago, that doesn&#8217;t mean it&#8217;s reasonable to assume history is repeating.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/cooking-the-books-is-hard-and-doesnt-help-anyone/' rel='bookmark' title='Cooking the books is hard and doesn&#8217;t help anyone'>Cooking the books is hard and doesn&#8217;t help anyone</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/">Targeting WebKit is not like targeting IE6</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=Ffz6E7YV-HI:M2Uo7z6SVDg:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=Ffz6E7YV-HI:M2Uo7z6SVDg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=Ffz6E7YV-HI:M2Uo7z6SVDg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=Ffz6E7YV-HI:M2Uo7z6SVDg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/Ffz6E7YV-HI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://encosia.com/targeting-webkit-is-not-like-targeting-ie6/</feedburner:origLink></item>
		<item>
		<title>Web API is now part of ASP.NET (and you can get it today)</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/6IGIz9uWbVE/</link>
		<comments>http://encosia.com/web-api-is-now-part-of-asp-net-and-you-can-get-it-today/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 20:19:13 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1285</guid>
		<description><![CDATA[One of the hardest parts of being privy to NDA information is keeping my mouth shut about new developments that I wish I could share with you immediately, often for months at a time. Recent developments around ASP.NET Web API (formerly WCF Web API) are a perfect example of that conundrum. As development on WCF [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>One of the hardest parts of being privy to NDA information is keeping my mouth shut about new developments that I wish I could share with you immediately, often for months at a time.</p>
<p>Recent developments around ASP.NET Web API (formerly WCF Web API) are a perfect example of that conundrum. As development on WCF Web API seemingly stagnated on CodePlex, Microsoft had actually rolled the project into ASP.NET itself. The project was in no danger whatsoever, but (frustratingly) I wasn&#8217;t able to tell you that.</p>
<p>So, it&#8217;s a relief that today&#8217;s <a href="http://www.asp.net/mvc/mvc4" target="_blank">today&#8217;s ASP.NET MVC 4 Beta release</a> has made that news public:</p>
<blockquote><h3>Top Features</h3>
<ul>
<li><strong>ASP.NET Web API</strong></li>
<li>Refreshed and modernized default project templates</li>
<li>New mobile project template</li>
<li>Many new features to support mobile apps</li>
<li>Recipes to customize code generation</li>
<li>Enhanced support for asynchronous methods</li>
</ul>
</blockquote>
<div class="aside">
Note: It&#8217;s not entirely clear, but installing the MVC 4 beta allows you to use Web API in WebForms projects too.
</div>
<p>Though Web API isn&#8217;t necessarily a gigantic step forward from using MVC&#8217;s controllers as a makeshift API for simple scenarios, it&#8217;s great that ASP.NET now has common mechanism for creating these endpoints that works the same way on both WebForms and MVC.</p>
<p>I&#8217;ve long held out against pressure to move from ASMX to WCF in WebForms projects, because accepting WCF&#8217;s complexity primarily only rewarded me with less flexible JSON serialization. By contrast, I&#8217;ve begun converting some of my projects from ASMX to Web API, and have been pleased with how easily Web API replaces ASMX.</p>
<p><strong>I believe Microsoft has finally found a good balance between ASMX&#8217;s simplicity and WCF&#8217;s power with Web API.</strong></p>
<p>Since it was built with jQuery in mind from the very start, I&#8217;m finding that Web API is perfect for the sort of work that I usually write about here. It even automatically responses to requests from jQuery with JSON, even if you use simple URL encoded parameters with the request, so adding an endpoint for AJAX interaction in either WebForms or MVC is a breeze now.</p>
<p>I&#8217;ll be writing more about actually using Web API here in the future, but I wanted to get this post published right away to help spread the news that Web API isn&#8217;t dead.</p>
<p>To learn more about what exactly Web API is and does, have a look at <a href="http://www.asp.net/whitepapers/mvc4-release-notes#_Toc317096197" target="_blank">its section in the release notes</a>. To get up and running quickly with some example code, take a look at <a href="http://www.asp.net/web-api" target="_blank">the new Web API material on the ASP.NET site</a>.</p>
<p>No related posts.</p><hr />

<p>You've been reading <a href="http://encosia.com/web-api-is-now-part-of-asp-net-and-you-can-get-it-today/">Web API is now part of ASP.NET (and you can get it today)</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/web-api-is-now-part-of-asp-net-and-you-can-get-it-today/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=6IGIz9uWbVE:NoOmOG0qfbs:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=6IGIz9uWbVE:NoOmOG0qfbs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=6IGIz9uWbVE:NoOmOG0qfbs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=6IGIz9uWbVE:NoOmOG0qfbs:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/6IGIz9uWbVE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/web-api-is-now-part-of-asp-net-and-you-can-get-it-today/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		<feedburner:origLink>http://encosia.com/web-api-is-now-part-of-asp-net-and-you-can-get-it-today/</feedburner:origLink></item>
		<item>
		<title>Read my interview with The Code Project</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/CDCE30Pf-Ls/</link>
		<comments>http://encosia.com/read-my-interview-with-the-code-project/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 16:46:07 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1283</guid>
		<description><![CDATA[I took part in The Code Project’s A Coder Interview series recently, and the result was published there yesterday. Terrence happened to send the questions at a rare moment when I wasn’t running in five directions at once, which led to me accidentally writing quite a bit. Part of it touches on something important to [...]
Related posts:<ol>
<li><a href='http://encosia.com/learn-from-my-express-js-http-status-code-blunder/' rel='bookmark' title='Learn from my Express.js HTTP status code blunder'>Learn from my Express.js HTTP status code blunder</a></li>
<li><a href='http://encosia.com/review-the-best-javascript-book-i%e2%80%99ve-read/' rel='bookmark' title='Review: The best JavaScript book I’ve read'>Review: The best JavaScript book I’ve read</a></li>
<li><a href='http://encosia.com/how-i-got-started-in-software-development/' rel='bookmark' title='How I Got Started in Software Development'>How I Got Started in Software Development</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I took part in The Code Project’s <em>A Coder Interview</em> series recently, and the result <a href="http://www.codeproject.com/Articles/327251/A-Coder-Interview-With-Dave-Ward" target="_blank">was published there yesterday</a>. <a href="https://twitter.com/#!/tpdorsey/" target="_blank">Terrence</a> happened to send the questions at a rare moment when I wasn’t running in five directions at once, which led to me accidentally writing quite a bit.</p>
<p>Part of it touches on something important to me that I plan to write more about eventually:</p>
<blockquote><p><strong>What advice would you offer to an up-and-coming programmer?</strong></p>
<p>Write about programming. Start a blog, answer questions on The Code Project or Stack Overflow, or whatever else suits you, but find some way to write about programming.
<p>I can’t count how many times I began writing about something I thought I knew thoroughly, only to find that I had to fill in several important gaps in my knowledge to write about it competently. Just as important, you have to learn topics more comprehensively to distill and teach them in simple terms. The combination of writing about programming and making that writing as clear and simple as you can is a powerful exercise.
<p>[…]</p>
</blockquote>
<p>The interview also exposes my shameful stance on tabs vs. spaces, but you’ll have to go there to read that part…
<p><a class="more-link" href="http://www.codeproject.com/Articles/327251/A-Coder-Interview-With-Dave-Ward">Click here to read the full interview at The Code Project</a></p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/learn-from-my-express-js-http-status-code-blunder/' rel='bookmark' title='Learn from my Express.js HTTP status code blunder'>Learn from my Express.js HTTP status code blunder</a></li>
<li><a href='http://encosia.com/review-the-best-javascript-book-i%e2%80%99ve-read/' rel='bookmark' title='Review: The best JavaScript book I’ve read'>Review: The best JavaScript book I’ve read</a></li>
<li><a href='http://encosia.com/how-i-got-started-in-software-development/' rel='bookmark' title='How I Got Started in Software Development'>How I Got Started in Software Development</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/read-my-interview-with-the-code-project/">Read my interview with The Code Project</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/read-my-interview-with-the-code-project/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=CDCE30Pf-Ls:B6FlrKRFo1w:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=CDCE30Pf-Ls:B6FlrKRFo1w:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=CDCE30Pf-Ls:B6FlrKRFo1w:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=CDCE30Pf-Ls:B6FlrKRFo1w:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/CDCE30Pf-Ls" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/read-my-interview-with-the-code-project/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://encosia.com/read-my-interview-with-the-code-project/</feedburner:origLink></item>
		<item>
		<title>The ASUS Zenbook UX31: Initial impressions</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/vF4J2LEzkFw/</link>
		<comments>http://encosia.com/the-asus-zenbook-ux31-initial-impressions/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 15:00:44 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1261</guid>
		<description><![CDATA[For over a year now, I’ve been using a 13” MacBook Air as my only laptop. Though it’s a bit underpowered and I prefer Windows to OS X, I was ultimately unable to resist Apple’s build quality compared to the Dell I had used previously. However, I never fully resigned myself to accepting a dichotomy [...]
Related posts:<ol>
<li><a href='http://encosia.com/a-month-with-my-zenbook-ux31/' rel='bookmark' title='A month with my Zenbook UX31'>A month with my Zenbook UX31</a></li>
<li><a href='http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/' rel='bookmark' title='Someone should copy these 4 features from the Zenbook'>Someone should copy these 4 features from the Zenbook</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0137.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0137-small.jpg" width="490" height="327" /></a></p>
<p>For over a year now, I’ve been using a 13” MacBook Air as my only laptop. Though it’s a bit underpowered and I prefer Windows to OS X, I was ultimately unable to resist Apple’s build quality compared to the Dell I had used previously.</p>
<p>However, I never fully resigned myself to accepting a dichotomy between quality construction and operating system. Thankfully, the recent proliferation of Windows-based Ultrabook&trade; machines seems to be rapidly bridging that divide.</p>
<p>Given my already-growing desire to find an alternative, when I was contacted about reviewing the <a href="http://www.amazon.com/gp/product/B005SY32Q2/ref=as_li_ss_tl?ie=UTF8&amp;tag=encosia-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B005SY32Q2" target="_blank">ASUS’ Zenbook UX31</a> Ultrabook&trade;, I decided to give it a go. I know I’m not alone in having been frustrated with a choice between machines that run Windows well and quality hardware, so I hope that you’ll find my experience of trying to move back from the MacBook hardware useful.</p>
<p><em>Disclaimer</em>: Up front, I want you to know that I’m receiving a complementary UX31 in return for evaluating it and writing a few posts about that experience. <strong>I&#8217;ll give you my honest assessment of it and only recommend it if it meets my own standards</strong>, but I also think it’s important to be transparent and not potentially abuse your trust.</p>
<h3>Unboxing</h3>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0011.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0011-small.jpg" width="490" height="327" /></a></p>
<p>Lurking Inside the cardboard box that Amazon delivered it in, highly polished packaging awaited. ASUS did a great job with the unboxing experience, from overall presentation to ease of unpacking. It definitely reminded me of opening a high-end Apple product.</p>
<p>The UX31 comes encased in a protective plastic casing to keep the brushed aluminum’s finish pristine until you open the box, and its accessories are neatly packaged up with a canvas carrying pouch:</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0036.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0036-small.jpg" width="490" height="327" /></a></p>
<p>Along with its power adapter, the UX31 comes with a USB Ethernet adapter and VGA adapter that attaches to its mini-HDMI port. Nothing terribly unique, but both are nice to have right from the beginning (especially the ability to use a wired network connection for all the downloads that accompany initial setup of a machine that may be used for development).</p>
<h3>Initial impressions</h3>
<p>The first thing you notice about the Zenbook is the distinctive top cover of its lid. None of the photos I’ve seen online do it justice, but we tried with this one:</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0134.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0134-small.jpg" width="490" height="327" /></a></p>
<p>When I saw the radial pattern in photos online, I worried that it might look overdone or gaudy, but it looks great in person. Color me pleasantly surprised.</p>
<h4>Quality construction</h4>
<p>Removing it from the packaging, the Zenbook immediately impressed me with its rock-solid construction. One of my favorite things about the MacBook Air is that its unibody case feels solid, and my opinion is that the Zenbook bests the Air in that category, with an even more rigid case.</p>
<p>Superficial or not, that attribute is a significant part of how I judge the quality of a laptop’s construction. A laptop case that flexes or creaks when I lift it from a corner annoys me to no end. Holding the Zenbook with one hand, even from the front corners, there’s not hint of flex in its chassis.</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0129.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0129-small.jpg" width="490" height="327" /></a></p>
<p>Contrasting with the rest of the case’s angular design, the lid’s convex curvature makes the machine feel more comfortable in my hand than my MacBook Air does when both are closed.</p>
<p>Also worth noting, I felt no flex in the lid when I squeezed it to lift and carry. That lid-flex is something I’ve always found unsettling about my Air (and the Dell before it).</p>
<h4>Windows 7, now with Bing Bar?</h4>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0115.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0115-small.jpg" width="490" height="327" /></a></p>
<p>It only took a few minutes to uninstall later, but having a <em>required</em> Bing toolbar installation at the OS level didn&#8217;t feel very zen to me. I understand that preinstalled software helps subsidize the machine, but this isn&#8217;t a $200 netbook.</p>
<p>The exterior of the machine sets a high bar, and it&#8217;s important that the interior hardware and software live up to that high expectation. Thankfully, the remainder of the UX31&#8242;s preinstalled software was more tasteful.</p>
<h4>Fantastic sound</h4>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0090.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0090-small.jpg" width="490" height="327" /></a></p>
<p>I’m listening to music on the laptop’s built-in speakers as I write this post, which is something I’d never bother with on the Air (or any laptop I’ve ever used, for that matter). But, since the Bang &amp; Olufsen audio is something touted right on the case itself, I figured I ought to give it a try.</p>
<p>From the first note that played, I was astonished by the quality of sound that the UX31’s sound system produces. Of course, it’s no rival for a proper set of external speakers, but it’s amazing for concealed, self-contained speakers.</p>
<h4>Keyboard concerns</h4>
<p>I’ve struggled a bit while typing this entire post on the UX31. The keyboard itself looks and feels very nice, with a setup that’s similar to the “chicklet” layout you’ll see on many modern keyboards:</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0083.jpg" rel="attachment"><img class="full-width" src="http://encosia.com/blog/wp-content/uploads/2012/01/zenbook-0083-small.jpg" width="490" height="327" /></a></p>
<p>Unfortunately, there’s something about how the keys respond to quick, light touch typing that I’m having a difficult time acclimating to. I’ve had adjustment periods with other keyboards in the past, so I’m hoping time will improve my ability to coax the desired result out of this one too.</p>
<h3>More to come</h3>
<p>This post has outlined my very initial impressions of using the UX31 for a few hours. I’ll be continuing to use it over the next couple of months and will publish another post after a few weeks and then a final review after a full two months of use. I hope that the end result is that I’ll be able to shelve my MacBook Air, but I’ll let you know how it turns out one way or the other.</p>
<h3>How about those photos?</h3>
<p>Those photos of the UX31 looked great, didn&#8217;t they? Almost&#8230; Professional. Well, that&#8217;s because they are. My good friends at <a href="http://www.35atlanta.com/" target="_blank">35 Atlanta</a> came over, set up studio in my house, and took 55 amazing photos of the UX31 for me to use in these posts. If you need photos of just about any kind, check them out.</p>
<div class="lqm_ad" lqm_publisher="lqm.encosia.site" lqm_zone="ron" lqm_format="1x1"></div>
<p>Related posts:<ol>
<li><a href='http://encosia.com/a-month-with-my-zenbook-ux31/' rel='bookmark' title='A month with my Zenbook UX31'>A month with my Zenbook UX31</a></li>
<li><a href='http://encosia.com/someone-should-copy-these-4-features-from-the-zenbook/' rel='bookmark' title='Someone should copy these 4 features from the Zenbook'>Someone should copy these 4 features from the Zenbook</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/the-asus-zenbook-ux31-initial-impressions/">The ASUS Zenbook UX31: Initial impressions</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/the-asus-zenbook-ux31-initial-impressions/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=vF4J2LEzkFw:zeBg4n0CvMo:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=vF4J2LEzkFw:zeBg4n0CvMo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=vF4J2LEzkFw:zeBg4n0CvMo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=vF4J2LEzkFw:zeBg4n0CvMo:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/vF4J2LEzkFw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/the-asus-zenbook-ux31-initial-impressions/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		<feedburner:origLink>http://encosia.com/the-asus-zenbook-ux31-initial-impressions/</feedburner:origLink></item>
		<item>
		<title>Adding your own callbacks to existing JavaScript functions</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/mZ6gyCZJm28/</link>
		<comments>http://encosia.com/adding-your-own-callbacks-to-existing-javascript-functions/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 20:08:31 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1242</guid>
		<description><![CDATA[Hey Dave, is there a way to create an event handler so when .tmpl() is done it will fire a function? I&#8217;m trying to make it global, so I was hoping I could say, when ANY template gets done, do this&#8230; The question of how to retroactively add hooks before and/or after a pre-existing JavaScript [...]
Related posts:<ol>
<li><a href='http://encosia.com/how-to-easily-enhance-your-existing-tables-with-simple-css/' rel='bookmark' title='How to easily enhance your existing tables with simple CSS'>How to easily enhance your existing tables with simple CSS</a></li>
<li><a href='http://encosia.com/using-external-templates-with-jquery-templates/' rel='bookmark' title='Using external templates with jQuery Templates'>Using external templates with jQuery Templates</a></li>
<li><a href='http://encosia.com/composition-with-jquery-templates-why-and-how/' rel='bookmark' title='Composition with jQuery Templates: Why and How'>Composition with jQuery Templates: Why and How</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<blockquote><p>Hey Dave, is there a way to create an event handler so when .tmpl() is done it will fire a function? I&#8217;m trying to make it global, so I was hoping I could say, when ANY template gets done, do this&#8230;</p></blockquote>
<p>The question of how to retroactively add hooks before and/or after a pre-existing JavaScript function executes is one that comes up from time to time. Whether it&#8217;s a simple method like <code>tmpl()</code>, a server-generated script artifact, or a function in a third-party script, <strong>sometimes it&#8217;s desirable to alter a JavaScript function without access to change the original declaration of the function</strong>.</p>
<p>One of the handy things about JavaScript is that you can combine its functional and dynamic aspects to make surprisingly quick work of tasks like this one. Doing so is fairly straightforward, but it involves an approach you might not consider if you&#8217;re more familiar with languages that lack JavaScript&#8217;s unique features.</p>
<p>In this post, I&#8217;ll briefly cover a few examples of how to &#8220;patch&#8221; existing JavaScript functions with callbacks. We&#8217;ll begin with simple examples, then address an issue that stems from applying this approach to jQuery plugins, and finish with a more elegant way to handle the problem of patching functions that accept parameters.</p>
<h3>A simple() example</h3>
<p>Let&#8217;s start with the simplest possible example, a function that accepts no arguments and returns nothing:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> simple<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// I am a black box.</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Maybe that function is pre-defined and emitted by server-side code. Maybe it&#8217;s part of a script you&#8217;re referencing from a public CDN. For whatever reason, assume that this function is part of your page, but that you don&#8217;t have the ability to directly change its code.</p>
<p>If you need to run some of your own code before and/or after any time the <code>simple()</code> function is called, you can use a technique called <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkey patching</a> to achieve that without access to the original function declaration.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Get a reference to the previously defined simple() function.</span>
<span style="color: #003366; font-weight: bold;">var</span> oldSimple <span style="color: #339933;">=</span> simple<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> simple<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// Code that runs before any call to simple() here.</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Make a call to the old/previous simple() function.</span>
  oldSimple<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Code that runs after any call to simple() here.</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Since functions are just like any other variable in JavaScript, it&#8217;s that simple.</p>
<p>Without touching the original <code>simple()</code> function declaration, this snippet has effectively redefined it anyway. Calls to the original function will also execute our before and after code now, unaware that anything has changed.</p>
<h3>Parameters and external &#8220;event&#8221; handlers</h3>
<p>If you want to apply this technique to a function that accepts parameters, you&#8217;ll also need to capture and relay those parameters.</p>
<p>Take this more complex function, for example:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> complex<span style="color: #009900;">&#40;</span>foo<span style="color: #339933;">,</span> bar<span style="color: #339933;">,</span> baz<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// An assortment of black boxes.</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>You could patch in a &#8220;before&#8221; event, parameters unimpeded, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> oldComplex <span style="color: #339933;">=</span> complex<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Capture the parameters that the original complex()</span>
<span style="color: #006600; font-style: italic;">//  function expects.</span>
<span style="color: #003366; font-weight: bold;">function</span> complex<span style="color: #009900;">&#40;</span>foo<span style="color: #339933;">,</span> bar<span style="color: #339933;">,</span> baz<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// Call onBeforeComplex() if it's defined when this runs, and</span>
  <span style="color: #006600; font-style: italic;">//  pass a copy of the parameters that complex() was called with.</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onBeforeComplex <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onBeforeComplex<span style="color: #009900;">&#40;</span>foo<span style="color: #339933;">,</span> bar<span style="color: #339933;">,</span> baz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Call the original function, parameters included.</span>
  oldComplex<span style="color: #009900;">&#40;</span>foo<span style="color: #339933;">,</span> bar<span style="color: #339933;">,</span> baz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Using a separate <code>onBeforeComplex()</code> function instead of inline code isn&#8217;t necessary, but I prefer that approach. Now, you can drop this code into a script include anywhere after <code>complex()</code> is defined and then declare the &#8220;handler&#8221; function anywhere on the page (or not at all).</p>
<p>Passing foo, bar, and baz to <code>onBeforeComplex()</code> is optional, of course, but it&#8217;s usually helpful to know something about what sort of call triggered the event.</p>
<h3>Applying this to jQuery plugins</h3>
<p>Now let&#8217;s apply this technique to the real-world problem of updating <code>tmpl()</code>. Doing that isn&#8217;t much more difficult than the previous example, but we do need to identify the method&#8217;s signature first so that we can apply the patch.</p>
<p>Digging into the last version of <a href="https://github.com/jquery/jquery-tmpl/blob/master/jquery.tmpl.js#L80" target="_blank">jQuery.tmpl.js on GitHub</a>, the function we&#8217;ll need to override can be found beginning on line 80:</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2012/01/original-tmpl-function.png" rel="attachment"><img src="http://encosia.com/blog/wp-content/uploads/2012/01/original-tmpl-function-sm.png" style="border: 1px solid #ccc;" /></a></p>
<p>So, the function we&#8217;ll need to patch is <code>jQuery.fn.tmpl</code>. Given the previous examples, you might thing it would be as easy as this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> oldTmpl <span style="color: #339933;">=</span> jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span><span style="color: #339933;">;</span>
&nbsp;
jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onBeforeTmpl <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onBeforeTmpl<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  oldTmpl<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Unfortunately, that will break <code>tmpl()</code></strong> (in two separate ways, no less).</p>
<h3>jQuery plugins make &#8220;this&#8221; more complicated</h3>
<p>Applying the monkey patching approach to functions that operate on and return <a href="http://docs.jquery.com/Types#jQuery" target="_blank">jQuery collection objects</a>, such as the <code>tmpl()</code> plugin that led to this post, requires extra consideration. The crux of jQuery&#8217;s fluent API is that chainable jQuery methods both operate upon and return an instance of the jQuery object.</p>
<p>Now that we&#8217;re interjecting an additional level of abstraction, we need to be sure to maintain the scope of <code>this</code> down into the original jQuery plugin method <em>and</em> preserve the original function&#8217;s return value. <strong>Otherwise, our intermediary function will break jQuery&#8217;s chaining.</strong></p>
<p>Using <a href="http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply" target="_blank"><code>apply()</code></a> to call the original function allows us to control its <code>this</code> value:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> oldTmpl <span style="color: #339933;">=</span> jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Note: the parameters don't need to be named the same as in the</span>
<span style="color: #006600; font-style: italic;">//  original. This could just as well be function(a, b, c).</span>
jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onBeforeTmpl <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onBeforeTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Make a call to the old tmpl() function, maintaining the value </span>
  <span style="color: #006600; font-style: italic;">//  of &quot;this&quot; and its expected function arguments.</span>
  <span style="color: #003366; font-weight: bold;">var</span> tmplResult <span style="color: #339933;">=</span> oldTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onAfterTmpl <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onAfterTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>data<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> parentItem<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Returning the result of tmpl() back so that it's actually </span>
  <span style="color: #006600; font-style: italic;">//  useful, but also to preserve jQuery's chaining.</span>
  <span style="color: #000066; font-weight: bold;">return</span> tmplResult<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>By capturing the return value of the original <code>tmpl()</code> function and returning that back to the original caller, chaining is preserved at that previous level. That&#8217;s particularly important in this specific example because that return value is the rendered template.</p>
<h3>Better argument handling</h3>
<p>If you&#8217;re like me, explicitly capturing and passing each individual function parameter doesn&#8217;t feel great. Not only is it extra work to determine how many parameters a method accepts, but our patched version of <code>tmpl()</code> would stop working correctly if the original were updated to begin accepting additional parameters.</p>
<p>We can improve this situation easily enough by taking advantage of JavaScript&#8217;s built-in way to capture all of the parameters that were passed to a function. Aptly named <a href="https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments" target="_blank"><code>arguments</code></a>, this so-called array-like object is perfect for eliminating the explicit plumbing code to pass parameters between the patched function and the original.</p>
<p>Even better, arguments will capture all the parameters passed into a function even if that function&#8217;s declaration doesn&#8217;t accept parameters at all. So, now there&#8217;s no need to worry about matching the original&#8217;s function signature:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> oldTmpl <span style="color: #339933;">=</span> jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span><span style="color: #339933;">;</span>
&nbsp;
jQuery.<span style="color: #660066;">fn</span>.<span style="color: #660066;">tmpl</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onBeforeTmpl <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onBeforeTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> tmplResult <span style="color: #339933;">=</span> oldTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> onAfterTmpl <span style="color: #339933;">===</span> <span style="color: #3366CC;">'function'</span><span style="color: #009900;">&#41;</span>
    onAfterTmpl.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> tmplResult<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Throw that code on a page, anywhere after the reference to jquery.tmpl.js, and then all existing usages of <code>tmpl()</code> will begin triggering the before and after &#8220;events&#8221;.</p>
<h3>Conclusion</h3>
<p>We took a circuitous route to get here, but I hope you agree that it was worthwhile to build the solution up step by step. Even if you don&#8217;t need to patch an event into <code>tmpl()</code>, you might be surprised how often this technique comes in handy once you&#8217;re keeping the possibility in mind.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/how-to-easily-enhance-your-existing-tables-with-simple-css/' rel='bookmark' title='How to easily enhance your existing tables with simple CSS'>How to easily enhance your existing tables with simple CSS</a></li>
<li><a href='http://encosia.com/using-external-templates-with-jquery-templates/' rel='bookmark' title='Using external templates with jQuery Templates'>Using external templates with jQuery Templates</a></li>
<li><a href='http://encosia.com/composition-with-jquery-templates-why-and-how/' rel='bookmark' title='Composition with jQuery Templates: Why and How'>Composition with jQuery Templates: Why and How</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/adding-your-own-callbacks-to-existing-javascript-functions/">Adding your own callbacks to existing JavaScript functions</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/adding-your-own-callbacks-to-existing-javascript-functions/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=mZ6gyCZJm28:FOC93Vt_RXQ:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=mZ6gyCZJm28:FOC93Vt_RXQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=mZ6gyCZJm28:FOC93Vt_RXQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=mZ6gyCZJm28:FOC93Vt_RXQ:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/mZ6gyCZJm28" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/adding-your-own-callbacks-to-existing-javascript-functions/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://encosia.com/adding-your-own-callbacks-to-existing-javascript-functions/</feedburner:origLink></item>
		<item>
		<title>Five years of Encosia</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/S148V2sKjcI/</link>
		<comments>http://encosia.com/five-years-of-encosia/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 22:50:02 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1230</guid>
		<description><![CDATA[As I ponder the title of this post, I&#8217;m conflicted. I clearly remember writing last year’s post and thinking that it didn&#8217;t seem like four years could have possibly passed since I started publishing here. As I write this one, I find myself feeling like it&#8217;s surely been much longer than five years. I guess [...]
Related posts:<ol>
<li><a href='http://encosia.com/3-years-of-encosia-the-best-of-2009-and-my-gratitude/' rel='bookmark' title='3 years of Encosia, the best of 2009, and my gratitude'>3 years of Encosia, the best of 2009, and my gratitude</a></li>
<li><a href='http://encosia.com/4-years-of-encosia-and-the-best-of-2010/' rel='bookmark' title='4 years of Encosia, and the best of 2010'>4 years of Encosia, and the best of 2010</a></li>
<li><a href='http://encosia.com/announcing-the-2010-encosia-holiday-giveaway/' rel='bookmark' title='Announcing the 2010 Encosia Holiday Giveaway'>Announcing the 2010 Encosia Holiday Giveaway</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://encosia.com/blog/wp-content/uploads/2011/12/five-year-birthday.jpg" width="162" height="265" align="left" style="margin-right: 10px; margin-top: 5px;" />As I ponder the title of this post, I&#8217;m conflicted.</p>
<p>I clearly remember writing last year’s post and thinking that it didn&#8217;t seem like four years could have possibly passed since I started publishing here. As I write this one, I find myself feeling like it&#8217;s surely been much longer than five years.</p>
<p>I guess you could say 2011 has been a long year?</p>
<p>Relativity aside, this week saw the fifth anniversary of the night that I hastily threw this site together and published my first post. So, I guess it&#8217;s that time again.</p>
<h3>Site stats</h3>
<p>Page views are far from a perfect metric for measuring the progress of a site like this one, but it’s one of the few consistent, long-term metrics I have. Aggregators come and go, RSS is giving way to Twitter, and social media has decentralized the conversation that would have taken place in a post’s comments years ago (A change for the worse, in my opinion). So, I measure what I can.</p>
<p>Pleasantly enough, the stats have continued to be encouraging.</p>
<p><a href="http://encosia.com/blog/wp-content/uploads/2011/12/encosia-2011-stats.png" rel="attachment"><img style="border: 1px solid #ccc;" src="http://encosia.com/blog/wp-content/uploads/2011/12/encosia-2011-stats-sm.png"></a></p>
<p>Since last year&#8217;s post, traffic has grown by a healthy 28%. That&#8217;s <strong>just over 1.6 million page views since this time last year</strong>. Insignificant compared to some sites, but I find it truly humbling to think that my little corner of the Internet has been visited 1.2 million times in the last year. Maybe even more incredible to me is that nearly 400,000 of those visits were apparently return visits. Frankly, I have a hard time rationalizing that number.</p>
<p>Interestingly enough, I seem to have benefited from Google’s recent algorithm tweaks aimed at content farms. I saw two distinct, sustained bumps in search traffic this year. I won’t complain…</p>
<h3>The Best Posts of 2011</h3>
<p>I considered omitting this section this year (and the year-end post itself for that matter). I figured that I probably care more about this than you do and there’s no point wasting everyone’s time, but <a href="https://twitter.com/#!/jbrinkman/statuses/149632801875050496" target="_blank">Joe Brinkman disagrees</a>.</p>
<p>If at least one person finds it useful to have a quick reference of the year’s most popular posts, then who I am to argue?</p>
<p><a href="http://encosia.com/in-javascript-curly-brace-placement-matters-an-example/">In JavaScript, curly brace placement matters: An example</a> – This post received the most traffic, primarily due to spending some time on the front page of Hacker News and the JavaScript subreddit. Frankly, I didn’t intend for it to capture the level of attention that it did at all. It was targeted at developers less experienced with JavaScript, but it ended up igniting a light-to-medium religious war around the Allman vs. K&amp;R debate among more seasoned developers instead.</p>
<p>Next year I should post about tabs vs. spaces.</p>
<p><a href="http://encosia.com/jquery-1-6-2-syntax-error-you-may-be-the-victim-of-seo/">jQuery 1.6.2 syntax error? You may be the victim of SEO.</a> – Similarly, this post did well in the stats simply because it spent some time at the top of Hacker News. Though I did have to endure the predictable abuse from the denizens of Hacker News, exposure there was enough to get some attention focused on the issue and ultimately get it resolved. I’d say that was worth suffering <a href="http://tirania.org/blog/archive/2011/Feb-17.html" target="_blank">the “Well, Actually” crowd</a> for a couple days.</p>
<p><a href="http://encosia.com/cripple-the-google-cdns-caching-with-a-single-character/">Cripple the Google CDN’s caching with a single character</a> – Yet another post in this lineup by virtue of the time it spent on the front page of Hacker News. Astute readers correctly pointed out that the Google CDN’s HTTPS assets <em>are</em> served with a header that allows them to be cached. Unfortunately, too many people got stuck on that inaccuracy and missed the larger point.</p>
<p>Since HTTP-delivered scripts aren’t eligible for use as cache hits for HTTPS references to the same script (and vice versa), using the HTTPS reference isolates the potential cross-site caching benefit to only users who have the HTTPS-served script cached. With the vast majority of jQuery CDN references being of the HTTP variety, it’s important to understand that and not use the HTTPS reference unless you actually need it.</p>
<p>Even better, use the protocol-less reference and never worry about it again.</p>
<p><a href="http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/">ASP.NET web services mistake: manual JSON serialization</a> – This is one that I felt strongly about. I had been seeing more and more code floating around that used JavaScriptSerializer or DataContractJsonSerializer to manually handle the encoding to and from JSON in ASP.NET services that were automatically doing that anyway. The result being nasty double-serialization of the data, and/or sending values in and out of methods as strings instead of using the strongly-typed objects that the data was usually based on ultimately anyway.</p>
<p>Fun fact: I wrote and published this post, from start to finish, while attending MIX11. </p>
<p><a href="http://encosia.com/use-jquery-to-extract-data-from-html-lists-and-tables/">Use jQuery to extract data from HTML lists and tables</a> – This post was somewhat niche, but I‘m a fan of the general approach of using list comprehension methods against the DOM. Particularly, map() is fantastically well-suited to dealing with HTML and the DOM. I’ve subsequently linked to this post to help explain the solutions to all sorts of tangentially related problems. I hope that many of the people who read this post were able to extrapolate the more general usefulness of map() and specifically jQuery’s implementation of it for dealing with selections of HTML elements.</p>
<h3>What I expect from 2012</h3>
<p><strong>JavaScript is going to continue exploding in popularity</strong>. If you’re a web developer and haven’t taken a serious look at <a href="http://nodejs.org/" target="_blank">Node.js</a> yet, now’s the time. JavaScript is not without flaws, but I think full-stack JavaScript is the future for a lot of platforms and web development in particular.</p>
<p><a href="http://ejohn.org/blog/javascript-as-a-first-language/" target="_blank">As new developers begin learning about development</a>, who would choose a platform that requires learning a different client-side and server-side language if a solid platform using a single language from start to finish existed?</p>
<p>Of course, that was part of the promise of failed technologies like Java applets and Silverlight, but JavaScript has the luxury of already being pervasive, native, and well-integrated in every user’s browser. Compared to conquering that client-side morass, ironing out the server-side platform wrinkles and maturing a web framework or two is nothing.</p>
<p><strong>Mobile and touch will change how we approach web development</strong>. It’s hard to believe that designing for touch was an obscure niche when I started this site five years ago. More than just avoiding hover menus and making click targets large enough for fat fingers, I think there’s still undiscovered potential for touch and gesture based UIs that we’re going to see begin making its way onto the web as touch input becomes more ubiquitous on a wide range of devices.</p>
<p>Of course, you can’t touch what you can’t see. Making sites work on a wide variety of screen sizes is more important now than ever. Using CSS media queries to build responsive layouts takes a bit of acclimation, but <a href="http://mediaqueri.es/" target="_blank">the results are absolutely worthwhile</a>. While responsive layouts aren’t new, I think they will become much more mainstream in the next year. Sites not taking advantage of media queries will probably seem as quaint as sites currently using table layouts soon.</p>
<p><strong>Windows 8 is going to be huge</strong>. I don’t know if it’ll be a huge success or a huge flop, but I think it’s safe to say there’s not much middle ground between the two outcomes. It’s certainly a bold move.</p>
<p>As an iPhone, iPad, and MacBook Air owner, I would be overjoyed if I could migrate from those devices to Windows-based devices of comparable quality. I&#8217;m rooting for Microsoft to pull this one off.</p>
<h3>Thanks</h3>
<p>As always, thank you for lending me your eyeballs for a few minutes.</p>
<p>If you’re reading this paragraph, there’s a decent chance that I owe you a bit of gratitude for your support over the past year, be it pointing someone here to solve a problem, a retweet or two, or just sparing me your attention.</p>
<p>Thanks.</p>
<h3>And you?</h3>
<p>How was your 2011? What technologies helped you succeed or presented challenges for you this year? What do you think’s going to be most important in 2012?</p>
<p>I’m interested to hear what you think. Leave a comment or leave a link to your own year-end post if you’d like.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/3-years-of-encosia-the-best-of-2009-and-my-gratitude/' rel='bookmark' title='3 years of Encosia, the best of 2009, and my gratitude'>3 years of Encosia, the best of 2009, and my gratitude</a></li>
<li><a href='http://encosia.com/4-years-of-encosia-and-the-best-of-2010/' rel='bookmark' title='4 years of Encosia, and the best of 2010'>4 years of Encosia, and the best of 2010</a></li>
<li><a href='http://encosia.com/announcing-the-2010-encosia-holiday-giveaway/' rel='bookmark' title='Announcing the 2010 Encosia Holiday Giveaway'>Announcing the 2010 Encosia Holiday Giveaway</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/five-years-of-encosia/">Five years of Encosia</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/five-years-of-encosia/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=S148V2sKjcI:yZyq7zCsmGE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=S148V2sKjcI:yZyq7zCsmGE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=S148V2sKjcI:yZyq7zCsmGE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=S148V2sKjcI:yZyq7zCsmGE:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/S148V2sKjcI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/five-years-of-encosia/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://encosia.com/five-years-of-encosia/</feedburner:origLink></item>
		<item>
		<title>Using CORS to access ASP.NET services across domains</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/8NqtWwXnjFY/</link>
		<comments>http://encosia.com/using-cors-to-access-asp-net-services-across-domains/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 06:25:26 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1223</guid>
		<description><![CDATA[Work on client-side applications long enough and it&#8217;s just about inevitable that you&#8217;ll eventually want to make an AJAX request that breaches the browser&#8217;s XMLHttpRequest security restrictions. Limitations on cross-domain requests are great when they&#8217;re preventing malicious sites from malfeasing, but are a thorn in the side when they complicate your legitimate applications. Traditionally, direct [...]
Related posts:<ol>
<li><a href='http://encosia.com/save-yourself-some-typing-when-you-call-asp-net-services/' rel='bookmark' title='Save yourself some typing when you call ASP.NET services'>Save yourself some typing when you call ASP.NET services</a></li>
<li><a href='http://encosia.com/asmx-and-json-common-mistakes-and-misconceptions/' rel='bookmark' title='ASMX and JSON &ndash; Common mistakes and misconceptions'>ASMX and JSON &ndash; Common mistakes and misconceptions</a></li>
<li><a href='http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/' rel='bookmark' title='Using jQuery to Consume ASP.NET JSON Web Services'>Using jQuery to Consume ASP.NET JSON Web Services</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://encosia.com/blog/wp-content/uploads/2011/12/successful-cors-request.png" alt="Successfully completing a cross-domain request to an ASMX service using CORS" title="Successful CORS request" style="border: 1px solid #ccc;" /></p>
<p>Work on client-side applications long enough and it&#8217;s just about inevitable that you&#8217;ll eventually want to make an AJAX request that breaches the browser&#8217;s XMLHttpRequest security restrictions. Limitations on cross-domain requests are great when they&#8217;re preventing malicious sites from malfeasing, but are a thorn in the side when they complicate your legitimate applications.</p>
<p>Traditionally, direct communication across the same-origin boundary required using a rickety (though clever) workaround called JSONP. JSONP is a reasonable compromise if all you need to do is make blind requests to a third-party API like Twitter, but comes up short if you need to use any HTTP verb other than GET. Of course, that&#8217;s <a href="http://weblogs.asp.net/scottgu/archive/2007/04/04/json-hijacking-and-how-asp-net-ajax-1-0-mitigates-these-attacks.aspx" target="_blank">a deal-breaking issue when you&#8217;re working with ASMX ScriptServices or ASPX page methods</a>.</p>
<p>Luckily, a relatively new feature has been making its way into browsers which provides a robust solution to the cross-domain AJAX problem: <strong>CORS</strong>.</p>
<p>In this post, I&#8217;m going to show you how to recognize exactly which requests are cross-origin, how to enable CORS for your ASP.NET site, and the extra configuration necessary when you&#8217;re working with ASP.NET&#8217;s JSON-enabled services.</p>
<p><em>Before we get started, I want to emphasize that this approach won’t work with any version of IE prior to IE10. If supporting older versions of IE is a requirement in your target environment, you’re stuck with something like JSONP or <a href="http://encosia.com/use-asp-nets-httphandler-to-bridge-the-cross-domain-gap/" target="_blank">a server-side proxy</a>. This will work in any version of IE if Chrome Frame is installed and enabled by your site/server though.</em></p>
<h3>Understanding what constitutes a different “origin”</h3>
<p>When it comes to making cross-origin AJAX requests, it&#8217;s helpful to understand which requests actually are cross-origin. Of course, a request from a page served under one domain to a resource on an entirely different one definitely falls under the umbrella of cross-origin:</p>
<p><img src="http://encosia.com/blog/wp-content/uploads/2011/12/failed-cors-request.png" width="490" style="border: 1px solid #ccc;" /></p>
<p>However, the common moniker for these requests, <em>cross-domain</em>, tends to be misleading. While a request from one domain to another is obviously cross-origin, browsers are much more picky than that.</p>
<p>For example, a request from <code>foo.domain.com</code> to <code>bar.domain.com</code> is just as much cross-origin request as one to <code>abc.com</code>. That’s not quite as intuitive as the traditional cross-domain scenario, but requires the same consideration.</p>
<p>A less obvious troublemaker is making a request from <code>localhost:8080</code> to <code>localhost:8081</code>, which XMLHttpRequest’s security restrictions will also deny you from making. That’s a particularly troublesome scenario for ASP.NET developers since Visual Studio is all too happy to help you spin up a separate services/API project almost transparently hosted at its own separate port.</p>
<p>The easiest way to determine whether a particular request will fall under the umbrella of cross origin resource sharing is to <strong>compare the portion of both addresses appearing before the first forward slash</strong>. Any difference before the first forward slash, including the port, protocol (HTTP vs. HTTPS), and sub-domain, will thwart a traditional XHR-based AJAX request.</p>
<h3>Enabling CORS for an ASP.NET site</h3>
<p>Though the conventional wisdom about cross-domain or cross-origin requests has long been JSONP or nothing, a solution called <a href="http://www.w3.org/TR/cors/" target="_blank">Cross-Origin Resource Sharing</a> has gained broad support in modern browsers over the past couple years. This standard defines a set of HTTP headers that a server can use to instruct browsers that it’s okay for certain XMLHttpRequest requests to that server to cross the same-origin boundary.</p>
<p>In the broadest case, enabling CORS for an ASP.NET site is simple. The <a href="http://enable-cors.org/" target="_blank">enable-cors.org</a> site has handy list of concise examples of how to configure a variety of servers for CORS, including IIS. For sites hosted on IIS7.0+ and Integrated Pipeline, enabling CORS is as simple as adding this to the site’s web.config:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;system.webserver<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;httpprotocol<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;customheaders<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Access-Control-Allow-Origin&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;*&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/customheaders<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/httpprotocol<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/system.webserver<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>That simple change gets you half way there. A regular GET request for an ASPX page&#8217;s HTML would work now, for example. Unfortunately, the Content-Type necessary for working with ASMX ScriptServices throws a new wrench in the works:</p>
<p><img src="http://encosia.com/blog/wp-content/uploads/2011/12/almost-successful-cors-request.png" alt="A partially successful CORS request to an ASMX ScriptService" title="Almost successful CORS request" width="490" height="106" style="border: 1px solid #ccc;" /></p>
<p>As it turns out, requests to ASP.NET’s JSON-enabled endpoints require one last configuration step to allow the request to go through unimpeded.</p>
<h3>Access-Control-Allow-Headers</h3>
<p>Sending the <code>Access-Control-Allow-Origin</code> header allows basic cross-origin access, but calling ASP.NET services like ASMX ScriptServices, ASPX page methods, and WCF services with AspNetCompatibilityRequirements enabled <a href="http://encosia.com/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/" target="_blank">requires jumping through a few more hoops</a>. Namely, sending a specific Content-Type header of <code>application/json</code>.</p>
<p>One of the security precautions that the CORS specification includes is that browsers must tightly control what&#8217;s sent along with these cross-origin requests. Among the items that must be explicitly allowed: any but the most basic HTTP headers, including <code>Content-Type</code>.</p>
<p>In order for CORS requests to specify their Content-Type, your site needs to respond with one additional CORS header: <code>Access-Control-Allow-Headers</code></p>
<p>That brings the web.config modifications necessary to this:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;system.webserver<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;httpprotocol<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;customheaders<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Access-Control-Allow-Origin&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;*&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Access-Control-Allow-Headers&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/customheaders<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/httpprotocol<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/system.webserver<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>And finally, it&#8217;s possible to use the same, familiar jQuery <code>$.ajax()</code> syntax to request our service from same- and cross-domain origins alike:</p>
<p><img src="http://encosia.com/blog/wp-content/uploads/2011/12/successful-cors-request.png" alt="A successful CORS request to an ASMX service with jQuery" title="Successful CORS request" width="490" height="170" style="border: 1px solid #ccc;" /></p>
<h3>Conclusion</h3>
<p>Even as we&#8217;re teetering at the precipice of 2012, CORS is still a fairly new feature and lacks ubiquitous support. IE10 should support CORS as fully as Chrome and Firefox already do, but the XDomainRequest implementation in earlier versions of IE does not (to my knowledge) support <code>Access-Control-Allow-Headers</code>, which makes it all but useless in this scenario.</p>
<p>If you&#8217;re comfortable leaving the comfy confines of XMLHttpRequest and jQuery&#8217;s <code>$.ajax</code>, a more cross-browser friendly solution does exist: <a href="http://easyxdm.net/wp/" target="_blank">easyXDM</a>. I haven&#8217;t personally used easyXDM beyond a bit of experimentation, but the approach it takes in older browsers is one that has been proven to be solid by similar libraries like <a href="http://socket.io/" target="_blank">Socket.IO</a>.</p>
<p>However, if you&#8217;re working in an environment where you can mandate Chrome (or Chrome Frame in IE9-) and/or Firefox as the browser of choice, CORS is an invaluable addition to your bag of tricks (I feel like I&#8217;ve typed that phrase in another post recently&#8230;). I hope this post will help you get your feet wet with this new technology which seems to get more lip service than actual usage.</p>
<h3>Get the source</h3>
<p>If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.</p>
<p><a href="https://github.com/Encosia/Encosia-Samples-ASMX-CORS/tree/AsPublished" target="_blank" class="generalButton" style="width: 220px; float: left; text-align: center;">Browse on GitHub</a><a href="https://github.com/Encosia/Encosia-Samples-ASMX-CORS/zipball/AsPublished" target="_blank" class="generalButton" style="width: 220px; float: right; text-align: center;">Download the ZIP</a></p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/save-yourself-some-typing-when-you-call-asp-net-services/' rel='bookmark' title='Save yourself some typing when you call ASP.NET services'>Save yourself some typing when you call ASP.NET services</a></li>
<li><a href='http://encosia.com/asmx-and-json-common-mistakes-and-misconceptions/' rel='bookmark' title='ASMX and JSON &ndash; Common mistakes and misconceptions'>ASMX and JSON &ndash; Common mistakes and misconceptions</a></li>
<li><a href='http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/' rel='bookmark' title='Using jQuery to Consume ASP.NET JSON Web Services'>Using jQuery to Consume ASP.NET JSON Web Services</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/using-cors-to-access-asp-net-services-across-domains/">Using CORS to access ASP.NET services across domains</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/using-cors-to-access-asp-net-services-across-domains/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=8NqtWwXnjFY:2kjIg7KvB9A:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=8NqtWwXnjFY:2kjIg7KvB9A:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=8NqtWwXnjFY:2kjIg7KvB9A:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=8NqtWwXnjFY:2kjIg7KvB9A:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/8NqtWwXnjFY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/using-cors-to-access-asp-net-services-across-domains/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://encosia.com/using-cors-to-access-asp-net-services-across-domains/</feedburner:origLink></item>
		<item>
		<title>Help me organize my posts about using jQuery with ASP.NET</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/TIeTEaNW6uc/</link>
		<comments>http://encosia.com/help-me-organize-my-posts-about-using-jquery-with-asp-net/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 19:12:22 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1219</guid>
		<description><![CDATA[One of the longest running themes here has been the compelling intersection between ASP.NET and jQuery. Beginning with my post about using jQuery to circumvent ASP.NET AJAX&#8217;s client-side apparatus for calling ASMX services, I&#8217;ve been writing about using ASP.NET and jQuery since the Spring of 2008. As these related posts have accumulated over the years, [...]
Related posts:<ol>
<li><a href='http://encosia.com/best-of-2008-5-most-popular-posts/' rel='bookmark' title='Best of 2008: 5 most popular posts'>Best of 2008: 5 most popular posts</a></li>
<li><a href='http://encosia.com/best-of-2007-5-most-popular-posts-and-contest-winners/' rel='bookmark' title='Best of 2007: 5 most popular posts (and contest winners)'>Best of 2007: 5 most popular posts (and contest winners)</a></li>
<li><a href='http://encosia.com/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/' rel='bookmark' title='3 mistakes to avoid when using jQuery with ASP.NET AJAX'>3 mistakes to avoid when using jQuery with ASP.NET AJAX</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img alt="Image by OZinOH on Flickr" src="http://encosia.com/blog/wp-content/uploads/2011/11/library-catalog-cabinet.jpg" style="border: 1px solid #ccc;" width="490" /></p>
<p>One of the longest running themes here has been the compelling intersection between ASP.NET and jQuery. Beginning with <a href="http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/" target="_blank">my post about using jQuery to circumvent ASP.NET AJAX&#8217;s client-side apparatus for calling ASMX services</a>, I&#8217;ve been writing about using ASP.NET and jQuery since the Spring of 2008.</p>
<p>As these related posts have accumulated over the years, I&#8217;ve made an effort to weave a thread of cross-links between them posts where appropriate. However, it&#8217;s nearly impossible to anticipate every possible entry point and subsequent path that someone might find themselves following here.</p>
<p>So, I&#8217;ve decided to finally do what I should have done a year or two ago: Create a top-level index to organize and improve the accessibility of my content for ASP.NET developers interested in integrating jQuery into their sites.</p>
<p>You can see my first draft of that here: <a href="http://encosia.com/jquery-for-the-asp-net-developer/" title="jQuery for the ASP.NET Developer" target="_blank">jQuery for the ASP.NET Developer</a></p>
<p>Unlike the other content here, I&#8217;m publishing this one <em>long</em> before it&#8217;s &#8220;finished&#8221;. My hope is that I can solicit early feedback to help better construct a useful narrative while the document is still in its formative stages. So, if you have any feedback on the current page or what you think should ultimately be there, please leave me a comment on either this post or that page, <a href="http://encosia.com/contact/" target="_blank">contact me directly</a>, or even <a href="http://twitter.com/Encosia" target="_blank">@mention it my way on Twitter</a>.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/best-of-2008-5-most-popular-posts/' rel='bookmark' title='Best of 2008: 5 most popular posts'>Best of 2008: 5 most popular posts</a></li>
<li><a href='http://encosia.com/best-of-2007-5-most-popular-posts-and-contest-winners/' rel='bookmark' title='Best of 2007: 5 most popular posts (and contest winners)'>Best of 2007: 5 most popular posts (and contest winners)</a></li>
<li><a href='http://encosia.com/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/' rel='bookmark' title='3 mistakes to avoid when using jQuery with ASP.NET AJAX'>3 mistakes to avoid when using jQuery with ASP.NET AJAX</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/help-me-organize-my-posts-about-using-jquery-with-asp-net/">Help me organize my posts about using jQuery with ASP.NET</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/help-me-organize-my-posts-about-using-jquery-with-asp-net/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=TIeTEaNW6uc:RP8M3iXAt7o:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=TIeTEaNW6uc:RP8M3iXAt7o:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=TIeTEaNW6uc:RP8M3iXAt7o:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=TIeTEaNW6uc:RP8M3iXAt7o:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/TIeTEaNW6uc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/help-me-organize-my-posts-about-using-jquery-with-asp-net/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://encosia.com/help-me-organize-my-posts-about-using-jquery-with-asp-net/</feedburner:origLink></item>
		<item>
		<title>Learn from my Express.js HTTP status code blunder</title>
		<link>http://feeds.encosia.com/~r/Encosia/~3/RUO_mqr85Kw/</link>
		<comments>http://encosia.com/learn-from-my-express-js-http-status-code-blunder/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 18:33:56 +0000</pubDate>
		<dc:creator>Dave Ward</dc:creator>
				<category><![CDATA[Express.js]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Node.js]]></category>

		<guid isPermaLink="false">http://encosia.com/?p=1202</guid>
		<description><![CDATA[If you&#8217;re like me, HTTP status code 200 Object] unknown probably doesn&#8217;t ring any bells. Of course, that&#8217;s mainly because it doesn&#8217;t exist. So, how did I end up with the screenshot above? I&#8217;ve been running with scissors again. It was one of the more popular web frameworks for Node.js that I cut myself with [...]
Related posts:<ol>
<li><a href='http://encosia.com/easy-incremental-status-updates-for-long-requests/' rel='bookmark' title='Easy incremental status updates for long requests'>Easy incremental status updates for long requests</a></li>
<li><a href='http://encosia.com/updated-see-how-i-used-firebug-to-learn-jquery/' rel='bookmark' title='Updated: See how I used Firebug to learn jQuery'>Updated: See how I used Firebug to learn jQuery</a></li>
<li><a href='http://encosia.com/4-aspnet-ajax-javascript-ui-functions-you-should-learn/' rel='bookmark' title='4 ASP.NET AJAX JavaScript UI methods you should learn'>4 ASP.NET AJAX JavaScript UI methods you should learn</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment" href="http://encosia.com/blog/wp-content/uploads/2011/11/broken-status.png"><img src="http://encosia.com/blog/wp-content/uploads/2011/11/broken-status-sm.png" width="490" height="110" style="border: 1px solid #999;" alt="Screenshot of the 200 Object] HTTP status code in Firebug" /></a></p>
<p>If you&#8217;re like me, HTTP status code <code>200 Object] unknown</code> probably doesn&#8217;t ring any bells. Of course, that&#8217;s mainly because it doesn&#8217;t exist.</p>
<p>So, how did I end up with the screenshot above? I&#8217;ve been running with scissors again. It was one of the more popular web frameworks for Node.js that I cut myself with this time: <a target="_blank" href="http://expressjs.com">Express.js</a></p>
<p>Unfortunately, a malformed status code like <code>200 Object]</code> will cause some browsers (including the version of Chrome I was using at the time) to refuse loading the page at all. That quickly elevated the importance of my strange status code from a trivial oddity to an annoying thorn in the side.</p>
<p>As it turns out, my code was running up against a documented Express feature and the remedy was simple enough.</p>
<h3>Status code: RTFM</h3>
<p>The site I was working on at the time is simple enough, built from a handful of views and a few supporting scripts that act as &#8220;models&#8221;. Unfortunately for me, the topic of this particular site led me to pass one of those models into a view using an object property named <code>status</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  Models.<span style="color: #660066;">getIndexViewModel</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>model<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066;">status</span><span style="color: #339933;">:</span> model <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>You can probably guess where my bizarre HTTP status code came from now, and a quick search through <a href="http://expressjs.com/guide.html#res.render()" target="_blank">the relevant Express documentation</a> confirms:</p>
<blockquote><p>This options object is also considered an “options” object. <strong>For example when you pass the status local, it’s not only available to the view, it sets the response status to this number.</strong> This is also useful if a template engine accepts specific options, such as debug, or compress. Below is an example of how one might render an error page, passing the status for display, as well as it setting res.statusCode.</p></blockquote>
<p>Head, meet desk.</p>
<p>Instead an HTTP status code, I was passing a JavaScript object to Express and it was trying to interpret the string representation of that object as an HTTP status code to apply to the response. In JavaScript, objects evaluate to a string value of <code>[object Object]</code>, which is how <code>Object]</code> ended up being sent down instead.</p>
<p>I didn&#8217;t take the time to dive into Express&#8217; source to determine why the <code>[object Object]</code> string ended up being split on the whitespace, with only the second half showing up in the actual response. The net takeaway is the same regardless of why: don&#8217;t pass <code>status</code> into your Express views unless you understand what that actually does.</p>
<h3>Everything&#8217;s easy in hindsight&#8230;</h3>
<p>In retrospect, it may seem painfully obvious that my choice of property names was the culprit, but I didn&#8217;t benefit from this post&#8217;s narrow context at the time.</p>
<p>I didn&#8217;t end up finding the issue until days after writing the code that caused the problem. Since the odd status code didn&#8217;t break anything while I was testing in Firefox, it wasn&#8217;t readily apparent that I had introduced a bug at all. By the time I tested in a browser that choked on the invalid status code, I was far removed from the relevant code, and it wasn&#8217;t as easy to debug as it might seem now.</p>
<p>I almost decided against posting this for fear of looking like a dunce, but I can&#8217;t be the only person that will run into this problem. So, I hope this post saves at least one person from running into the same self-inflicted injury that I did.</p>
<p>Related posts:<ol>
<li><a href='http://encosia.com/easy-incremental-status-updates-for-long-requests/' rel='bookmark' title='Easy incremental status updates for long requests'>Easy incremental status updates for long requests</a></li>
<li><a href='http://encosia.com/updated-see-how-i-used-firebug-to-learn-jquery/' rel='bookmark' title='Updated: See how I used Firebug to learn jQuery'>Updated: See how I used Firebug to learn jQuery</a></li>
<li><a href='http://encosia.com/4-aspnet-ajax-javascript-ui-functions-you-should-learn/' rel='bookmark' title='4 ASP.NET AJAX JavaScript UI methods you should learn'>4 ASP.NET AJAX JavaScript UI methods you should learn</a></li>
</ol></p><hr />

<p>You've been reading <a href="http://encosia.com/learn-from-my-express-js-http-status-code-blunder/">Learn from my Express.js HTTP status code blunder</a>, originally posted at <a href="http://encosia.com">Encosia</a>.  I hope you enjoyed it, and thanks for reading.</p>

<p>If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can <a href="http://encosia.com/learn-from-my-express-js-http-status-code-blunder/#post-commentblock">click here to jump directly to the comment section of this post</a>.</p><div class="feedflare">
<a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Encosia?i=RUO_mqr85Kw:jCVdIAACQjA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:aWKiLpGymzw"><img src="http://feeds.feedburner.com/~ff/Encosia?d=aWKiLpGymzw" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:30RXbuXOgYA"><img src="http://feeds.feedburner.com/~ff/Encosia?d=30RXbuXOgYA" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Encosia?i=RUO_mqr85Kw:jCVdIAACQjA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.encosia.com/~ff/Encosia?a=RUO_mqr85Kw:jCVdIAACQjA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Encosia?i=RUO_mqr85Kw:jCVdIAACQjA:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Encosia/~4/RUO_mqr85Kw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://encosia.com/learn-from-my-express-js-http-status-code-blunder/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://encosia.com/learn-from-my-express-js-http-status-code-blunder/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 1.396 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-04-29 16:35:39 -->

