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

<channel>
	<title>Aaron Lerch &#187; asp.net</title>
	<atom:link href="http://www.aaronlerch.com/blog/category/aspnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.aaronlerch.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 10 Mar 2010 12:45:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rock the iPhone with ASP.NET MVC</title>
		<link>http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/</link>
		<comments>http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/#comments</comments>
		<pubDate>Sun, 08 Jun 2008 23:30:06 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/</guid>
		<description><![CDATA[With much fanfare Apple announced the availability of the iPhone SDK. I downloaded it and someday plan to play around with it, though with the SDK already having gone through 4 or 5 beta releases (each a ~2GB download) I’ll probably wait a long time before cracking it open. However, for web applications the best [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iphone1.png" align="right" />With much fanfare Apple announced the availability of the <a href="http://developer.apple.com/iphone/">iPhone SDK</a>. I downloaded it and someday plan to play around with it, though with the SDK already having gone through 4 or 5 beta releases (each a ~2GB download) I’ll probably wait a long time before cracking it open. However, for web applications <em>the best way to integrate with an iPhone is still through the browser</em>.</p>
<p>Unfortunately Apple didn&#8217;t provide much help in the form of html or css to make your website &#8220;iPhone-y&#8221;. They <a href="http://developer.apple.com/webapps/">provide</a> documentation on elements like iPhone specific events (&#8220;onorientationchange&#8221;) and details about how Safari works on the iPhone in terms of zooming, etc., but nothing that offers guidance on how to make an application look like it belongs on the iPhone.</p>
<p>Enter <a href="http://joehewitt.com/">Joe Hewitt</a> and <a href="http://code.google.com/p/iui/">iUI</a>. iUI takes HTML that follows a simple set of conventions and does all the heavy lifting to enable you to easily build a version of your site that is tailored for the iPhone experience. I <a href="http://www.aaronlerch.com/blog/2007/10/27/writing-web-apps-for-the-iphone/">first started using iUI</a> before ASP.NET MVC was publicly introduced, and I specifically remember thinking how much iUI was built for &#8220;<a href="http://www.hanselman.com/blog/ASPNETMVCWebFormsUnplugged.aspx">webforms unplugged</a>&#8220;. Let&#8217;s take a quick look at an example of how iUI works, and how to use it with ASP.NET MVC.</p>
<p>If you’re the type that likes to get their hands dirty first, <a href="http://s3.amazonaws.com:80/aaronlerch.com/files/iUISample.v1.zip">download the code here</a>.</p>
<h1>CSS Zen Garden</h1>
<p>iUI is literally nothing more than some javascript, some css, and a bunch of image assets. It’s how things are supposed to work with HTML and it’s beautiful, like the <a href="http://www.csszengarden.com/">CSS Zen Garden</a>. It also has some simple conventions that I’ll summarize like so: “write HTML the way it was intended”. &lt;ul&gt; or &lt;ol&gt; for lists, and &lt;div&gt; or &lt;form&gt; for dialogs and pages. Easy enough, right? There’s not a ton to iUI but for this post I’ll start simple. Let’s create a list of products that we want to display like so:</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iui-product_list_screenshot.png" /></p>
<p>This is the HTML behind the list itself (not including the top toolbar, though the “title” attribute of the list controls the text shown in the center of the toolbar):</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">ul</span> <span class="attr">id</span><span class="kwrd">="products"</span> <span class="attr">title</span><span class="kwrd">="Products"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/1"</span><span class="kwrd">&gt;</span>Alice Mutton<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/2"</span><span class="kwrd">&gt;</span>Aniseed Syrup<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/3"</span><span class="kwrd">&gt;</span>Boston Crab Meat<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/4"</span><span class="kwrd">&gt;</span>Camembert Pierrot<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/5"</span><span class="kwrd">&gt;</span>Carnarvon Tigers<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/6"</span><span class="kwrd">&gt;</span>Chai<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/7"</span><span class="kwrd">&gt;</span>Chang<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/8"</span><span class="kwrd">&gt;</span>Chartreuse verte<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">ul</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<p>iUI does the heavy lifting to format the list in the iPhone style, and will dynamically load any linked content using an AJAX call and render it in-place, replacing the current list (“products”). iUI handles sliding in the new content from the right-hand side, just like a native iPhone application.</p>
<p>You could also reference another list defined within the same page, for example if you had a very short list of items and had each list item’s “linked content” also included in the page, like this:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">ul</span> <span class="attr">id</span><span class="kwrd">="products"</span> <span class="attr">title</span><span class="kwrd">="Products"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="#subproduct1"</span><span class="kwrd">&gt;</span>Product 1<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">ul</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">ul</span> <span class="attr">id</span><span class="kwrd">="subproduct1"</span> <span class="attr">title</span><span class="kwrd">="Related Products"</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;</span>Sub Item 1<span class="kwrd">&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;</span>Sub Item 2<span class="kwrd">&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">ul</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<h1>The Root Page</h1>
<p>iUI will dynamically render partial content into the current view, but it needs an initial root page describing the main layout. The easiest way to figure out what is needed is to look at one of the examples that iUI includes, but in a nutshell you’ll probably need at least two elements: the toolbar (the heading) and some content. To support the example above of a product list, our entire root page could look like this:</p>
<pre class="csharpcode"><span class="kwrd">&lt;!</span><span class="html">DOCTYPE</span> <span class="attr">html</span> <span class="attr">PUBLIC</span> <span class="kwrd">"-//W3C//DTD XHTML 1.0 Strict//EN"</span> <span class="kwrd">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span> <span class="attr">xmlns</span><span class="kwrd">="http://www.w3.org/1999/xhtml"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">meta</span> <span class="attr">http-equiv</span><span class="kwrd">="Content-Type"</span> <span class="attr">content</span><span class="kwrd">="text/html; charset=iso-8859-1"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>Northwind Explorer<span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">meta</span> <span class="attr">name</span><span class="kwrd">="viewport"</span> <span class="attr">content</span><span class="kwrd">="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">style</span> <span class="attr">type</span><span class="kwrd">="text/css"</span> <span class="attr">media</span><span class="kwrd">="screen"</span><span class="kwrd">&gt;</span>@import "../../Content/iui/iui.css";<span class="kwrd">&lt;/</span><span class="html">style</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="application/x-javascript"</span> <span class="attr">src</span><span class="kwrd">="../../Content/iui/iui.js"</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">class</span><span class="kwrd">="toolbar"</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">h1</span> <span class="attr">id</span><span class="kwrd">="pageTitle"</span><span class="kwrd">&gt;&lt;/</span><span class="html">h1</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">a</span> <span class="attr">id</span><span class="kwrd">="backButton"</span> <span class="attr">class</span><span class="kwrd">="button"</span> <span class="attr">href</span><span class="kwrd">="#"</span><span class="kwrd">&gt;&lt;/</span><span class="html">a</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">ul</span> <span class="attr">id</span><span class="kwrd">="products"</span> <span class="attr">title</span><span class="kwrd">="Products"</span> <span class="attr">selected</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/1"</span><span class="kwrd">&gt;</span>Alice Mutton<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/2"</span><span class="kwrd">&gt;</span>Aniseed Syrup<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/3"</span><span class="kwrd">&gt;</span>Boston Crab Meat<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/4"</span><span class="kwrd">&gt;</span>Camembert Pierrot<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/5"</span><span class="kwrd">&gt;</span>Carnarvon Tigers<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/6"</span><span class="kwrd">&gt;</span>Chai<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/7"</span><span class="kwrd">&gt;</span>Chang<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="/products/index/8"</span><span class="kwrd">&gt;</span>Chartreuse verte<span class="kwrd">&lt;/</span><span class="html">a</span><span class="kwrd">&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">ul</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<p>The site will initially show the list of products, and when the user clicks on a product, the &lt;ul id=”products” title=”Products” selected=”true”&gt;…&lt;/ul&gt; element will be wholesale replaced with the content loaded by an AJAX call to “/products/index/[number]”.</p>
<h1>Hooking up iUI to MVC</h1>
<p>First things first &#8211; <a href="http://code.google.com/p/iui/source/browse/trunk/iui">download</a> the latest iUI assets from the google code repository trunk. You&#8217;ll get the latest bug fixes and features, which I&#8217;ve found to be helpful. As a side note, you can view some samples directly from the repository itself &#8211; like the <a href="http://iui.googlecode.com/svn/trunk/samples/music.html">music example</a>. Put the downloaded files in the Content directory:</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iui-assets.png" /></p>
<p>Define your main page—the main entry point to the site. I chose /home/index in my example. This is where you’ll reference the iUI javascript and css assets, and define the initial structure of your page.</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iui-products_home.png" /></p>
<p>One big catch that I already mentioned with iUI is that it expects links (whether AJAX-loaded or in-page references) to return HTML fragments. It literally takes the results of an AJAX call to a given URL and sets the innerHTML of the content to replace.</p>
<p>This means that every other page in our application should return partial content. For example, when I click on “Products” this is the only content of the view page that lists the products:</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iui-product_list.png" /></p>
<p>As you can see, it’s simply building the list itself and rendering the partial HTML content as a response.</p>
<p>You can connect with an iPhone on your local network with a wifi connection, but it’s much easier to install and test with <a href="http://www.apple.com/safari/">Safari for Windows</a>. Both Safari for Windows and the iPhone’s mobile Safari use the <a href="http://webkit.org/">WebKit</a> engine so the rendering experience is about as close as you can get. Shrink the browser to approximately the size of the iPhone screen and you’d never know you didn’t spend the $400+ on an iPhone. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/iui-safari.png" /></p>
<p>You can <a href="http://s3.amazonaws.com:80/aaronlerch.com/files/iUISample.v1.zip">download the first version of my example project here</a>.</p>
<h1>Up Next</h1>
<p>In future posts I’ll explore some more of iUI’s features such as adding a product page to view details of a product in a friendly way (I’ve included this in the example project already), rendering partial lists (allowing the user to expand the list incrementally), detecting the user agent and loading iPhone views vs. “normal” views, and more. I’ll update the example project as we go!</p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/06/08/rock-the-iphone-with-aspnet-mvc/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Automatic formatting of inline ASP.NET tags</title>
		<link>http://www.aaronlerch.com/blog/2008/04/08/automatic-formatting-of-inline-aspnet-tags/</link>
		<comments>http://www.aaronlerch.com/blog/2008/04/08/automatic-formatting-of-inline-aspnet-tags/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 05:26:08 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/04/08/automatic-formatting-of-inline-aspnet-tags/</guid>
		<description><![CDATA[I don&#8217;t know whether it&#8217;s Resharper and/or Visual Studio 2008 that messes up the auto-formatting of inline ASP.NET tags, but it sucks. I usually start &#34;prettying&#34; it up, but usually give up halfway through, because every time I add anything else, the formatting is shot again. Is it just me? Is there a setting I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t know whether it&#8217;s <a href="http://www.jetbrains.com/resharper/">Resharper</a> and/or Visual Studio 2008 that messes up the auto-formatting of inline ASP.NET tags, but it sucks. I usually start &quot;prettying&quot; it up, but usually give up halfway through, because every time I add anything else, the formatting is shot again. Is it just me? Is there a setting I&#8217;m missing?</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/messed_up_formatting.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/04/08/automatic-formatting-of-inline-aspnet-tags/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testing TempData, and Mocking SessionState</title>
		<link>http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/</link>
		<comments>http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 00:07:10 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/</guid>
		<description><![CDATA[About a month and a half ago Ben Scheirman wrote about testing TempData in ASP.NET MVC. It&#8217;s good stuff, and aside from changes between Preview 1 and Preview 2, it still works fine. (See Scott Hanselman&#8217;s post for some Preview 2-friendly mock helpers using Rhino Mocks.)
While I can easily understand what Ben&#8217;s code is doing, [...]]]></description>
			<content:encoded><![CDATA[<p>About a month and a half ago <a href="http://flux88.com/">Ben Scheirman</a> wrote about <a href="http://flux88.com/testingtempdatainaspnetmvc.aspx">testing TempData in ASP.NET MVC</a>. It&#8217;s good stuff, and aside from changes between Preview 1 and Preview 2, it still works fine. (See <a href="http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx">Scott Hanselman&#8217;s post</a> for some Preview 2-friendly mock helpers using Rhino Mocks.)</p>
<p>While I can easily understand what Ben&#8217;s code is doing, what I couldn&#8217;t figure out is <em>why</em> it worked. If you reflect over TempDataDictionary (the type of the Controller.TempData property), you&#8217;ll see that the data type it persists to the session is an internal structure.</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/tempdata-reflector.png" /></p>
<p>Ben&#8217;s code, however, mocks out the Session to return the expected TempDataDictionary object. By all counts, that should fail, since the TempDataDictionary won&#8217;t be getting back the values it expects&#8211;it expects the internal map structure.</p>
<p>Well, it turns out I was glossing over one very important fact. TempDataDictionary was written to be smart enough that if the underlying session store either didn&#8217;t work, or didn&#8217;t provide the right data, TempData will continue to operate as normal&#8211;<em>for the current request only</em>. You can see below that if the session data was null or wasn&#8217;t the right type, it just creates a new internal map.</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/tempdata-reflector2.png" /><br />
<font size="1">(image cut off for space)</font></p>
<p>One of the benefits of TempData is the cross-request persistence via the session. You might not have known it, but when you call RedirectToAction in your controller action, for example, it&#8217;s actually resulting in a 300-level HTTP redirect, which means an entirely new HttpContext for the next request. It&#8217;s basically deferring to the browser to perform the redirect.</p>
<p>So, while Ben&#8217;s code will definitely work, here&#8217;s an extension method that can help with mocking out the session a little more &#8220;correctly&#8221;:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> NullifySessionState(<span class="kwrd">this</span> HttpSessionStateBase session)
{
    SetupResult.For(session[<span class="kwrd">null</span>]).IgnoreArguments().Return(<span class="kwrd">null</span>);
    session[<span class="kwrd">null</span>] = <span class="kwrd">null</span>;
    LastCall.IgnoreArguments();
}</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/03/12/testing-tempdata-and-mocking-sessionstate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Displaying [foo] on every page of an ASP.NET MVC application</title>
		<link>http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/#comments</comments>
		<pubDate>Sat, 26 Jan 2008 15:15:16 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/</guid>
		<description><![CDATA[ Frequently in web applications there&#8217;s a requirement like this: &#8220;Every page should display [foo].&#8221; Where &#8220;foo&#8221; can be literally anything: a list of favorites, sponsors, news, or whatever &#8211; it&#8217;s data. In what I&#8217;ll call &#8220;normal, by a long shot&#8221; ASP.NET cases, universally displayed data will probably be encapsulated in a user control and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://aaronlerch.com.s3.amazonaws.com/images/aspnetmvcfooscreen.png" align="right" /> Frequently in web applications there&#8217;s a requirement like this: &#8220;Every page should display [foo].&#8221; Where &#8220;foo&#8221; can be literally anything: a list of favorites, sponsors, news, or whatever &#8211; <em>it&#8217;s data</em>. In what I&#8217;ll call &#8220;normal, by a long shot&#8221; ASP.NET cases, universally displayed data will probably be encapsulated in a user control and put on a master page. The master page includes the user control on all pages, and the user control loads the data and renders it, and it was all declared Good.</p>
<p>The MVC world (<a href="http://www.hanselman.com/blog/ASPNETMVCWebFormsUnplugged.aspx">ASP.NET &#8220;unplugged&#8221;</a>) turns everything on it&#8217;s head. Maintaining a clean separation of concerns means the controller is responsible for ensuring the appropriate data is made available to the appropriate view. The view does not load data on it&#8217;s own, nor does it know or care where the data came from. And the view was declared Dumb.</p>
<p>Views aren&#8217;t really dumb, of course, they have to render data, and the MVC framework does give them some tools to help. For example, the ViewMasterPage base class exposes helpers for constructing links, accessing the view data, etc.</p>
<p><img src="http://aaronlerch.com.s3.amazonaws.com/images/viewmasterpage.png" /></p>
<p>So what do you do in the ASP.NET MVC world when you&#8217;ve got a &#8220;user control&#8221; embedded in your master page that needs specific data? Let&#8217;s say that hypothetically speaking you&#8217;re working on a <a href="http://code.google.com/p/codecampserver/">CodeCampServer</a> project, and you need to, oh I don&#8217;t know, display a list of code camp Sponsors (ahem, &#8220;Contributors&#8221;) on every single page?</p>
<p>The way I see it, you&#8217;ve got three options:</p>
<p><strong>1. &#8220;Global&#8221; data for global display</strong></p>
<p>Data can be loaded at a low level for each and every request. Something like:</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> Application_BeginRequest(<span class="kwrd">object</span> sender, EventArgs e)
{
    <span class="kwrd">this</span>.Context.Items[<span class="str">"FooData"</span>] = <span class="kwrd">new</span> FooData();
}</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<p>The pro is that FooData will be available to every view (though not through the standard ViewData). Unfortunately if this data is expensive to compute (or even if it isn&#8217;t) it&#8217;ll be loaded for <em>every request</em>, no matter what. Oh, and no one in their right mind would actually do it this way. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  There&#8217;s that, too.</p>
<p><strong>2. Controller.OnPreAction</strong></p>
<p>The main Controller class exposes a virtual OnPreAction method which offers a hook just before an action is invoked. For global data, all controllers in your application could derive from a common base controller class which loads the necessary data.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> OnPreAction(<span class="kwrd">string</span> actionName, System.Reflection.MethodInfo methodInfo)
{
    ViewData[<span class="str">"FooData"</span>] = <span class="kwrd">new</span> FooData();
    <span class="kwrd">return</span> <span class="kwrd">base</span>.OnPreAction(actionName, methodInfo);
}</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; }</style>
<p>Views will be able to access the data via the ViewData property, as normal. With single inheritance in C#, a required base class just for common data can potentially cause problems.</p>
<p><strong>3. Call &#8220;RenderAction&#8221; from the view</strong></p>
<p><a href="http://www.marklio.com/marklio/PermaLink,guid,90f5b539-3f7f-4309-a70a-fe98fdbc7347.aspx">RenderAction</a> is an extension method that allows a view to reference a Controller and Action and have the results be rendered in-place within the view.</p>
<p><img src="http://aaronlerch.com.s3.amazonaws.com/images/aspnetmvcrenderaction.png" /></p>
<p>The &#8220;Tags&#8221; controller and &#8220;Cloud&#8221; action would render a view that generated an HTML fragment that would fit within the current view. This approach has advantages of only loading data when absolutely necessary and changing your view doesn&#8217;t necessarily require changing the application code to match.</p>
<p>There could be questions about separation of concerns: a view is determining what data to include regardless of what it&#8217;s controller gave it. But the same is true for the other solutions as well &#8211; this is just more dynamic.</p>
<p>Another advantage to this approach is that if <a href="http://www.aaronlerch.com/blog/2008/01/01/unifying-web-sites-and-web-services-with-the-aspnet-mvc-framework/">you set it up right</a>, with no extra work your &#8220;viewlets&#8221; (the views that render fragments) can return JSON serialized data for an AJAX call, for example.</p>
<p>I&#8217;m pro-RenderAction, but in discussions I&#8217;ve had with people it hasn&#8217;t been as big a hit with them. What are your thoughts? Am I missing some pros or cons? Are there more options that I didn&#8217;t include? Is it really just an app-by-app decision, or is there an emerging convention that should be followed?</p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Unifying Web &quot;Sites&quot; and Web Services with the ASP.NET MVC Framework</title>
		<link>http://www.aaronlerch.com/blog/2008/01/01/unifying-web-sites-and-web-services-with-the-aspnet-mvc-framework/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/01/unifying-web-sites-and-web-services-with-the-aspnet-mvc-framework/#comments</comments>
		<pubDate>Wed, 02 Jan 2008 03:10:53 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web services]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/01/unifying-web-sites-and-web-services-with-the-aspnet-mvc-framework/</guid>
		<description><![CDATA[(For those who&#8217;d rather just download the code, the link is at the end.)
Lately I&#8217;ve been delving into the ASP.NET MVC framework, the timing of which has been interesting as I am about to finish reading RESTful Web Services by Leonard Richardson and Sam Ruby. It&#8217;s an excellent book that I&#8217;d highly recommend to anybody [...]]]></description>
			<content:encoded><![CDATA[<p>(For those who&#8217;d rather just download the code, the link is at the end.)</p>
<p>Lately I&#8217;ve been delving into the <a href="http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx">ASP.NET MVC framework</a>, the timing of which has been interesting as I am about to finish reading <a href="http://www.amazon.com/RESTful-Web-Services-Leonard-Richardson/dp/0596529260">RESTful Web Services</a> by Leonard Richardson and Sam Ruby. It&#8217;s an excellent book that I&#8217;d highly recommend to anybody designing and creating services for the web, or just interested in it.</p>
<p>This quote from the book description on Amazon.com succinctly describes what&#8217;s been floating around in my head for a while:</p>
<blockquote><p><em>You&#8217;ve built web sites that can be used by humans. But can you also build web sites that are usable by machines?</em> That&#8217;s where the future lies, and that&#8217;s what RESTful Web Services shows you how to do.       <br />[Emphasis mine]</p>
</blockquote>
<p>Why do we have to build web &quot;sites&quot; for humans and <em>different</em> web services for machines? I can create an ASP.NET site, a SOAP-based ASMX web service, or a SOAP or <a href="http://www.aaronlerch.com/blog/2007/08/21/creating-restful-web-services-with-wcf-35/">REST (with .NET 3.5)</a> WCF service and while they can share business logic, there&#8217;s still a lot of &quot;endpoint code&quot; (for lack of a better term) that has to be implemented, and if I want a human friendly front end + a web API, I have to build a site that essentially wraps <em>another</em> service, since the site itself really is a service.</p>
<p>With the ASP.NET MVC Framework, though, I see the opportunity to unify services and &quot;sites&quot; (human-readable services). Imagine visiting http://www.example.com/books/ and being able to receive back HTML, POX, or JSON, depending on what you asked for&#8211;with no additional code required outside of following a convention or two. Web browsers ask for HTML, returning a human consumable page that gets rendered. AJAX or custom clients can request JSON or XML, whatever they know how to interpret best.</p>
<p>The separation of concerns and extensibility that the ASP.NET MVC framework exposes lets us accomplish this with surprisingly little code. At least for read-only services (which is as far as I took it for now.) If you&#8217;re not familiar with how the ASP.NET MVC framework works, check out <a href="http://weblogs.asp.net/leftslipper/archive/2007/12/10/asp-net-mvc-design-philosophy.aspx">Eilon&#8217;s excellent ASP.NET MVC design philosophy post</a> (he also includes many good reference links).</p>
<h3>Approach</h3>
<p>Outside of the ASP.NET MVC framework itself, from an HTTP perspective I simply want to alter my response format depending on what the incoming request asked for. I decided to keep it simple and only support the &quot;<a href="http://www.rfc-editor.org/rfc/rfc2854.txt">text/html</a>&quot;, &quot;<a href="http://www.rfc-editor.org/rfc/rfc3023.txt">application/xml</a>&quot;, and &quot;<a href="http://www.ietf.org/rfc/rfc4627.txt">application/json</a>&quot; media types.</p>
<p>I started off trying to use the &quot;<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">Accept</a>&quot; HTTP header as an indicator for what response format the client preferred. After all, that&#8217;s what the Accept header is for: &quot;The Accept request-header field can be used to specify certain media types which are acceptable for the response.&quot; But I quickly ran into a snafu when I found that Firefox prefers XML over HTML.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="167" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image.png" width="311" border="0" /> </p>
<p>That means that every request Firefox makes would result in the uber-friendly XML view.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="179" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_3.png" width="438" border="0" /> </p>
<p>And because of that snafu, I read up some more on the Accept header &#8211; namely what they had to say about it in an appendix of <u>RESTful Web Services</u>:</p>
<blockquote><p>Hiding this information inside the HTTP headers is a good idea for web browsers, but it shouldn&#8217;t be the only solution for web service clients. I recommend exposing different representations using different URIs. &#8230; If you want to support Accept on top of this, that&#8217;s great (Rails does this too).</p>
</blockquote>
<p>There was also some pragmatic advice in the chapter on Representations.</p>
<blockquote><p>It&#8217;s RESTful to keep this information [file format types] in the HTTP headers, and it&#8217;s RESTful to put it in the URI. I recommend keeping as much of this information as possible in the URI, and as little as possible in request metadata. I think URIs are more useful than metadata. URIs get passed around from person to person, and from program to program. The request metadata almost always gets lost in translation.</p>
</blockquote>
<p>I tend to agree with that. To make it easy and somewhat intuitive, I chose to base the response format on the existence of a querystring parameter named &quot;format&quot;. It can specify &quot;xml&quot; or &quot;json&quot;, for example http://www.example.com/books/?format=json. But really, you can use any method you want to allow format specification.</p>
<h3>Implementation</h3>
<p>Formatting the response is the responsibility of the View in the MVC architecture. Since processing requests for HTML content didn&#8217;t need to change from the default ASP.NET MVC behavior, all I need to do is override the default WebFormViewFactory functionality and return my own &quot;SerializedView&quot; if the URI indicated xml or json formatting. SerializedView is an abstract base class that encapsulates common functionality and allows sub-classes to perform the serialization, or handle custom error reporting.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="300" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/aspnetmvc_service_classdiagram.png" width="380" border="0" /> </p>
<p>When a Controller passes control to a View, it calls the &quot;RenderView&quot; method on the Controller base class, passing in the view name and some optional data &#8211; including something called &quot;ViewData&quot; &#8211; an object that represents the content the view should render.</p>
<p><strong>Here&#8217;s the best part:</strong> creating an ASP.NET MVC site+service using my approach means passing a serializable object as ViewData. <em>It&#8217;s as simple as that</em>, nothing else needs to change (ok, you need one additional line of code in your Application_Start handler &#8211; more on that later). In your ASPX view, you can access the object via ViewData and use all the HTML helpers, UserControls, etc. that you want to build out your HTML, javascript, and who-knows-what.</p>
<p>Unfortunately, the current CTP of the ASP.NET MVC framework does not expose a way to &quot;inject&quot; a different IViewFactory (my subclassed version) into the default Controller created by the ControllerBuilder class. So, that means implementing the IControllerFactory interface and duplicating (ouch!) the code that ControllerBuilder executes, with one somewhat nasty addition.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="200" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_5.png" width="680" border="0" /> </p>
<p>Yuck! The ViewFactory property is specific to the Controller class, not the IController interface, hence the specific processing &#8212; and that also means my approach won&#8217;t work for other IController implementations. Not without some extra work, anyway.</p>
<p>This is where the only change you need to make comes in. My IControllerFact<br />
ory implementation needs to be registered as the default controller factory, which is done in the Application_Start handler &#8211; the same place your routes are configured.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="100" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_6.png" width="910" border="0" /></p>
<h3>Serializable Types</h3>
<p>For various reasons, you should use the WCF [DataContract] and [DataMember] attributes to tag your objects as serializable. For one, you gain all the serialization benefits these attributes offer, plus you can use the same contract types across multiple endpoints if you need to. And for another, serializing to JSON via the <a title="DataContractJsonSerializer Class" href="http://msdn2.microsoft.com/bb908432.aspx">System.Runtime.Serialization.Json.DataContractJsonSerializer</a> requires the DataContract attribute. If you use the older [Serializable] attribute, you get some interesting results.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="265" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/aspnetmvc_service_serializedjson.png" width="390" border="0" /> </p>
<p>The deprecated <a title="JavaScriptSerializer Class" href="http://msdn2.microsoft.com/bb337495.aspx">System.Web.Script.Serialization.JavaScriptSerializer</a> works correctly for objects tagged with [Serializable] but it&#8217;s, well, deprecated.</p>
<h3>Example</h3>
<p>Using the default ASP.NET MVC Application templates, I registered the default ControllerFactory in my Application_Start handler, defined a Books controller with a default action, and a &quot;List&quot; view that prints out some Author and Title information. I also created the following definition of a book.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="265" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_8.png" width="365" border="0" /> </p>
<p>My controller implementation is no different than it normally would be. I get a list of books and render the &quot;List&quot; view, explicitly specifying the book list as the ViewData. You might notice that I pass the ControllerContext into the GetBooks method. I am experimenting with returning URIs to related resources as part of the data. I&#8217;m still playing around, but for now you get my latest attempt. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_9.png" width="510" border="0" /> </p>
<p>Requesting the appropriate URI in Firefox yields the expected result from my List view:</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="355" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_10.png" width="385" border="0" /></p>
<p>And altering the URI returns the appropriate response types, xml or json.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="355" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/aspnetmvc_service_xmlformat.png" width="385" border="0" /></p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="80" alt="image" src="http://www.aaronlerch.com/files/blog/WebServiceswithASP.NETMVC_31B2/image_12.png" width="620" border="0" /> </p>
<h3>Summary</h3>
<p>This ended up being a longer post than I intended, but I hope it was worth it. I&#8217;ve put the full source for the &quot;MvcServiceLibrary&quot; and an example up on my <a href="http://www.aaronlerch.com/blog/tools/">Tools page</a> &#8211; but <a href="http://www.aaronlerch.com/files/blog/MvcServiceLibrary.zip">here&#8217;s the direct download link</a>. I&#8217;ll also be checking if this is worth putting into the <a href="http://mvccontrib.org/">MvcContrib</a> open source project.</p>
<p>I think that the ASP.NET MVC framework is a huge step forward in creating RESTful web sites, and hopefully now also RESTful web services! Let me know what you think, I love getting feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/01/unifying-web-sites-and-web-services-with-the-aspnet-mvc-framework/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Writing web apps for the iPhone</title>
		<link>http://www.aaronlerch.com/blog/2007/10/27/writing-web-apps-for-the-iphone/</link>
		<comments>http://www.aaronlerch.com/blog/2007/10/27/writing-web-apps-for-the-iphone/#comments</comments>
		<pubDate>Sat, 27 Oct 2007 04:01:21 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/10/27/writing-web-apps-for-the-iphone/</guid>
		<description><![CDATA[I&#8217;ve been working on a web app for the iPhone the last few days. It&#8217;s been a little while since I&#8217;ve done ASP.NET (I miss it!) so it&#8217;s fun to jump back in. I came across iUI &#8211; a very well done, lightweight and visually beautiful &#8220;mini-framework&#8221; for creating web sites that behave just like [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a web app for the iPhone the last few days. It&#8217;s been a little while since I&#8217;ve done ASP.NET (I miss it!) so it&#8217;s fun to jump back in. I came across <a href="http://code.google.com/p/iui/">iUI</a> &#8211; a very well done, lightweight and visually beautiful &#8220;mini-framework&#8221; for creating web sites that behave just like native iPhone applications. Digg.com used an early version of iUI to create their <a href="http://digg.com/iphone">iPhone interface</a>.</p>
<p>Unfortunately, to use the HTML structure and navigation paradigm that iUI supports out of the box, I feel more like I&#8217;m coding in classic ASP, not ASP.NET. iUI (as it currently stands) is all about replacing the current page fragment with one returned from the server via an Ajax call. Sort of like a bunch of UpdatePanel&#8217;s that keep replacing each other&#8211;except that the last instance isn&#8217;t removed, just hidden. So if you navigate to a &#8220;sub page&#8221; (or sub menu) and perform an action that causes a state change such that an already-loaded higher level menu should be updated, it won&#8217;t be. It&#8217;s cached.</p>
<p>Alas, these are the issues I&#8217;m working around. I&#8217;m working on some possible tweaks to iUI to help support some of this functionality. I&#8217;ll probably post something when my app is done with a quick tutorial on how to use the toolkit from ASP.NET&#8211;assuming I figure it out. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Has anybody out there used iUI and have advice for me? I&#8217;m interested! I&#8217;ll pay big bucks&#8230; I&#8217;ll take you out for a fancy fast-food meal. How can you pass that up??</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8623fa52-93ba-4381-9cf9-d95f3150ba7d" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/iPhone" rel="tag">iPhone</a>, <a href="http://technorati.com/tags/iUI" rel="tag">iUI</a>, <a href="http://technorati.com/tags/ASP.NET" rel="tag">ASP.NET</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/10/27/writing-web-apps-for-the-iphone/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating Comet applications with ASP.NET</title>
		<link>http://www.aaronlerch.com/blog/2007/07/08/creating-comet-applications-with-aspnet/</link>
		<comments>http://www.aaronlerch.com/blog/2007/07/08/creating-comet-applications-with-aspnet/#comments</comments>
		<pubDate>Sun, 08 Jul 2007 02:47:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/07/08/creating-comet-applications-with-aspnet/</guid>
		<description><![CDATA[Sometimes it&#8217;s useful to hijack a particular technology to do something it was never intended to do.  Comet does exactly that, and it&#8217;s not for the faint of heart.  In a nutshell, &#8220;Comet-style&#8221; applications use features of the HTTP request-response communication model to morph it into a streaming context whereby the server can [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it&#8217;s useful to hijack a particular technology to do something it was never intended to do.  <a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet</a> does exactly that, and it&#8217;s not for the faint of heart.  In a nutshell, &#8220;Comet-style&#8221; applications use features of the HTTP request-response communication model to morph it into a streaming context whereby the server can essentially push data to the client (instead of the client request data from the server). <a href="http://en.wikipedia.org/wiki/Comet_(programming)">Wikipedia</a> puts it well:</p>
<blockquote><p>Comet is a programming technique that enables web servers to send data to the client without having any need for the client to request it. It allows creation of event-driven web applications which are hosted in the browser.</p></blockquote>
<p>When faced with the need for a real-time web application, there will always be trade-offs between performance and scalability.  One possibility is to implement a pull architecture that periodically polls the sever. The benefits include higher scalability per server with the trade-off of increased latency and lower performance (in terms of information availability).  On the other side of the coin is a persistent connection which allows the server to push streaming data to the client. Benefits include great performance (low latency), but low scalability since every client connection is held open for long periods of time which today&#8217;s web servers are not optimized for.  <a href="http://www.lightstreamer.com/">Lightstreamer.com</a> has <a href="http://www.lightstreamer.com/Lightstreamer_Paradigm.pdf">a good white paper</a> describing the pros and cons of the various approaches (including some hybrid methods), and, of course, why theirs is the best and you should buy it.  Truth be told, I think they have a very compelling product offering. (I haven&#8217;t tried it, though, just read about it.)</p>
<p>So how can a Comet ASP.NET application scale?  Very poorly.  Since each client connection holds open a dedicated thread from the ASP.NET thread pool, there are really only two ways to scale:</p>
<ol>
<li>Increase the number of threads in the thread pool to the maximum. This is done in the <a href="http://msdn2.microsoft.com/en-us/library/7w2sway1.aspx">&lt;processModel&gt;</a> element located under &lt;system.web&gt;. Set the maxWorkerThreads attribute to the max of 100.  This is a per-CPU value, so assuming you ran this on a quad-processor server, your application has the <em>potential</em> to scale to 400 concurrent users per server.  Assuming you grab a <a href="http://configure.us.dell.com/dellstore/config.aspx?c=us&amp;cs=555&amp;l=en&amp;oc=pe6850pad&amp;s=biz">barebones Dell PowerEdge 4-proc server</a> for $10,000 USD, you&#8217;ll be paying $25 per concurrent user. Fantastic numbers! Not.</li>
<li>Add more servers &#8211; in real-time applications it&#8217;s typically not feasible for each client connection to end up on different servers. Once the initial connection has been made, the client is &#8220;pinned&#8221;.  In cases like these, additional servers can be added but they have to live behind some &#8220;sticky load balancing&#8221; routers.</li>
</ol>
<p>The other option is to write a custom web server that is optimized for concurrent connections.  I wonder if WCF could handle the challenge, and while it seems like it could do better than IIS+ASP.NET, it appears you wouldn&#8217;t necessarily get a huge bang for your buck. Some real-world testing would be much more definitive however. Here&#8217;s a few links talking about streaming data back over an HTTP connection with WCF:</p>
<ul>
<li><a href="http://blogs.msdn.com/drnick/archive/2006/10/20/keeping-connections-open-in-iis.aspx">Nicholas Allen &#8211; Keeping Connections open in IIS</a></li>
<li><a href="http://blogs.thinktecture.com/buddhike/archive/2007/05/23/414851.aspx">Buddhike &#8211; WCF &#8211; POX Streaming</a></li>
</ul>
<p>Just for fun I&#8217;ve created a very brief ASP.NET sample application that demonstrates a basic Comet implementation.  It streams the current server time back to the web browser, which just displays the value.  Most of the work is in javascript on the client page. The key ASP.NET components are simply the disabling of output buffering, and flushing the response stream as appropriate.  I didn&#8217;t use any &#8220;fancied up&#8221; javascript libraries so as not to exclude anybody who isn&#8217;t familiar with any particular library.</p>
<p>And now, after having bashed my own approach, here it is.  Create a new Web Site in Visual Studio 2005.  Add a page called simply &#8220;Service.aspx&#8221; and put this code in the code-behind:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> Delimiter = <span class="str">"|"</span>;

<span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
{
    Response.Buffer = <span class="kwrd">false</span>;

    <span class="kwrd">while</span> (<span class="kwrd">true</span>)
    {
        Response.Write(Delimiter
            + DateTime.Now.ToString(<span class="str">"HH:mm:ss.FFF"</span>));
        Response.Flush();
<span class="rem">
        // Suspend the thread for 1/2 a second
</span>        System.Threading.Thread.Sleep(500);
    }<span class="rem">

    // Yes I know we'll never get here,
 </span>   <span class="rem">// it's just hard not to include it!
</span>    Response.End();
}</pre>
<p>Add a new HTML page to the project (I called mine &#8220;ajax.html&#8221;) and overwrite the contents with this: (Explanation to follow.)<br />
(NOTE: The formatting got screwed up during a blog import to Wordpress &#8211; download the zip file linked below for &#8220;readable&#8221; code. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">html</span> <span class="attr">xmlns</span><span class="kwrd">="http://www.w3.org/1999/xhtml"</span> <span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>Comet AJAX Sample<span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>    <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="javascript"</span><span class="kwrd">&gt;</span>      <span class="kwrd">function</span> getData()      {          loadXMLDoc(<span class="str">"Service.aspx"</span>);      }<span class="kwrd">var</span> req = <span class="kwrd">false</span>;

<span class="kwrd">function</span> createRequest()      {        <span class="rem">// branch for native XMLHttpRequest object</span>        <span class="kwrd">if</span>(window.XMLHttpRequest &amp;&amp; !(window.ActiveXObject))        {          <span class="kwrd">try</span> {            req = <span class="kwrd">new</span> XMLHttpRequest();          } <span class="kwrd">catch</span>(e) {            req = <span class="kwrd">false</span>;          }        <span class="rem">// branch for IE/Windows ActiveX version</span>        } <span class="kwrd">else</span> <span class="kwrd">if</span>(window.ActiveXObject) {          <span class="kwrd">try</span> {            req = <span class="kwrd">new</span> ActiveXObject(<span class="str">"Msxml2.XMLHTTP"</span>);          } <span class="kwrd">catch</span>(e) {            <span class="kwrd">try</span> {                req = <span class="kwrd">new</span> ActiveXObject(<span class="str">"Microsoft.XMLHTTP"</span>);            } <span class="kwrd">catch</span>(e) {                req = <span class="kwrd">false</span>;            }          }        }      }

<span class="kwrd">function</span> loadXMLDoc(url) {          <span class="kwrd">try</span>          {              <span class="kwrd">if</span> (req) {                  req.abort();                  req = <span class="kwrd">false</span>;              }

createRequest();

<span class="kwrd">if</span> (req) {                 req.onreadystatechange = processReqChange;                 req.open(<span class="str">"GET"</span>, url, <span class="kwrd">true</span>);                 req.send(<span class="str">""</span>);              }              <span class="kwrd">else</span> {                  alert(<span class="str">'unable to create request'</span>);              }          }          <span class="kwrd">catch</span> (e) {              alert(e.message);          }      }

<span class="kwrd">function</span> processReqChange() {          <span class="kwrd">if</span> (req.readyState == 3) {              <span class="kwrd">try</span>              {                  ProcessInput(req.responseText);

<span class="rem">// At some (artibrary) length </span>                  <span class="rem">// recycle the connection</span>                  <span class="kwrd">if</span> (req.responseText.length &gt; 3000) {                      lastDelimiterPosition = -1;                      getData();                  }              }              <span class="kwrd">catch</span> (e) {                  alert(e.message);              }          }      }

<span class="kwrd">var</span> lastDelimiterPosition = -1;

<span class="kwrd">function</span> ProcessInput(input)      {          <span class="rem">// Make a copy of the input</span>          <span class="kwrd">var</span> text = input;          <span class="rem">// Search for the last instance of the delimiter</span>          <span class="kwrd">var</span> nextDelimiter =                 text.indexOf(<span class="str">'|'</span>, lastDelimiterPosition+1);          <span class="kwrd">if</span> (nextDelimiter != -1) {              <span class="rem">// Pull out the latest message</span>              <span class="kwrd">var</span> timeStamp = text.substring(nextDelimiter+1);              <span class="kwrd">if</span> (timeStamp.length &gt; 0) {                  lastDelimiterPosition = nextDelimiter;                  ProcessTime(timeStamp);              }          }      }

<span class="kwrd">function</span> ProcessTime(time)      {          <span class="kwrd">var</span> <span class="kwrd">out</span> = document.getElementById(<span class="str">'outputZone'</span>);          <span class="kwrd">out</span>.innerHTML = time;      }    <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;</span><span class="html">body</span> <span class="attr">onload</span><span class="kwrd">="getData()"</span><span class="kwrd">&gt;</span>    <span class="kwrd">&lt;</span><span class="html">b</span><span class="kwrd">&gt;</span>Server Time:<span class="kwrd">&lt;/</span><span class="html">b</span><span class="kwrd">&gt;</span><span class="attr"> </span><span class="attr"> </span><span class="kwrd">&lt;</span><span class="html">span</span> <span class="attr">id</span><span class="kwrd">="outputZone"</span><span class="kwrd">&gt;&lt;/</span><span class="html">span</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span><span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span></pre>
<p>It works by making a connection to the server and processing the response as it streams back.  &#8220;getData()&#8221; will initiate an AJAX request for the service page, which will continue to stream data back.  When new data is available, the client parses out the new data beginning from the last location in the response that was processed.  If the response text gets too large, the connection is severed and a new one made (semi-polling &#8212; one of the hybrid approaches) as processing an ever increasing response body can ultimately slow down the web browser unnecessarily.</p>
<p>There is a lot more to a successful Comet implementation, obviously, and I encourage you to read the information available at Wikipedia including the reference links.</p>
<p>Download the 3 files (ajax.html, Service.aspx, Service.cs) here:  <a href="http://www.aaronlerch.com/files/blog/ASP_NET_Comet_Example.zip">ASP.NET Comet Example.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/07/08/creating-comet-applications-with-aspnet/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>ASP.NET 2.0 Page Lifecycle</title>
		<link>http://www.aaronlerch.com/blog/2006/07/15/aspnet-20-page-lifecycle/</link>
		<comments>http://www.aaronlerch.com/blog/2006/07/15/aspnet-20-page-lifecycle/#comments</comments>
		<pubDate>Sat, 15 Jul 2006 00:27:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/07/15/aspnet-20-page-lifecycle/</guid>
		<description><![CDATA[I think just about every single ASP.NET candidate I’ve interviewed knows practically nothing about the page lifecycle, except for “Page_Load” of course—and they always say that: “Page Load”. They never say “Load” which is the actual event name. (That’s being a little picky though.)
Here’s something every web developer should be familiar with—not necessarily memorized (otherwise [...]]]></description>
			<content:encoded><![CDATA[<p>I think just about every single ASP.NET candidate I’ve interviewed knows practically nothing about the page lifecycle, except for “Page_Load” of course—and they always say that: “Page Load”. They never say “Load” which is the actual event name. (That’s being a little picky though.)</p>
<p><a href="http://spietrek.blogspot.com/2006/07/aspnet-20-page-life-cycle.html">Here’s something every web developer should be familiar with</a>—not necessarily memorized (otherwise why would we enjoy diagrams like this?)—but at least <em>familiar</em>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/07/15/aspnet-20-page-lifecycle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debugging ASP.NET</title>
		<link>http://www.aaronlerch.com/blog/2005/12/20/debugging-aspnet/</link>
		<comments>http://www.aaronlerch.com/blog/2005/12/20/debugging-aspnet/#comments</comments>
		<pubDate>Tue, 20 Dec 2005 12:30:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2005/12/20/debugging-aspnet/</guid>
		<description><![CDATA[Jim Cheshire has posted a helpful resource (with links to helpful resources) for debugging ASP.NET applications.  Not VS.NET debugging, but really debugging.
(link to his blog)
]]></description>
			<content:encoded><![CDATA[<p>Jim Cheshire has posted a helpful resource (with links to helpful resources) for debugging ASP.NET applications.  Not VS.NET debugging, but <em>really</em> debugging.</p>
<p><a href="http://blogs.msdn.com/jamesche/archive/2005/12/20/505941.aspx">(link to his blog)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2005/12/20/debugging-aspnet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS 2005 and Web Projects</title>
		<link>http://www.aaronlerch.com/blog/2005/11/22/vs-2005-and-web-projects/</link>
		<comments>http://www.aaronlerch.com/blog/2005/11/22/vs-2005-and-web-projects/#comments</comments>
		<pubDate>Tue, 22 Nov 2005 18:44:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2005/11/22/vs-2005-and-web-projects/</guid>
		<description><![CDATA[Here is an indispensable tool for building and deploying Web Projects in Visual Studio 2005.
(on msdn.microsoft.com)
Also, I have run into this sticky situation: I have several projects in my solution (a few class library projects, the website project, and the web deployment project), where one or more class libraries make use of web services. The [...]]]></description>
			<content:encoded><![CDATA[<p>Here is an indispensable tool for building and deploying Web Projects in Visual Studio 2005.<br />
<a href="http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx">(on msdn.microsoft.com)</a></p>
<p>Also, I have run into this sticky situation: I have several projects in my solution (a few class library projects, the website project, and the web deployment project), where one or more class libraries make use of web services. The web service endpoint binding is set to &#8220;dynamic&#8221; which means the URL is placed in an app.config file. That&#8217;s great, but when those class libraries are used in the website, the configuration information is read from the web.config file, not the individual app.config files.</p>
<p>Unless I am missing something on how to automatically link the app.config files to the web.config file, I have to manually import the required settings. I originally thought that the web deployment project options would save me here, because there is an option to &#8220;Enable web.config file section replacement&#8221; where you pull the section from another .config file, however it seems to be failing on anything except for the <span style="font-family: courier new">&lt;appsettings/&gt;</span> section (in the app.config file the dynamic web service binding is saved in the <span style="font-family: courier new">&lt;applicationsettings/&gt;</span> section).</p>
<p>It works if I manually update the file, but I&#8217;m disappointed that the deployment project won&#8217;t handle it. Yeah yeah, I know it&#8217;s only Beta Preview, but still!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2005/11/22/vs-2005-and-web-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
