<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    <channel>
        <title>Lee Richardson - Blogs at Near Infinity</title>


        <link>http://www.nearinfinity.com/blogs/</link>
        <description>Employee Blogs</description>
        <language>en</language>
        <copyright>Copyright 2012</copyright>
        <lastBuildDate>Tue, 29 Nov 2011 10:36:04 -0500</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>How To Get The Most From Twitter: Scoping Rules</title>
            <description><![CDATA[ <p>Ever noticed a tweet disappear? As in someone else can't see something you posted?  There's a common mistake even twitter pros make that causes this to occur.</p>
<p>Are you sure you're seeing <i>all</i> of the replies to your tweets -- even from people you don't follow?  Do you ever find yourself missing important posts -- like those from your real life friends?  Do you know which will reach a wider audience: new style retweets vs old style retweets?</p>
<p>This article will answer these and other twitter related questions. It will help beginner to intermediate twitter users get the most out of the service.</p>

<p><b>#1 Standard #Tweets</b></p>
<p><a href="http://4.bp.blogspot.com/-e8CL3yKse4c/TtRbWzwGNlI/AAAAAAAAByI/lB9vEdwttes/s1600/1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 349px; height: 343px;" src="http://4.bp.blogspot.com/-e8CL3yKse4c/TtRbWzwGNlI/AAAAAAAAByI/lB9vEdwttes/s400/1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5680265477428229714" /></a></p>
<p>These appear simple.  These show up in the timeline of your followers (@admirer and @vet in the example above).  And they don't show up in the timeline of anyone who doesn't follow you (@effusive).  If this was all there was to twitter it would be a complete waste of time.</p>
<p>The subtlety with this type of tweet is that your content may show up to someone that doesn't follow you but that is following a hashtag or a topic you mention.  In the example above @hiro thows a hashtag onto the word aardvarks to indicate that it's special somehow.  His tweet is then picked up by @spca who runs a constant search in a twitter client for the word "#aardvark".</p>
<p>The first time I realized how powerful this could be I had was at a conference.  I was extremely bored by a terrible keynote.  With nothing else to do I discovered the conference hashtag on twitter and started watching it.  Suddenly I realized I wasn't alone.  I was in a huge room full of people making fun of the presenter!  It was like telepathy, or group consciousness or something.  I've never felt alone or bored at a conference since.</p>
<p>Interesting statistic: As of June 2010, about 65 million tweets were posted each day, equaling about 750 tweets sent each second. (<a href="http://en.wikipedia.org/wiki/Twitter">reference</a>)</p>
<p><b>#2 Replies</b></p>
<p><a href="http://3.bp.blogspot.com/-yg6C6yTNlfo/TtRbXFuUjsI/AAAAAAAAByU/Si6sfvHr-9c/s1600/2.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://3.bp.blogspot.com/-yg6C6yTNlfo/TtRbXFuUjsI/AAAAAAAAByU/Si6sfvHr-9c/s400/2.png" border="0" alt="" id="Img1" /></a></p>
<p>Replies are more complicated.  In the example above the guy on the left, @vet, replies to @hiro by prefixing his tweet with "@hiro".  However, this probably doesn't work like you think.  The tweet obviously shows up in @hiro's timeline, but it also shows up in @admirer's timeline because she follows both people mentioned in the tweet (@hiro <i>and</i> @vet).  But the tweet does <i>not</i> show up to @effusive because, while he follows @vet, the author of the tweet, he doesn't follow @hiro, the person being mentioned.</p>
<p>Getting this scoping rule wrong is way too easy.  For instance you can't just announce that someone did something great.  If @hiro started a tweet with "@vet gave a great anti-aardvark presentation" then most of his followers (e.g. @effusive) wouldn't actually see the tweet!  I've seen seasoned twitter users make this mistake.</p>
<p>As an interesting aside twitter can help track conversations.  If you click a reply button in a twitter client or on the website twitter will keep track of which tweet you replied to and then help piece a conversation together.  But if you simply start a new tweet with "@somone" without clicking reply, the above scoping rules still apply, but twitter won't help anyone reconstruct the conversation.</p>
<p>Finally a word on notifications: If someone mentions you (via a reply or anywhere in their tweet) and you follow them then you will get an e-mail and possibly an SMS notification.  If someone that you do not follow replies to you, you <i>will not</i> get an email.  For this reason you must either frequently check the "mentions and more" section of the website or use a column based twitter client, discussed in the final section on lists.</p>
<p>Interesting statistic: On average only 23% of tweets get a reply. (<a href="http://www.sysomos.com/insidetwitter/engagement/">more</a>)</p>
<p>Another one: 38% of tweets are conversational.  In other words 38% of tweets start with an "@". If your percentage of replies is lower you probably aren't using twitter to its fullest. (<a href="http://www.pearanalytics.com/blog/wp-content/uploads/2010/05/Twitter-Study-August-2009.pdf">more</a>)</p>
<p><b>#3 Reply-All's</b></p>
<p><a href="http://3.bp.blogspot.com/-VBvIcRq5ANk/TtRbXahnI2I/AAAAAAAAByc/U1KHy4J3x0Q/s1600/3.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 379px; height: 333px;" src="http://3.bp.blogspot.com/-VBvIcRq5ANk/TtRbXahnI2I/AAAAAAAAByc/U1KHy4J3x0Q/s400/3.png" border="0" alt="" id="Img2" /></a></p>
<p>So what happens if you want to reply to someone, but still have it show up in the timelines of <i>all</i> of your followers?  As long as your tweet doesn't start with an "@" symbol then you're fine.  So the convention that has grown up is to prefix your tweet with a "." and then the "@someone".  In the example above @effusive now sees the tweet where he didn't in a standard reply.</p>
<p>Interesting statistic: The highest usage rate of twitter to date occurred during the 2011 FIFA Women's World Cup Final between Japan and the United States when 7,196 tweets were published per second! (<a href="http://www.usatoday.com/tech/news/2011-07-18-world-cup-twitter-record_n.htm">more</a>)</p>
<p><b>#4 Old Style Retweet or "Retweet with Comment"</b></p>
<p><a href="http://4.bp.blogspot.com/-T2Z7KRpWud8/TtRbXh_DKuI/AAAAAAAABys/EHV8GHZIRrE/s1600/4.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 400px; height: 282px;" src="http://4.bp.blogspot.com/-T2Z7KRpWud8/TtRbXh_DKuI/AAAAAAAABys/EHV8GHZIRrE/s400/4.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5680265489838975714" /></a></p>
<p>Prior to late 2009 if you saw a tweet you wanted to share with your followers you would retweet (RT) it by copy and pasting their tweet and prefixing it with "RT @author".  The problem from a scoping perspective was that people would get duplicates.  In the example above @admirer sees a duplicate from @vet when he retweets @hiro's tweet.</p>
<p>There are other problems with old style retweets unrelated to scoping.  One problem is that you get long chains of "RT @person1 RT @person2 ...".  Another problem is it was hard to follow a person but not all their retweets.  The biggest problem is old style retweets take valuable characters away from your available 140, and sometimes require mangling the original.</p>
<p>Old style retweeting is still in use today primarily from people wish to retweet but add a comment, but also because it allows people to reach a wider audience (since new style retweets won't show up in searches or lists, more on this later).</p>
<p>Interesting statistic: Only 6% of tweets get retweeted (<a href="http://socialtimes.com/report-71-percent-of-tweets-do-not-get-a-single-reply-or-retweet_b24365">more</a>)</p>
<p><b>#5 New Style Retweet</b></p>
<p><a href="http://2.bp.blogspot.com/-OfR_u71pkK8/TtRbYFzvYkI/AAAAAAAABy4/n_JlWBmX-3Q/s1600/5.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 400px; height: 338px;" src="http://2.bp.blogspot.com/-OfR_u71pkK8/TtRbYFzvYkI/AAAAAAAABy4/n_JlWBmX-3Q/s400/5.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5680265499455218242" /></a></p>
<p>In November of 2009 twitter rolled out a new technique for retweeting aimed at solving the problems mentioned above.  It caused a lot of confusion, but did solve the problems.</p>
<p>The end result of new style retweets from a scoping perspective is that sometimes people see tweets from people they don't follow.  In the example above @effusive sees @hiro's tweet in his timeline even though he doesn't follow @hiro, because @vet performed a new-style retweet.</p>
<p>If you click the retweet button on the twitter website today it will perform a new style retweet.  Some twitter clients like TweetDeck give you the option.  The only way to perform an old style retweet or retweet with comment via the website is to copy and paste the message.</p>
<p>Interesting statistic: Less than half of tweets are posted using the web user interface.  By far the most common twitter client is Tweetdeck with 8.48% of the market. (<a href="http://www.sysomos.com/insidetwitter/clients/">more</a>)</p>
<p><b>#6 Direct Messages</b></p>
<p><a href="http://2.bp.blogspot.com/-hTvmYv4PA7k/TtRcUt8ld_I/AAAAAAAABzE/7gD3kRqy8Rc/s1600/6.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 400px; height: 276px;" src="http://2.bp.blogspot.com/-hTvmYv4PA7k/TtRcUt8ld_I/AAAAAAAABzE/7gD3kRqy8Rc/s400/6.png" border="0" alt="" id="Img4" /></a></p>
<p>Direct messages are simple.  Prefix your tweet with "D somone" (no at symbol before the name) and they will be the only person that will see it.  Just like e-mail except the recipient will get an e-mail and a text message if they've set that up on their phone.  Note that neither people watching an included hashtag  (e.g. @spca) nor people mentioned will see direct messages unless they are the recipient.</p>
<p>Interesting statistic: Six percent of all tweets are sent via SMS. (<a href="http://www.quora.com/What-percentage-of-Twitter-users-get-their-Twitter-updates-predominately-from-direct-text-messages-as-opposed-to-the-website-or-3rd-party-Apps">more</a>)</p>
<p><b>#7 Lists</b></p>
<p>The last scoping topic worthy of mention is lists.  This fantastic feature was added by twitter in late 2009.  It allows you to organize the people you follow.  For instance I have a private "Infrequent Posters" list that I try very hard to never miss a tweet from.  Meanwhile I follow enough people that my main list is more like a stream that I dip into but don't get stressed out if I miss some of.</p>
<p>Lists work best when used in conjunction with a column based twitter clients (e.g. TweetDeck).  These types of twitter clients are the only way to go if you want to become a twitter pro.  If you've gotten to the point where you start missing content from important people (e.g. your real life friends), or you're missing responses to your tweets, or mentions from people you don't follow: then you probably need lists, but you absolutely need something like TweetDeck.</p>
<p><a href="http://3.bp.blogspot.com/-xyrC1APLTqM/TtRcU6p58_I/AAAAAAAABzQ/cUvaNcE8_zk/s1600/7.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="cursor:pointer; cursor:hand;width: 368px; height: 321px;" src="http://3.bp.blogspot.com/-xyrC1APLTqM/TtRcU6p58_I/AAAAAAAABzQ/cUvaNcE8_zk/s400/7.png" border="0" alt="" id="Img3" /></a></p>
<p>In regards to scoping, lists contain one subtlety that you need to be aware of.  They do not support new style retweets.  In the example above @vet posts a normal tweet.  He then new-style retweets one of @hiro's tweets.  @effusive follows @vet and has also placed him into a list.  While the list helps @effusive not miss tweets from @vet, it does not end up displaying @hiro's tweet.  </p>
<p>Note that this rule applies both to people who maintain their own lists as well as to people who follow lists maintained by other people (e.g. your company may maintain a public list of its twitter enabled employees).</p>
<p>Interesting Statistic: Pointless babble is the most common type of content on twitter.  It represents 40.55% of all traffic. (<a href="http://www.pearanalytics.com/blog/wp-content/uploads/2010/05/Twitter-Study-August-2009.pdf">more</a>)</p>


<div style="float:right;padding:4px; text-align: center; width: 115px;">
<iframe src="http://platform.twitter.com/widgets/tweet_button.html#_=1322581831960&amp;count=horizontal&amp;id=twitter_tweet_button_0&amp;lang=en&amp;original_referer=http%3A%2F%2Frapidapplicationdevelopment.blogspot.com%2F2011%2F11%2Fhow-to-get-most-from-twitter.html&amp;related=lprichar%3ALee%20Richardson%20Blog&amp;text=RT%20%40lprichar%20How%20To%20Get%20The%20Most%20From%20Twitter%3A%20Understand%20Scoping%20Rules&amp;url=http%3A%2F%2Frapidapplicationdevelopment.blogspot.com%2F2011%2F11%2Fhow-to-get-most-from-twitter.html" allowtransparency="true" frameborder="0" scrolling="no" class="twitter-share-button twitter-count-horizontal" style="width: 110px; height: 20px; " title="Twitter For Websites: Tweet Button"></iframe>
<script type="text/javascript">
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2011/11/how-to-get-most-from-twitter.html';

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(document.createElement('br'));
        div.appendChild(dotnetkicksLink);
        document.write(div.innerHTML);
    </script>
<p></p>
<div id="___plusone_0" style="height: 20px; width: 90px; display: inline-block; text-indent: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: none; line-height: normal; font-size: 1px; vertical-align: baseline; background-position: initial initial; background-repeat: initial initial; "><iframe allowtransparency="true" frameborder="0" hspace="0" id="I1_1322581832741" marginheight="0" marginwidth="0" name="I1_1322581832741" scrolling="no" src="https://plusone.google.com/_/+1/fastbutton?url=http%3A%2F%2Frapidapplicationdevelopment.blogspot.com%2F2011%2F11%2Fhow-to-get-most-from-twitter.html&amp;size=medium&amp;count=true&amp;annotation=bubble&amp;hl=en-US&amp;jsh=m%3B%2F_%2Fapps-static%2F_%2Fjs%2Fwidget%2F__features__%2Frt%3Dj%2Fver%3DJJ_UMfXdHS0.en_US.%2Fsv%3D1%2Fam%3D!7cXxqVkrvlyIEO88iA%2Fd%3D1%2F#id=I1_1322581832741&amp;parent=http%3A%2F%2Frapidapplicationdevelopment.blogspot.com&amp;rpctoken=152461457&amp;_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe" style="width: 90px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; height: 20px; position: static; left: 0px; top: 0px; visibility: visible; " tabindex="-1" vspace="0" width="100%" title="+1"></iframe></div>
<script src="http://platform.twitter.com/widgets.js" type="text/javascript">
</script>
</div>

<p><b>Conclusion</b></p>
<p>Twitter may appear to be fairly simple at first glance.  In reality it has grown over the years to become very sophisticated.  Sophisticated and incredibly powerful.  But to fully tap that power you must understand the scoping rules and subtleties surrounding things like replies, retweets, and lists.  Hopefully you're closer now.</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/how_to_get_the_most_from_twitt.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/how_to_get_the_most_from_twitt.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">twitter</category>
            
            <pubDate>Tue, 29 Nov 2011 10:36:04 -0500</pubDate>
        </item>
        
        <item>
            <title>Integrating JavaScript and C# with Script#</title>
            <description><![CDATA[<p>Have you ever had an enum in your server code that you wanted to access in client side code?  Or wanted the safety of compile time errors when there are discrepancies between your server-side and client-side code?  Or had a C# Data Transfer Object (DTO) that you wanted to enable Intellisense for in JavaScript?  I hadn't found a good solution either ... until now.</p>
<p><b>Compiling C# to What!?</b></p>

<div style="float:right; overflow: auto; margin-left:10px;">
<script type='text/javascript'> 
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2011/08/integrating-javascript-and-c-with.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script> 
</div>

<p>Compiling C# code into JavaScript may seem foreign, but <a href=" http://projects.nikhilk.net/ScriptSharp ">Script#</a> is a mature technology that is absolutely worth a look.  Our team has been using it very happily for about three months.  We've found a number of benefits  including:</p>

<ul>
<li>Consistently working Intellisense</li>
<li>Better encapsulation</li>
<li>Simpler Object Orientation</li>
<li>Easier deployment (Script# compiles multiple files to a single, optionally minified file)</li>
<li>Safer refactoring</li>
<li>Simpler unit testing</li>
<li>Type safety; and</li>
<li>Design time syntax checking (no more mistyping a variable and accidentally declaring it to the global scope)</li>
</ul>

<p>Scott Hanselman covered most of these topics in last month's Hanselminutes episode: <a href=" http://www.hanselminutes.com/default.aspx?showID=296">Script# Compiles to JavaScript</a>.  If you have a spare car ride I definitely recommend the listen.  But what wasn't covered were some additional benefits provided by an off the beaten path approach to this great technology.  The main benefit is tighter server side C# to client side JavaScript integration.  A secondary benefit is less of a dependency on Script#.</p>

<p><b>To the Command Line</b></p>

<p>Typically to get going with Script# you: </p>

<ol>
<li>Install the Script# Visual Studio plug-in</li>
<li>File -> New project</li>
<li>Select "Script Library" and</li>
<li>Compile to generate JavaScript</li>
</ol>

<p>Nice and easy.  The down side to this approach is you can't easily include files outside of your project.  Specifically, you can't include data transfer objects or enum's from your server side code.  Furthermore, all of your team members must install Script#.  If instead you compile with Script#'s "ssc.exe" command you obtain more control and get less dependency.</p>

<p><b>How-To</b></p>

<p>The how-to looks something like this:</p>

<ol>

<li><a href="http://projects.nikhilk.net/ScriptSharp">Download</a> and install Script#</li>
<li>Add a Class Library (not a Script# project)</li>
<li>Project properties -> Build -> Advanced -> "Do not reference mscorlib"<br />
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-u7QvzHOOfxE/TlRhVwoGyII/AAAAAAAABu8/Vonkzc8nNLc/s1600/mscorlib.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 235px;" src="http://4.bp.blogspot.com/-u7QvzHOOfxE/TlRhVwoGyII/AAAAAAAABu8/Vonkzc8nNLc/s400/mscorlib.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5644243259460339842" /></a>
</li>

<li>Ideally move the Script# files (C:\Program Files (x86)\ScriptSharp) locally to the solution and check them into source control to a Libs or something similar</li>

<li>Remove all references, but add: ScriptSharp.dll, ScriptSharp.Web.dll, Script.Jquery</li>
<li>Edit your .csproj to manually reference Script#'s mscorlib (right click, Unload project, Edit MyProject.csproj)<br />
    <br />
    <span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">Reference</span><span style="font-size:9.5pt;
line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> </span>
    <span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;color:red;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">Include</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">=</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA">&quot;<span style="color:blue">mscorlib, Version=0.7.0.0, 
    Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4, processorArchitecture=MSIL</span>&quot;<span 
        style="color:blue">&gt;<br />
    <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="color:#A31515">SpecificVersion</span><span 
        style="color:blue">&gt;</span>True<span style="color:blue">&lt;/</span><span 
        style="color:#A31515">SpecificVersion</span><span style="color:blue">&gt;<br />
    <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="color:#A31515">HintPath</span><span 
        style="color:blue">&gt;</span>..\Libs\ScriptSharp\v1.0\mscorlib.dll<span 
        style="color:blue">&lt;/</span><span style="color:#A31515">HintPath</span><span 
        style="color:blue">&gt;<br />
    &lt;/</span><span style="color:#A31515">Reference</span><span style="color:
blue">&gt;</span></span><br /><br /></li>

<li>Modify AssemblyInfo.cs and remove the following lines:<br />
<br />
[assembly: ComVisible(false)]<br />
[assembly: Guid("b5e2449f-193c-46d1-9023-9143618d8491")]<br />
<br />
</li>

<li>Modify AssemblyInfo.cs and add the following:<br />
<br />
[assembly: ScriptAssembly("ScriptSharpDemoAssembly")<br />
<br />
</li>

<li>Ensure it compiles in Visual Studio</li>
<li>Create a batch script or PowerShell script that compiles using ssc.exe like this:<br />
<br />
..\Libs\ScriptSharp\v1.0\ssc.exe ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/debug ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/out:MyScriptSharp.js ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/ref:"..\Libs\ScriptSharp\v1.0\Framework\mscorlib.dll" ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;.\Properties\AssemblyInfo.cs ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;.\Class1.cs<br />
<br />

</li>
</ol>

<p>Notice the last two lines in the script are a list of the files that you want to include.  The point of this exercise is that you can now include files outside of your main Script# project in that list.</p>
<p>Now for completeness if you put a simple static method in Class1.cs, something like this:</p>
    <p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">namespace</span><span style="font-size:9.5pt;
line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA"> MyScriptSharp<br />
        {<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">class</span> <span style="color:#2B91AF">Class1<br />
        </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>{<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">static</span> <span style="color:blue">string</span> 
        HelloWorld()<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">
        return</span> <span style="color:#A31515">&quot;Hello World!&quot;</span>;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}<br />
        }</span></p>

<p>Then run the batch file you should get something like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA">Type.registerNamespace(<span style="color:maroon">&#39;MyScriptSharp&#39;</span>);<br />
    <br />
    <span style="color:darkgreen">
    ////////////////////////////////////////////////////////////////////////////////<br />
    // MyScriptSharp.Class1<br />
    <br />
    </span>MyScriptSharp.Class1 = <span style="color:blue">function</span> 
    MyScriptSharp_Class1() {<br />
    }<br />
    MyScriptSharp.Class1.helloWorld = <span style="color:blue">function</span> 
    MyScriptSharp_Class1$helloWorld() {<br />
    <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>
    <span style="color:maroon">&#39;Hello World!&#39;</span>;<br />
    }<br />
    <br />
    MyScriptSharp.Class1.registerClass(<span style="color:maroon">&#39;MyScriptSharp.Class1&#39;</span>);</span></p>

<p>Obviously you could get these results faster with approach #1.  But now you have a lot more control.</p>

<p><b>Summary</b></p>

<p>The main downside to this approach is maintaining the batch file is a bit of a hassle.  But the upsides are that you can include any file from your server-side C# code.  And any changes in that server-side code are automatically reflected in your JavaScript.  And any breaking changes in your server-side code generate compile time errors in your client side code.  And furthermore none of your team members need to install Script#.  For our team it's an easy tradeoff.  What about for yours?  Please share your thoughts in the comments or on <a href="http://twitter.com/#!/lprichar">twitter</a>.</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/integrating_javascript_and_c_w.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/integrating_javascript_and_c_w.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">script#</category>
            
            <pubDate>Tue, 23 Aug 2011 23:09:48 -0500</pubDate>
        </item>
        
        <item>
            <title>Advanced Burn Up Charts</title>
            <description><![CDATA[<p>If you've read my previous posts on the subject you know that I love agile <a href="http://www.nearinfinity.com/blogs/lee_richardson/forget_burndown_use_burnup_charts.html">burn up charts</a> for managing SCRUM style projects, particularly compared to burn down charts.</p>
<div style='float:right; margin-left:10px;'> 
<script type='text/javascript'> 
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2011/04/advanced-burn-down-charts.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script> 
</div> 
<blockquote>
The problem is that burndown charts lack two essential pieces of information. First, how much work was actually accomplished during a given iteration (as opposed to how much work remains to be completed) and second how much total work the project contains (or if you prefer how much scope has increased each iteration). </blockquote>
<p>What you might not know is how flexible they can be.  In particular the example I gave last time has a problem.  Can you spot it?</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_gez10dNhuPk/SQExi1j16lI/AAAAAAAABlM/pqg4SgFBkIs/s1600-h/Burnup.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 273px;" src="http://4.bp.blogspot.com/_gez10dNhuPk/SQExi1j16lI/AAAAAAAABlM/pqg4SgFBkIs/s400/Burnup.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5260540314308176466" /></a></p>
<p>The problem is that the scope increase of 20 points in iteration six might very well have had zero impact on the actual deployment date.  Those points might have all been low priority tasks that the team will work on after they deploy the initial 100 points.  Wouldn't it be nice if the burn up chart could convey priority information as well?</p>
<p>So that's exactly what I did on my current project last week, and it appeared to be a big hit.  And with the addition of some Excel trend lines the chart was able to convey a lot of insight into the project:</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-nqHRslSmh3I/TaL1f1sZ2CI/AAAAAAAABt4/Z5i4iyXrFh8/s1600/Burnup1.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 173px;" src="http://1.bp.blogspot.com/-nqHRslSmh3I/TaL1f1sZ2CI/AAAAAAAABt4/Z5i4iyXrFh8/s400/Burnup1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5594303614485649442" /></a></p>
<p>Obviously all that data is made up, but the chart still tells an interesting story:</p>
<ul>
<li>The customer hasn't been adding high priority tasks, perhaps because there is a hard deadline approaching</li>
<li>Because of the customer's restraint in adding high priority tasks the team can be fairly confident that they will finish all the high priority tasks by Iteration 3</li>
<li>While the customer hasn't added high priority tasks they have still been able to be agile by adding normal and low priority tasks</li>
</ul>
<p>What's really wonderful about this way of reporting is that it gives the customer the flexibility to add scope to future iterations while maintaining near term deadlines.  In short it supports what agile is supposed to be about.</p>
<p>But why stop there?  Depending on the story you need to tell or the scenario you need to evaluate perhaps you could incorporate team member contributions.  For example:</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-J0lMgjTfmFw/TaL1fwd7rqI/AAAAAAAABuA/p1QyRmW5Byk/s1600/Burnup2.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 162px;" src="http://3.bp.blogspot.com/-J0lMgjTfmFw/TaL1fwd7rqI/AAAAAAAABuA/p1QyRmW5Byk/s400/Burnup2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5594303613082775202" /></a></p>
<p>In this example we can try to show what might happen if we remove a particular team member or if we'd never had a particular team member.  What's unique about this way or reporting is that it's incorporating the backlog's increasing trend into account.  While it's possible that the backlog may increase or decrease at a different rate with a different team makeup, it's a better scenario than ignoring the rate of increase of the backlog all together.</p>
<p>Perhaps we could incorporate other information.  Maybe bug vs. feature information.  Or planned vs. actual (e.g. task slippage) information.  It seems like there is a lot of potential.  Any other ideas out there?  Feel free to post in the comments or via <a href="http://www.twitter.com/lprichar">twitter</a>.  If there's enough interest I'd be happy to post another screencast similar to the last one I did on <a href=" http://www.nearinfinity.com/blogs/lee_richardson/video_how_to_create_burndown_c.html">how to produce burn up and burn down with SharePoint and Excel</a> except this time with trends and priorities.</p>
<p>So overall while these charts may be a little more complicated than a traditional burn down chart they would make an excellent talking point during a PowerPoint presentation, or as part of your iteration close out.  And with a little training I bet just about any customer would learn to love the insight they provide.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/advanced_burn_up_charts.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/advanced_burn_up_charts.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Agile Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">burndown</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">burnup</category>
            
            <pubDate>Mon, 11 Apr 2011 08:52:53 -0500</pubDate>
        </item>
        
        <item>
            <title>Death to the DAO and How to Test LINQ</title>
            <description><![CDATA[<p>Occasionally I hear complaints that LINQ is hard to unit test.  These complaints aren't about LINQ to objects, mind you, they're specific to the complexities of the flavors of LINQ that turn C# code into something else like SQL or CAML using <a href="http://rapidapplicationdevelopment.blogspot.com/2008/03/expression-trees-why-linq-to-sql-is.html">expression trees</a>.  The most common technologies are LINQ to SQL, the Entity Framework, or in my case at the moment LINQ to SharePoint.  In this post I'm going to propose a technique that makes testing LINQ not just easy, but downright elegant - assuming you're ok with extension methods - lots of extension methods.  And assuming you're ready to kill your Data Access Objects (DAO) tier.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/07/death-to-dao-and-how-to-test-linq.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>


<p><b>The Unit Testing Problem</b></p><p>Any architecture needs a place to put code that finds entities.  For instance FindBySocialSecurityNumber().  In a traditional architecture we might put a method like this is in a DAO layer.  If so our method will look something like this:</p><p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">public</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> <span style="color:blue">class</span> <span style="color:#2B91AF"> EmployeesDao</span> {<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span> <span style="color:#2B91AF">Employee</span> FindBySSN(<span   style="color:#2B91AF">Context</span> ctx, <span style="color:blue">string</span>  ssn) {<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>  ctx.Employees.SingleOrDefault(e =&gt; e.Ssn == ssn);<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}<br /> }</span></p><p>So how would we go about unit testing this?</p><p>One fairly typical solution would be to use an in-memory database.  That approach works if our data store is a database, but it certainly doesn't work if the data store is something less traditional like SharePoint.  But even if our store is a database, we'll still have the hassle of setting up the in-memory database.</p><p>Another solution might be to use a mock Context that returns an IQueryable<Employee>.  But wouldn't it be wonderful if we could avoid mocking all together?</p><p><b>Killing the DAO</b></p><p>The first question is why we even have a DAO tier to begin with.  The original idea was that we wanted a place to put code specific to a particular data store.  In other words we wanted to isolate the code that will need to be changed should the data store switch from SQL Server to Oracle.  But isn't that exactly what LINQ does?  I'd be pretty surprised if there wasn't a decent LINQ provider for just about any data store at this point that required more than minimal code changes.  So why not embrace LINQ and reconsider alternatives to a DAO tier?</p><p>One alternative that I've been using for over a month now is to switch to extension methods.  To give credit where it's due the idea originated with a conversation with fellow <a href="http://www.nearinfinity.com">Near Infinity</a> employee <a href="http://www.nearinfinity.com/blogs/joe_ferner/">Joe Ferner</a>.  And I'm sure the idea isn't particularly original (please post in the comments if you know others that use this approach).</p><p>Using this technique our code changes from something like this:</p><p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">var</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:R-SA"> employeeDao = <span style="color:blue">new</span> <span style="color:#2B91AF">EmployeesDao</span>(); <span style="color:green">//  or use IOC of course<br /> </span>employeeDao.FindBySSN(ctx, <span style="color:#A31515">&quot;111-11-1111&quot;</span>);</span></p><p>To something like this:</p><p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">ctx.Employees.FindBySSN(<span style="color:#A31515">&quot;111-11-1111&quot;</span>);</span></p><p>Among other things I find this far more aesthetically pleasing because each of the three elements to the statement represent a subsequent filtering of data.  It's a more functional way of looking at things.</p><p>We could implement this off of the Employees property of the context if we have control over that (which I don't with spmetal). But if we implement this as an extension method like this:</p><p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">public</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> <span style="color:blue">static</span> <span style="color:blue">class</span> <span style="color:#2B91AF">EmployeeExtensions</span> {<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:#2B91AF">Employee</span>  FindBySSN(<span style="color:blue">this</span> <span style="color:#2B91AF"> IQueryable</span>&lt;<span style="color:#2B91AF">Employee</span>&gt; employees, <span style="color:blue">string</span> ssn) {<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>  employees.SingleOrDefault(e =&gt; e.Ssn == ssn);<br /> <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}<br /> }</span></p><p>We now have something that's considerable easier to unit test.</p><p><b>Testing It</b></p><p>Once we've refactored our function as an extension method that filters down the corpus of entities, we can test the code using in-memory objects with a call to .AsQueryable().  For instance:</p><p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">public</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:R-SA"> <span style="color:blue">void</span>  FindBySSN_OneSsnExists_EmployeeReturned() {<br /> <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>  employees = <span style="color:blue">new</span> [] { <span style="color:blue"> new</span> <span style="color:#2B91AF">Employee</span> { Ssn = <span style="color:#A31515">&quot;111-11-1111&quot;</span> } };<br /> <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>  actual = employees.AsQueryable().FindBySSN(<span style="color:#A31515">&quot;111-11-1111&quot;</span>);<br /> <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Assert</span>.IsNotNull(actual); <br /> }</span></p><p>Notice we didn't have to mock anything.</p><p><b>Testability, but at What Cost?</b></p><p>This technique works great for the example above, but how does it scale to harder problems and what other downsides are there?</p><p>As far as scalability I've found this technique works great for every scenario I've run across in the month I've been doing it.  It works for joins, aggregations, and even for inserts, update, and deletes.</p><p>As far as downsides the astute reader may be wondering about mockability.  For instance what if we want to mock the call to FindBySSN and give it the exact Employee that will be returned.  This scenario is admittedly harder.  But what I've found is that far more often than not I don't really need to mock the types of things that used to live in the DAO tier.  Instead I just mock the Employee object off of context to return in-memory objects and make my tests slightly larger in scope.  Most of the time I find the larger scope increases the usefulness of the test.  In the occasional case where I do really want to mock the "DAO" tier I use a technique described in <a href=" http://www.clariusconsulting.net/blogs/kzu/archive/2009/02/19/Makingextensionmethodsamenabletomocking.aspx">this post</a> by Daniel Cazzulino.</p><p><b>Conclusion</b></p><p>Obviously there is more to this architecture, for instance how do you handle insert and update operations?  The short answer is it's easy, but I'll save that topic for a future post.  For now why not give this approach a try?  You weren't really happy with that useless old DAO tier anyway, were you?  I say we eradicate it and never look back.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/death_to_the_dao_and_how_to_te.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/death_to_the_dao_and_how_to_te.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">architecture</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">LINQ</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">testing</category>
            
            <pubDate>Thu, 22 Jul 2010 22:42:43 -0500</pubDate>
        </item>
        
        <item>
            <title>ASP.AJAX 4 Templates Part 4 - jQuery, and Manual JSON Object Manipulation</title>
            <description><![CDATA[<p>This is part 4 of a multi-part series exploring building client side AJAX applications with ASP.Net AJAX 4 Templating and the WCF Data Services (aka ADO.Net Data Services, aka oData, aka Astoria) in SharePoint 2010.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/04/aspajax-4-templates-part-4-jquery-and.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html">Part 1 - Exploring WCF Data Services in SharePoint 2010</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html">Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html">Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates</a><br/>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html">Part 4 - jQuery and Manual JSON Object Manipulation</a>
</p>

<p>In the previous posts in this series I've shown how you can access SharePoint data using WCF Data Services, how you can display that data using ASP.Net AJAX 4.0 Templates, and how you can write data back to SharePoint.</p>

<p>In this post I'll take writing data back to SharePoint a step further by showing how you can modify non-visible fields by modifying JSON objects directly.  More specifically I'll enable dragging user story index cards on a virtual bulletin board using a jQuery plugin, save the X and Y coordinates back to JSON objects, and then save the updated records back to SharePoint. </p>

<p><b>Cards on a Corkboard</b></p>

<p>The first thing I'll do is style the cards and display them with absolute position.  While I'm at it I'll also reference the <a href=" http://jqueryui.com/demos/droppable/ ">draggable</a> jQuery UI plugin.  If you're following along at home just built a custom .js download from the jQuery UI site, drop it in your layouts directory and add a reference.  So my PageHead content control now looks like this:</p>

<p class="MsoNormal"><span style="font-size:9.5pt;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:blue">&lt;</span><span style="font-size:9.5pt;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:maroon">asp</span><span style="font-size:9.5pt;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:blue">:</span><span style="font-size:9.5pt;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:maroon">content</span><span    style="font-size:9.5pt;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas">  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">id</span><span style="color:blue">=&quot;PageHead&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">contentplaceholderid</span><span style="color:blue">=&quot;PlaceHolderAdditionalPageHead&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />  <br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjax.js&quot;&gt;&lt;/</span><span    style="color:maroon">script</span><span style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxDataContext.js&quot;&gt;&lt;/</span><span    style="color:maroon">script</span><span style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxTemplates.js&quot;&gt;&lt;/</span><span    style="color:maroon">script</span><span style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxAdoNet.js&quot;&gt;&lt;/</span><span    style="color:maroon">script</span><span style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../jquery-ui-1.8.custom/js/jquery-1.4.2.min.js&quot;&gt;&lt;/</span><span    style="color:maroon">script</span><span style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:red">src</span><span style="color:blue">=&quot;../jquery-ui-1.8.custom/js/jquery-ui-1.8.custom.min.js&quot;&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;/</span><span style="color:maroon">script</span><span    style="color:blue">&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  <span style="color:blue">&lt;</span><span style="color:maroon">style</span>  <span style="color:red">type</span><span style="color:blue">=&quot;text/css&quot;&gt;<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:maroon">.sys-template<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">display</span>: <span style="color:blue">none</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  }<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:maroon">.userstorycard<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">border</span>: <span style="color:blue">1px</span>  <span style="color:blue">solid</span> <span style="color:blue">#777777</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">width</span>: <span style="color:blue">200px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">position</span>: <span style="color:blue">  absolute</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">cursor</span>: <span style="color:blue">move</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  }<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:maroon">.carddescription<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">font-size</span>: <span style="color:blue">13px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">background-image</span>: <span style="color:blue">  url(&#39;card_bg.jpg&#39;)</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">padding</span>: <span style="color:blue">0px</span>  <span style="color:blue">5px</span> <span style="color:blue">5px</span>  <span style="color:blue">5px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  }<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  <span style="color:maroon">.cardtitle<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">font-size</span>: <span style="color:blue">15px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">font-weight</span>: <span style="color:blue">bold</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">padding</span>: <span style="color:blue">0px</span>  <span style="color:blue">0px</span> <span style="color:blue">0px</span>  <span style="color:blue">0px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">border-bottom</span>: <span style="color:blue">  1px</span> <span style="color:blue">solid</span> <span style="color:blue">red</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">background-color</span>: <span style="color:blue">  White</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color:red">padding</span>: <span style="color:blue">0px</span>  <span style="color:blue">5px</span> <span style="color:blue">0px</span>  <span style="color:blue">5px</span>;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>  }<br style="mso-special-character:line-break" />  <![if !supportLineBreakNewLine]>  <br style="mso-special-character:line-break" />  <![endif]><o:p></o:p></span> </p> <span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"><span style="mso-spacerun:yes"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>...</span>

<p>The next thing to do is add X and Y fields to the user story list in SharePoint.  And finally display the cards with absolute positioning:</p>

<span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&lt;</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">div</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> <span style="color:#A31515">xmlns</span><span     style="color:blue">:</span><span style="color:red">sys</span><span     style="color:blue">=&quot;javascript:Sys&quot;</span> <span style="color:red">class</span><span     style="color:blue">=&quot;background&quot;&gt;<br />   </span><span style="mso-spacerun:yes">&nbsp; </span><span style="color:blue">&lt;</span><span     style="color:#A31515">div</span> <span style="color:red">id</span><span     style="color:blue">=&quot;userStories&quot;</span> <span style="color:red">class</span><span     style="color:blue">=&quot;sys-template&quot;&gt;<br />   </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span     style="color:#A31515">div</span> <span style="color:red">class</span><span     style="color:blue">=&quot;userStoryCard&quot;</span>   <br />   <span style="mso-spacerun:yes">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span><b     style="mso-bidi-font-weight:normal"><span style="color:#A31515">sys</span><span     style="color:blue">:</span><span style="color:red">style</span><span     style="color:blue">=&quot;</span>{{ &#39;<span style="color:red">left</span>:   <span style="color:blue">&#39; + X + &#39;px</span>; <span style="color:red">top</span>:   <span style="color:blue">&#39; + Y + &#39;px</span>;&#39;}}<span style="color:blue">&quot;&gt;<br />   <br />   </span></b><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">   &lt;</span><span style="color:#A31515">div</span> <span style="color:red">class</span><span     style="color:blue">=&quot;userStoryTitle&quot;&gt;</span>{{ Title }}<span     style="color:blue">&lt;/</span><span style="color:#A31515">div</span><span     style="color:blue">&gt;<br />   </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span><span style="color:blue">&lt;</span><span     style="color:#A31515">div</span> <span style="color:red">class</span><span     style="color:blue">=&quot;userStoryBody&quot;&gt;&lt;</span><span style="color:#A31515">div</span><span     style="color:blue">&gt;</span>{{ Description }}<span style="color:blue">&lt;/</span><span     style="color:#A31515">div</span><span style="color:blue">&gt;<br />   </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span     style="color:#A31515">div</span><span style="color:blue">&gt;<br />   </span><span style="mso-spacerun:yes">&nbsp; </span><span style="color:blue">&lt;/</span><span     style="color:#A31515">div</span><span style="color:blue">&gt;<br />   &lt;/</span><span style="color:#A31515">div</span><span style="color:blue">&gt;</span></span></p>

<p>Notice the sys:style attribute.  The sys: part is the namespace you need to add for attributes when using templating that I mentioned in <a href=" http://rapidapplicationdevelopment.blogspot.com/2010/03/client-side-ajax-applications-in_3617.html">part three</a>.  Also notice the JavaScript string concatenation inside the binding.  You can put in any JavaScript in there that you like.  So now if you manually set X and Y values in SharePoint for a card the card shows in the right place.  But we're still missing the ability to drag cards.</p>

<p><b>Making Cards Draggable with jQuery</b></p>

<p>In order to enable dragging support you're supposed to call the draggable() function on the DOM elements you want to make draggable.  Simple right?  You just call $(".userstorycard").draggable() which should find every element with a class of userstorycard and call draggable() on it.</p>

<p>But if you do this onLoad() then ASP.Net AJAX Templating engine hasn't had a chance to render the new DOM elements yet.  Fortunately the DataView has the JavaScript equivalent of an OnRendered event that you can tie into:</p>

<p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">function</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> onLoad() {<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>dataContext = $create(<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Sys.Data.AdoNetDataContext,  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{ serviceUri:  <span style="color:maroon">&quot;/demoprep/_vti_bin/ListData.svc&quot;</span> }<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>);<br />  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>dataView = $create(<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Sys.UI.DataView,<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>autoFetch:  <span style="color:blue">true</span>,<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dataProvider: dataContext,<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>fetchOperation:  <span style="color:maroon">&quot;UserStories&quot;</span>,<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>fetchParameters: { $top: 20 }<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>},<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span>rendered: onRendered<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>},<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</span><span style="color:blue">null</span>,<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>$get(<span style="color:maroon">&#39;userStories&#39;</span>)<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>);<br />  }<br />  <br />  <span style="color:blue">function</span> onRendered() {<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:darkgreen">// from   http://jqueryui.com/demos/draggable/<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>$(<span style="color:maroon">&quot;.userstorycard&quot;</span>).draggable();<br />  }</span></p>

<p>And that's it for enabling dragging.  Pretty simple.  The result looks like this:</p>

<p><a href="http://1.bp.blogspot.com/_gez10dNhuPk/S8C5Crk0xAI/AAAAAAAABss/y3vsN5TbKQA/s1600/part4-1-screenshot.jpg"><img style="cursor:pointer; cursor:hand;width: 400px; height: 334px;" src="http://1.bp.blogspot.com/_gez10dNhuPk/S8C5Crk0xAI/AAAAAAAABss/y3vsN5TbKQA/s400/part4-1-screenshot.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458566204081095682" /></a></p>

<p>Ok, well you can't see the dragging support, but it's there, trust me.  And it's pretty cool except for one thing.</p>

<p><b>Saving Non-Visible Properties</b></p>

<p>The problem is that every time you refresh the page the nice layout you've done disappears and everything goes back to being stacked one on top of the other in the upper left.  My first thought was to create input type=hidden form elements on the page.  This approach causes a lot more plumbing code than is necessary.  The better way is that you can access the underlying in-memory JSON objects.  Step one is to register an "event" for when the user stops dragging a card.</p>

<p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">function</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> onRendered() {<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:darkgreen">// from   http://jqueryui.com/demos/draggable/<br />  </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>$(<span style="color:maroon">&quot;.userstorycard&quot;</span>).draggable({<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span>stop: onDragStop<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>});<br />  }</span></p>

<p>Once you wire that up the onDragStop() function is where all the interesting stuff happens:</p>

<p><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">function</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:Consolas;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> onDragStop(event, ui) {<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>   userStoryCard = ui.helper[0];<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>   selectedUserStoryJsonObject =  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span>dataView.findContext(userStoryCard).dataItem;<br />  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>   newX = ui.position.left;<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span>   newY = ui.position.top;<br />  <br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  Sys.Observer.setValue(selectedUserStoryJsonObject, <span style="color:maroon">  &quot;X&quot;</span>, newX);<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>  Sys.Observer.setValue(selectedUserStoryJsonObject, <span style="color:maroon">  &quot;Y&quot;</span>, newY);<br />  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>dataContext.saveChanges();<br />  }</span></p>

<p>The first line gets the DOM element that just the user just completed dragging.  The second line retrieves the in memory JSON object represented by that DOM element.  The next couple of lines get the X and Y that the user story card was dragged to relative to their parent DOM element.  And then something odd happens.</p>

<p>Sys.Observer.setValue looks so complicated.  Why couldn't we just call selectedUserStoryJsonObject.X = newX?</p>

<p>Well, if we'd done that the DataView wouldn't know about the change we just made.  If we then tried to call dataContext.saveChanges() nothing would get sent back to the server.  <a href=" http://msdn.microsoft.com/en-us/library/dd393596%28VS.100%29.aspx">Sys.Observer.setValue</a> notifies any interested parties, in this case the DataView, that a value has been changed.  And this enables the functionality we saw in <a href="">part two</a> where the DataView only sends the relevant records back to SharePoint instead of the entire set of JSON objects.</p>

<p>And so, with this code in place, we can now move user story cards around on the page and when we refresh the page or come back days later our layout has persisted back into SharePoint.</p>

<p><b>Conclusion</b></p>

<p>In this post you've seen how to directly modify the in-memory JSON objects and send them back to SharePoint.  Our application is finally getting interesting and I find it quite remarkable how little code it's taken.  In the next post I'll show how to do master-detail scenario's for editing user story cards.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">AJAX</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">jQuery</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint 2010</category>
            
            <pubDate>Sat, 10 Apr 2010 14:03:06 -0500</pubDate>
        </item>
        
        <item>
            <title>Client Side AJAX Applications in SharePoint 2010 - Part 3</title>
            <description><![CDATA[ <p>Note: This is one of a multi-part series exploring building client side AJAX applications with ASP.Net AJAX 4 Templating and the WCF Data Services (aka ADO.Net Data Services, aka oData, aka Astoria) in SharePoint 2010.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/03/client-side-ajax-applications-in_3617.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>

<p>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html">Part 1 - Exploring WCF Data Services in SharePoint 2010</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html">Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html">Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates</a><br/>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html">Part 4 - jQuery and Manual JSON Object Manipulation</a>
</p>

<p>In the previous two posts in this series I've shown how you can access SharePoint data using WCF Data Services and consume that data using ASP.Net AJAX 4 templates.  In this post I'll update the previous example in order to show how to write data back to SharePoint.</p>
<p><b>Templates and Linking</b></p>
<p>Before we go into writing data back let's modify our example to link each item back to the SharePoint DispForm.aspx page.  A naïve approach would look like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">ul</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> <span style="color:red">id</span><span style="color:blue">=&quot;userStoriesList&quot;</span>
 <span style="color:red">class</span><span style="color:blue">=&quot;sys-template&quot;&gt;<br />
 </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;&lt;</span><span 
  style="color:maroon">a</span> <span style="color:red">href</span><span 
  style="color:blue">=&quot;../../Lists/User%20Stories/DispForm.aspx?ID={{ID}}&quot;&gt;</span>{{ 
 Title }}<span style="color:blue">&lt;/</span><span style="color:maroon">a</span><span 
  style="color:blue">&gt;&lt;/</span><span style="color:maroon">li</span><span 
  style="color:blue">&gt;<br />
 &lt;/</span><span style="color:maroon">ul</span><span style="color:blue">&gt;</span></span></p>

<p>It turns out this approach doesn't work because the DataView won't look for the data binding syntax inside of attributes.  The next approach that might make sense would now be to set href to a data binding syntax and inside there do some string concatenation like so:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">li</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&gt;&lt;</span><span style="font-size:9.5pt;
line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;color:maroon;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">a</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA"> <span style="color:red">href</span><span 
  style="color:blue">=&quot;{{ &#39;../../Lists/User%20Stories/DispForm.aspx?ID=&#39; + ID 
 }}&quot;&gt;</span>{{ Title }}<span style="color:blue">&lt;/</span><span 
  style="color:maroon">a</span><span style="color:blue">&gt;&lt;/</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;</span></span></p>

<p>It turns out this doesn't work either, but for a different reason.  Apparently the DataView can't natively convert some HTML attributes like href and src for reasons <a href=" http://weblogs.asp.net/bleroy/archive/2008/07/30/using-client-templates-part-1.aspx">Bertrand La Roy</a> describes.  The solution is to prefix the attribute with the ASP.Net AJAX system namespace.  Typically you would define the system namespace on the HTML body element.  But with SharePoint you don't have access to this element.  Fortunately you can declare this namespace on any element so the following code works:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">div</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> <span style="color:red">xmlns</span><span style="color:blue">:</span><span 
  style="color:red">sys</span><span style="color:blue">=&quot;javascript:Sys&quot;&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:maroon">ul</span>
 <span style="color:red">id</span><span style="color:blue">=&quot;userStoriesList&quot;</span>
 <span style="color:red">class</span><span style="color:blue">=&quot;sys-template&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;&lt;</span><span 
  style="color:maroon">a</span> <span style="color:red">sys</span><span 
  style="color:blue">:</span><span style="color:red">href</span><span 
  style="color:blue">=&quot;{{ &#39;../../Lists/User%20Stories/DispForm.aspx?ID=&#39; + ID 
 }}&quot;&gt;</span>{{ Title }}<span style="color:blue">&lt;/</span><span 
  style="color:maroon">a</span><span style="color:blue">&gt;&lt;/</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:maroon">ul</span><span 
  style="color:blue">&gt;<br />
 &lt;/</span><span style="color:maroon">div</span><span style="color:blue">&gt;</span></span></p>

<p>Great.  Let's move on to updating data.</p>

<p><b>Live Binding Syntax</b></p>
<p>The {{ }} template syntax we've seen so far is what's known as one time binding.  When you use this syntax the expression is evaluated only once when the template is rendered.  What we want is one way live binding and/or two way live binding.</p>

<p>In order to understand the live bindings you need to understand that behind the scenes the DataView keeps an in memory copy of all of the JSON objects it downloads.  It's possible for the data in these objects to change.  And that's where one way live bindings come in.  When you use the syntax { binding [FieldName] }, the DataView will automatically update the binding when the underlying JSON object changes.</p>

<p>Two way live binding happens automatically when you use the one way live binding syntax on HTML INPUT elements.  For these scenarios the DataView automatically updates the in memory JSON objects.  Then the DataView updates any one way live binding's.</p>

<p>So let's throw two DataViews onto the page, one with one way live bound hyperlinks, one with two way bound HTML INPUT textbox elements and see what happens:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">script</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">
 function</span> pageInit() {<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span> 
 dataContext = $create(Sys.Data.AdoNetDataContext, { serviceUri:
 <span style="color:maroon">&quot;/demoprep/_vti_bin/ListData.svc&quot;</span> });<br />
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>$create(Sys.UI.DataView,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>{<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>autoFetch:
 <span style="color:blue">true</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>dataProvider: 
 dataContext,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>fetchOperation:
 <span style="color:maroon">&quot;UserStories&quot;</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>fetchParameters: { 
 $top: 20 }<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>},<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>$get(<span 
  style="color:maroon">&quot;userStoriesList&quot;</span>)<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>);<br />
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>$create(Sys.UI.DataView,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>{<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>autoFetch:
 <span style="color:blue">true</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>dataProvider: 
 dataContext,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>fetchOperation:
 <span style="color:maroon">&quot;UserStories&quot;</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>fetchParameters: { 
 $top: 20 }<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>},<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>$get(<span 
  style="color:maroon">&quot;userStoriesTable&quot;</span>)<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>);<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>Sys.Application.add_init(pageInit);<br />
 <span style="color:blue">&lt;/</span><span style="color:maroon">script</span><span 
  style="color:blue">&gt;</span><br />
 <br />
 <span style="color:blue">&lt;</span><span style="color:maroon">div</span>
 <span style="color:red">xmlns</span><span style="color:blue">:</span><span 
  style="color:red">sys</span><span style="color:blue">=&quot;javascript:Sys&quot;&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">ul</span> <span style="color:red">id</span><span 
  style="color:blue">=&quot;userStoriesList&quot;</span> <span style="color:red">class</span><span 
  style="color:blue">=&quot;sys-template&quot;&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;&lt;</span><span 
  style="color:maroon">a</span> <span style="color:red">sys</span><span 
  style="color:blue">:</span><span style="color:red">href</span><span 
  style="color:blue">=&quot;{{ &#39;../../Lists/User%20Stories/DispForm.aspx?ID=&#39; + ID 
 }}&quot;&gt;</span>{ binding Title }<span style="color:blue">&lt;/</span><span 
  style="color:maroon">a</span><span style="color:blue">&gt;&lt;/</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp; &nbsp;&nbsp;</span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">ul</span><span style="color:blue">&gt;</span><br />
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">table</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">thead</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">tr</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">td</span><span style="color:blue">&gt;</span>Title<span 
  style="color:blue">&lt;/</span><span style="color:maroon">td</span><span 
  style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">tr</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">thead</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">tbody</span> <span style="color:red">id</span><span 
  style="color:blue">=&quot;userStoriesTable&quot;</span> <span style="color:
red">class</span><span style="color:blue">=&quot;sys-template&quot;&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">tr</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">td</span><span style="color:blue">&gt;&lt;</span><span 
  style="color:maroon">input</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text&quot;</span> <span style="color:red">sys</span><span 
  style="color:blue">:</span><span style="color:red">value</span><span 
  style="color:blue">=&quot;{binding Title}&quot;</span> <span style="color:blue">/&gt;&lt;/</span><span 
  style="color:maroon">td</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">tr</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">tbody</span><span style="color:blue">&gt;</span><br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">table</span><span style="color:blue">&gt;</span><br />
 <span style="color:blue">&lt;/</span><span style="color:maroon">div</span><span 
  style="color:blue">&gt;</span></span></p>

<p>Notice the input element with the sys:value bound to title and the new binding syntax in the text of the a href.  The result looks like this:</p>

<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/S6bMoFgda1I/AAAAAAAABsk/LwN6UrGi--g/s1600-h/part3-1-endresult.gif"><img style="cursor:pointer; cursor:hand;width: 269px; height: 400px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/S6bMoFgda1I/AAAAAAAABsk/LwN6UrGi--g/s400/part3-1-endresult.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5451269388023720786" /></a></p>

<p>It may not be all that pretty yet, but if you change the text in any of the text boxes the result is immediately updated in the hyperlinks on mouse out.  But if you hop back to SharePoint or refresh the page you'll see that our data hasn't been updated.</p>
<p><b>Updating SharePoint, For Real This Time</b></p>
<p>Just because the DataView updated the in memory JSON objects it's bound to doesn't mean it sent a POST request back to ListData.svc.  To accomplish that we need to call dataContext.saveChanges().  If you toss in a button below the table like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">button</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> <span style="color:red">onclick</span><span style="color:blue">=&quot;dataContext.saveChanges()&quot;&gt;</span>Save 
 Changes<span style="color:blue">&lt;/</span><span style="color:maroon">button</span><span 
  style="color:blue">&gt;</span></span></p>

<p>And move the dataContext variable to a higher scope like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">var</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> dataContext;<br />
 <br />
 <span style="color:blue">function</span> onLoad() {<br />
 <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dataContext = 
 $create(Sys.Data.AdoNetDataContext, { serviceUri: <span style="color:maroon">
 &quot;/demoprep/_vti_bin/ListData.svc&quot;</span> });</span></p>

<p>Then when you click the button the AdoNetDataContext figures out which JSON objects changed and sends just those objects back to ListData.svc.  How do you know it only sends the rows that changed?  If you look at Fiddler there will be a POST to ListData.svc/$batch with something like the following:</p>

<p><span class="style1" 
  style="font-size: 11.0pt; line-height: 115%; font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi; mso-themecolor: background1; mso-style-textfill-fill-color: white; mso-style-textfill-fill-themecolor: background1; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-colortransforms: lumm=50000; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">
 --batch_d425-6668-6b05<br />
 Content-Type: multipart/mixed;boundary=changeset_8a05-bdcd-0b3e<br />
 --changeset_8a05-bdcd-0b3e<br />
 Content-Type: application/http<br />
 Content-Transfer-Encoding: binary<br />
 MERGE http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3) HTTP/1.1<br />
 If-Match: W/&quot;3&quot;<br />
 Host: localhost<br />
 Accept: application/json<br />
 Accept-Charset: utf-8<br />
 Content-Type: application/json;charset=utf-8</span><span style="font-size:11.0pt;line-height:115%;
font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;mso-ascii-theme-font:minor-latin;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:&quot;Times New Roman&quot;;mso-bidi-theme-font:minor-bidi;
color:white;mso-themecolor:background1;mso-style-textfill-fill-color:white;
mso-style-textfill-fill-themecolor:background1;mso-style-textfill-fill-alpha:
100.0%;mso-style-textfill-fill-colortransforms:lumm=50000;mso-ansi-language:
EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"><br />
 </span>
 <span style="font-size:9.5pt;line-height:115%;font-family:Consolas;
mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:
EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA">{<br />
 <span style="color:maroon">&quot;__metadata&quot;</span>:{<span style="color:maroon">&quot;uri&quot;</span>:<span 
  style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)&quot;</span>,<br />
 <span style="color:maroon">&quot;etag&quot;</span>:<span style="color:maroon">&quot;W/\&quot;3\&quot;&quot;</span>,<br />
 <span style="color:maroon">&quot;type&quot;</span>:<span style="color:maroon">&quot;Microsoft.SharePoint.DataService.UserStoriesItem&quot;</span>},<br />
 <span style="color:maroon">&quot;ContentTypeID&quot;</span>:<span style="color:maroon">&quot;0x01080070E2807D369BD94FBD6C057D3110E6D3&quot;</span>,<br />
 <span style="color:maroon">&quot;Title&quot;</span>:<span style="color:maroon">&quot;Renamed 
 Task&quot;</span>,<br />
 <span style="color:maroon">&quot;Predecessors&quot;</span>:{<span style="color:maroon">&quot;__deferred&quot;</span>:{<span 
  style="color:maroon">&quot;uri&quot;</span>:<span style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)/Predecessors&quot;</span>}},<br />
 <span style="color:maroon">&quot;Priority&quot;</span>:{<span style="color:
maroon">&quot;__deferred&quot;</span>:{<span style="color:maroon">&quot;uri&quot;</span>:<span 
  style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)/Priority&quot;</span>}},<br />
 <span style="color:maroon">&quot;PriorityValue&quot;</span>:<span style="color:maroon">&quot;(2) 
 Normal&quot;</span>,<br />
 <span style="color:maroon">&quot;Status&quot;</span>:{<span style="color:maroon">&quot;__deferred&quot;</span>:{<span 
  style="color:maroon">&quot;uri&quot;</span>:<span style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)/Status&quot;</span>}},<br />
 <span style="color:maroon">&quot;StatusValue&quot;</span>:<span style="color:maroon">&quot;Not 
 Started&quot;</span>,<br />
 <span style="color:maroon">&quot;Complete&quot;</span>:<span style="color:blue">null</span>,<br />
 <span style="color:maroon">&quot;AssignedToID&quot;</span>:<span style="color:blue">null</span>,<br />
 <span style="color:maroon">&quot;TaskGroupID&quot;</span>:<span style="color:blue">null</span>,<br />
 <span style="color:maroon">&quot;Description&quot;</span>:<span style="color:maroon">&quot;&lt;div&gt;&lt;/div&gt;&quot;</span>,<br />
 <span style="color:maroon">&quot;StartDate&quot;</span>:<span style="color:
maroon">&quot;\/Date(1266624000000)\/&quot;</span>,<br />
 <span style="color:maroon">&quot;DueDate&quot;</span>:<span style="color:blue">null</span>,<br />
 <span style="color:maroon">&quot;Points&quot;</span>:8,<br />
 <span style="color:maroon">&quot;Iteration&quot;</span>:{<span style="color:maroon">&quot;__deferred&quot;</span>:{<span 
  style="color:maroon">&quot;uri&quot;</span>:<span style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)/Iteration&quot;</span>}},<br />
 <span style="color:maroon">&quot;IterationID&quot;</span>:1,<br />
 <span style="color:maroon">&quot;ID&quot;</span>:3,<br />
 <span style="color:maroon">&quot;ContentType&quot;</span>:<span style="color:maroon">&quot;Task&quot;</span>,<br />
 <span style="color:maroon">&quot;Modified&quot;</span>:<span style="color:maroon">&quot;\/Date(1269128451000)\/&quot;</span>,<br />
 <span style="color:maroon">&quot;Created&quot;</span>:<span style="color:maroon">&quot;\/Date(1266679964000)\/&quot;</span>,<br />
 <span style="color:maroon">&quot;CreatedByID&quot;</span>:1,<br />
 <span style="color:maroon">&quot;ModifiedByID&quot;</span>:1,<br />
 <span style="color:maroon">&quot;Owshiddenversion&quot;</span>:3,<br />
 <span style="color:maroon">&quot;Version&quot;</span>:<span style="color:maroon">&quot;3.0&quot;</span>,<br />
 <span style="color:maroon">&quot;Attachments&quot;</span>:{<span style="color:maroon">&quot;__deferred&quot;</span>:{<span 
  style="color:maroon">&quot;uri&quot;</span>:<span style="color:maroon">&quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(3)/Attachments&quot;</span>}},<br />
 <span style="color:maroon">&quot;Path&quot;</span>:<span style="color:maroon">&quot;/demoprep/Lists/User 
 Stories&quot;</span><br />
 }<br />
 </span><span class="style1" 
  style="font-size: 11.0pt; line-height: 115%; font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi; mso-style-textfill-fill-color: #000000; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-colortransforms: &quot;lumm=60000 lumo=40000&quot;; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">
 --changeset_8a05-bdcd-0b3e--<br />
 --batch_d425-6668-6b05--</span></p>

<p>And that, as you may have noticed, is the JSON for just a single of the rows that we were displaying.</p>
<p>But how did the AdoNetDataContext know which objects were changed?  <a href=" http://lostintangent.com/2009/06/ ">Jonathan Carter</a> explains this better than I could but basically when the data context downloads JSON objects it injects them with the ability to notify itself when they change.  As Jonathan points out it's a neat trick that would not be possible in a statically typed language.</p>
<p><b>Summary</b></p>
<p>We've finally gotten to some of the core benefits of using ASP.Net AJAX 4 Templating.  With very little JavaScript we were able to cleanly separate our UI from our data access code and write data back to the server.  And the amount of HTTP traffic and server operations was kept to a bare minimum, keeping things as fast and responsive as possible.  So all we're missing at this point is how to use it to make something real out of these technologies.  And that will be the topic for the <a href="http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html">next post</a>.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ADO.Net Data Services</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint 2010</category>
            
            <pubDate>Sun, 21 Mar 2010 22:17:25 -0500</pubDate>
        </item>
        
        <item>
            <title>Client Side AJAX Applications in SharePoint 2010 - Part 2</title>
            <description><![CDATA[<p>Note: This is one of a multi-part series exploring building client side AJAX applications with ASP.Net AJAX 4 Templating and the WCF Data Services (aka ADO.Net Data Services, aka oData, aka Astoria) in SharePoint 2010.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/03/client-side-ajax-applications-in_21.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>


<p>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html">Part 1 - Exploring WCF Data Services in SharePoint 2010</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html">Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html">Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates</a>
</p>

<p>In <a href="http://rapidapplicationdevelopment.blogspot.com/2010/03/client-side-ajax-applications-in.html">Part 1</a> I described how SharePoint 2010 exposes list data through ListData.svc and WCF Data Services.  So far this is interesting, but the next logical question is how would you actually build a Web 2.0 application with the data?  One answer is with a new technology called ASP.Net AJAX 4.0 Client Side Templating.  I'll give you some background and then provide a walkthrough of how to build a SharePoint application page that reads and writes data to SharePoint through ListData.svc.</p>
<p><b>What is ASP.Net AJAX 4.0 Client Side Templating?</b></p>
<p>In Part 1 I talked about some of the problems with the two existing ways of writing Web 2.0 interfaces.  ASP.Net AJAX 4.0 Client Side Templating addresses most of these issues.  Specifically it:</p>

<ul>
<li>Minimizes plumbing code</li>
<li>Cleanly separates presentation from data access code</li>
<li>Simplifies saving data back to the server via Live Data Bindings</li>
<li>Has no ViewState!</li>
<li>Uses lightweight JSON rather than HTML</li>
</ul>

<p>Sounds good?  Ready to see some code?</p>
<p><b>Show Me The Code</b></p>
<p>Note: This walkthrough assumes you haven't played with Visual Studio 2010 and SharePoint 2010, so please skip ahead to "No Really, Show Me the AJAX Templating Code" if you've already seen the sweet SharePoint and Visual Studio integration.</p>
<p>To get started open Visual Studio 2010.  Select New Project and for the template navigate to SharePoint then 2010 select "Empty SharePoint Project" (p.s. see <a href=" http://httpcode.com/blogs/PermaLink,guid,357e4853-9a75-4962-ad68-1e07bcf40bb8.aspx">Visual Web Part</a> in the list?  Make sure you look that up if you haven't heard of it yet).</p>


<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/S6akfBI5uSI/AAAAAAAABr8/XZ97uHe4fIY/s1600-h/part2-1-vstemplates.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 306px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/S6akfBI5uSI/AAAAAAAABr8/XZ97uHe4fIY/s400/part2-1-vstemplates.gif" border="0" alt=""id="Img2" /></a>


<p>If you haven't been keeping up with what's new in SharePoint 2010 you should immediately notice that SharePoint integration is built into Visual Studio 2010 out of the box just based on the listed templates.  But just wait, it gets much better. </p>

<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/S6akfS6krBI/AAAAAAAABsE/0hTDT72N8Gc/s1600-h/part2-2-specifysite.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/S6akfS6krBI/AAAAAAAABsE/0hTDT72N8Gc/s400/part2-2-specifysite.gif" border="0" alt=""id="Img4" /></a>


<p>The next screen asks what site you want to use for debugging.  It's asking this because when you hit F5 ("Start Debugging") Visual Studio 2010 packages up your wsp file, deployes it to the URL you enter here, attaches to the w3wp process, and opens a browser into SharePoint, and you're immediately in debug mode!  </p>
<p>If you aren't deeply impressed then you haven't developed in WSS 3.0.  Now we aren't writing any server side code in this tutorial, but it's still extremely impressive how much work Microsoft has put into making SharePoint a first class citizen.</p>
<p>Once you have your site select Project -> Add New Item and select Application Page.</p>


<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_gez10dNhuPk/S6akfkNRsFI/AAAAAAAABsM/5kPkOSkDPRM/s1600-h/part2-3-addnewitem.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 323px;" src="http://4.bp.blogspot.com/_gez10dNhuPk/S6akfkNRsFI/AAAAAAAABsM/5kPkOSkDPRM/s400/part2-3-addnewitem.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5451225261180825682" /></a>

<p>Visual Studio then plops out a page that's 100% ready to go including the correct Content controls for the SharePoint master page.</p>

<p><span style="font-size: 9.5pt; line-height: 115%; font-family: Consolas; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; background: yellow; mso-highlight: yellow; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">
 &lt;%</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">@</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA"> <span style="color:maroon">Assembly</span>
 <span style="color:red">Name</span><span style="color:blue">=&quot;$SharePoint.Project.AssemblyFullName$&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Import</span>
 <span style="color:red">Namespace</span><span style="color:blue">=&quot;Microsoft.SharePoint.ApplicationPages&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Register</span>
 <span style="color:red">Tagprefix</span><span style="color:blue">=&quot;SharePoint&quot;</span>
 <span style="color:red">Namespace</span><span style="color:blue">=&quot;Microsoft.SharePoint.WebControls&quot;</span>
 <span style="color:red">Assembly</span><span style="color:blue">=&quot;Microsoft.SharePoint, 
 Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Register</span>
 <span style="color:red">Tagprefix</span><span style="color:blue">=&quot;Utilities&quot;</span>
 <span style="color:red">Namespace</span><span style="color:blue">=&quot;Microsoft.SharePoint.Utilities&quot;</span>
 <span style="color:red">Assembly</span><span style="color:blue">=&quot;Microsoft.SharePoint, 
 Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Register</span>
 <span style="color:red">Tagprefix</span><span style="color:blue">=&quot;asp&quot;</span>
 <span style="color:red">Namespace</span><span style="color:blue">=&quot;System.Web.UI&quot;</span>
 <span style="color:red">Assembly</span><span style="color:blue">=&quot;System.Web.Extensions, 
 Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Import</span>
 <span style="color:red">Namespace</span><span style="color:blue">=&quot;Microsoft.SharePoint&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Assembly</span>
 <span style="color:red">Name</span><span style="color:blue">=&quot;Microsoft.Web.CommandUI, 
 Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <span style="background: yellow; mso-highlight: yellow">&lt;%</span><span 
  style="color:blue">@</span> <span style="color:maroon">Page</span>
 <span style="color:red">Language</span><span style="color:blue">=&quot;C#&quot;</span>
 <span style="color:red">AutoEventWireup</span><span style="color:blue">=&quot;true&quot;</span>
 <span style="color:red">CodeBehind</span><span style="color:blue">=&quot;ApplicationPage1.aspx.cs&quot;</span>
 <span style="color:red">Inherits</span><span style="color:blue">=&quot;MyAppPage.Layouts.MyAppPage.ApplicationPage1&quot;</span>
 <span style="color:red">DynamicMasterPageFile</span><span style="color:blue">=&quot;~masterurl/default.master&quot;</span>
 <span style="background: yellow; mso-highlight: yellow">%&gt;</span><br />
 <br />
 <span style="color:blue">&lt;</span><span style="color:maroon">asp</span><span 
  style="color:blue">:</span><span style="color:maroon">Content</span>
 <span style="color:red">ID</span><span style="color:blue">=&quot;PageHead&quot;</span>
 <span style="color:red">ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderAdditionalPageHead&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
 <br />
 &lt;/</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span><span style="color:blue">&gt;<br />
 <br />
 &lt;</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span> <span style="color:red">ID</span><span 
  style="color:blue">=&quot;Main&quot;</span> <span style="color:red">
 ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderMain&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
 </span>Hello World!<br />
 <span style="color:blue">&lt;/</span><span style="color:maroon">asp</span><span 
  style="color:blue">:</span><span style="color:maroon">Content</span><span 
  style="color:blue">&gt;<br />
 <br />
 &lt;</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span> <span style="color:red">ID</span><span 
  style="color:blue">=&quot;PageTitle&quot;</span> <span style="color:red">
 ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderPageTitle&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
 </span>Application Page<br />
 <span style="color:blue">&lt;/</span><span style="color:maroon">asp</span><span 
  style="color:blue">:</span><span style="color:maroon">Content</span><span 
  style="color:blue">&gt;<br />
 <br />
 &lt;</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span> <span style="color:red">ID</span><span 
  style="color:blue">=&quot;PageTitleInTitleArea&quot;</span> <span style="color:red">
 ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderPageTitleInTitleArea&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;</span>
 <span style="color:blue">&gt;<br />
 </span>My Application Page<br />
 <span style="color:blue">&lt;/</span><span style="color:maroon">asp</span><span 
  style="color:blue">:</span><span style="color:maroon">Content</span><span 
  style="color:blue">&gt;</span></span></p>

<p>(ok, the "Hello World!" is mine).  Now if you hit F5 or click Build -> "Deploy Solution" then as I mentioned SharePoint packages up the application page into a wsp file and deployes it out to SharePoint.  Now if you navigate to your application page (in my case http://localhost/mysite/_layouts/MyAppPage/ApplicationPage1.aspx) then you should see something like this:</p>

<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_gez10dNhuPk/S6akgCoo_CI/AAAAAAAABsU/ccLTEAhinWQ/s1600-h/part2-4-helloworld.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 286px;" src="http://1.bp.blogspot.com/_gez10dNhuPk/S6akgCoo_CI/AAAAAAAABsU/ccLTEAhinWQ/s400/part2-4-helloworld.gif" border="0" alt=""id="Img3" /></a>

<p>Amazed?  You should be.  We didn't write a line of evil looking CAML, didn't have to write any DOS batch files, didn't have to deploy to the GAC, we probably didn't even notice that a feature.xml file was created behind the scenes.  Yet already we're deployed!  Ok, enough exuberance, back to business.</p>

<p><b>No Really, Show Me the AJAX Templating Code</b></p>
<p>Before writing code you should probably create some lists to read and write to.  As I mentioned in a previous post I like <a href=" http://rapidapplicationdevelopment.blogspot.com/2010/02/video-how-to-create-burndown-charts-for.html ">tracking user stories in SharePoint</a>.  So for my examples I have an Iterations list and a User Stories list, which is based off of the Tasks content type (automatically giving you a number of columns like Priority).</p>
<p>After creating some lists you need to ensure you have the latest <a href=" http://ajax.codeplex.com/releases/view/35895 ">ASP.Net Ajax Library</a>.  I suspect an updated copy will be included with the RTM copy of SharePoint 2010, but in my case I downloaded the latest copy and moved the entire Scripts directory into C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ajax.  Note that out of the box SharePoint 2010 already included some of these files in LAYOUTS, but it was missing others, so this step was necessary.</p>
<p>So here is the absolute simplest templating example that still works:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">asp</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">:</span><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:maroon;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">Content</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA"> <span style="color:red">ID</span><span style="color:blue">=&quot;PageHead&quot;</span>
 <span style="color:red">ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderAdditionalPageHead&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">script</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text/javascript&quot;</span> <span style="color:red">src</span><span 
  style="color:blue">=&quot;../ajax/MicrosoftAjax.js&quot;&gt;&lt;/</span><span 
  style="color:maroon">script</span><span style="color:blue">&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">script</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text/javascript&quot;</span> <span style="color:red">src</span><span 
  style="color:blue">=&quot;../ajax/MicrosoftAjaxDataContext.js&quot;&gt;&lt;/</span><span 
  style="color:maroon">script</span><span style="color:blue">&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">script</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text/javascript&quot;</span> <span style="color:red">src</span><span 
  style="color:blue">=&quot;../ajax/MicrosoftAjaxTemplates.js&quot;&gt;&lt;/</span><span 
  style="color:maroon">script</span><span style="color:blue">&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">script</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text/javascript&quot;</span> <span style="color:red">src</span><span 
  style="color:blue">=&quot;../ajax/MicrosoftAjaxAdoNet.js&quot;&gt;&lt;/</span><span 
  style="color:maroon">script</span><span style="color:blue">&gt;<br />
 &lt;/</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span><span style="color:blue">&gt;<br />
 <br />
 &lt;</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span> <span style="color:red">ID</span><span 
  style="color:blue">=&quot;Main&quot;</span> <span style="color:red">
 ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderMain&quot;</span>
 <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">script</span> <span style="color:red">type</span><span 
  style="color:blue">=&quot;text/javascript&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">
 function</span> pageInit() {<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">var</span> 
 dataContext = $create(Sys.Data.AdoNetDataContext, {
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>serviceUri:
 <span style="color:maroon">&quot;/demoprep/_vti_bin/ListData.svc&quot;</span>
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>});<br />
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>$create(Sys.UI.DataView,
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>autoFetch:
 <span style="color:blue">true</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dataProvider: 
 dataContext,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>fetchOperation:
 <span style="color:maroon">&quot;UserStories&quot;</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>fetchParameters: { 
 $top: 20 }<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>},<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:blue">null</span>,<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>$get(<span 
  style="color:maroon">&quot;userStoriesList&quot;</span>)<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>);<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
 Sys.Application.add_init(pageInit);<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">script</span><span style="color:blue">&gt;<br />
 </span>
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">ul</span> <span style="color:red">id</span><span 
  style="color:blue">=&quot;userStoriesList&quot;</span> <span style="color:red">class</span><span 
  style="color:blue">=&quot;sys-template&quot;&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;</span><span 
  style="color:maroon">li</span><span style="color:blue">&gt;</span>{{ Title }}<span 
  style="color:blue">&lt;/</span><span style="color:maroon">li</span><span 
  style="color:blue">&gt;<br />
 </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">&lt;/</span><span 
  style="color:maroon">ul</span><span style="color:blue">&gt;<br />
 &lt;/</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
  style="color:maroon">Content</span><span style="color:blue">&gt;</span></span></p>

<p>The four script references in the PageHead Content control are necessary to define the required ASP.Net AJAX JavaScript classes you'll need for templating.  But the Main content control is where things get interesting.</p>
<p>Skip over the JavaScript for now and notice the unordered list named userStoriesList.  Inside of the li elements is a strange notation: {{ Title }}.  This specifies a binding to the name of a SharePoint field.  You could also have put in PriorityValue or any of the other columns specified in the JSON that I showed in Part 1.</p>
<p>As far as the JavaScript, the dataContext variable is a class of type AdoNetDataContext, which knows how to talk to WCF Data Services like ListData.svc.  It inherits from a JavaScript class called DataContext which is extensible and knows how to talk with other protocols, but us SharePoint developers probably won't care about this most of the time.</p>
<p>The userStoriesTemplate variable is a class of type DataView.  This is where the magic happens.  DataViews pull data from a DataContext, duplicates the innerHtml of an associated DOM element for each row returned (e.g. userStoriesList), and replace the binding syntax with real data.  Seems simple enough, but it is actually quite sophisticated when you get to some more advanced scenarios that I'll describe later.</p>
<p>One last thing to notice is the sys-template class.  This is a prespecified CSS class that ASP.Net AJAX sets to display: block when it is finished rendering.  It's a good idea to create a CSS class for sys-template with display: none so that end users don't see your template code while the page is loading.  Obviously you should do this in a separate CSS class in LAYOUTS or if you're lazy you can put it in the PageHead content control like so:</p>

 <p class="MsoNormal">
  <span style="font-size:
9.5pt;font-family:Consolas;color:blue">&lt;</span><span style="font-size:9.5pt;
font-family:Consolas;color:maroon">STYLE</span><span style="font-size:9.5pt;
font-family:Consolas"> <span style="color:red">type</span><span style="color:blue">=&quot;text/css&quot;&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:maroon">.sys-template</span> { <span style="color:red">
  display</span>: <span style="color:blue">block</span>; }<br />
  <span style="color:blue">&lt;/</span><span style="color:maroon">STYLE</span><span 
   style="color:blue">&gt;<br />
  <br />
  &lt;</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
   style="color:maroon">Content</span> <span style="color:red">ID</span><span 
   style="color:blue">=&quot;PageHead&quot;</span> <span style="color:red">
  ContentPlaceHolderID</span><span style="color:blue">=&quot;PlaceHolderAdditionalPageHead&quot;</span>
  <span style="color:red">runat</span><span style="color:blue">=&quot;server&quot;&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>
  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>
  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjax.js&quot;&gt;&lt;/</span><span 
   style="color:maroon">script</span><span style="color:blue">&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>
  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>
  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxDataContext.js&quot;&gt;&lt;/</span><span 
   style="color:maroon">script</span><span style="color:blue">&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>
  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>
  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxTemplates.js&quot;&gt;&lt;/</span><span 
   style="color:maroon">script</span><span style="color:blue">&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;</span><span style="color:maroon">script</span>
  <span style="color:red">type</span><span style="color:blue">=&quot;text/javascript&quot;</span>
  <span style="color:red">src</span><span style="color:blue">=&quot;../ajax/MicrosoftAjaxAdoNet.js&quot;&gt;&lt;/</span><span 
   style="color:maroon">script</span><span style="color:blue">&gt;<br />
  </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;</span><span style="color:maroon">STYLE</span>
  <span style="color:red">type</span><span style="color:blue">=&quot;text/css&quot;&gt;<br />
  </span><span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  </span><span style="color:maroon">.sys-template</span> { <span style="color:red">
  display</span>: <span style="color:blue">block</span>; }<br />
  <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  <span style="color:blue">&lt;/</span><span style="color:maroon">STYLE</span><span 
   style="color:blue">&gt;<br />
  &lt;/</span><span style="color:maroon">asp</span><span style="color:blue">:</span><span 
   style="color:maroon">Content</span><span style="color:blue">&gt;<br 
   style="mso-special-character:line-break" />
  <![if !supportLineBreakNewLine]>
  <br style="mso-special-character:line-break" />
  <![endif]></span><o:p></o:p></span>
 </p>

<p>So now if you click If you click Build -> Deploy Solution you should see something like this:</p>

<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/S6akgdn0DlI/AAAAAAAABsc/ePFlii5mG9o/s1600-h/part2-5-endresult.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 292px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/S6akgdn0DlI/AAAAAAAABsc/ePFlii5mG9o/s400/part2-5-endresult.gif" border="0" alt=""id="Img1" /></a>

<p><b>Summary</b></p>
<p>Ok, this isn't super exciting yet.  We certainly could have done this much easier with server side code.  But bear with me, this has a lot of potential.  For instance, how do you write data back to the server?  How do you really make it AJAXy?  I'll explore these questions in <a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html">Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates</a> and subsequent posts in the series.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ADO.Net Data Services</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">Astoria</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint 2010</category>
            
            <pubDate>Sun, 21 Mar 2010 20:36:54 -0500</pubDate>
        </item>
        
        <item>
            <title>Client Side AJAX Applications in SharePoint 2010 - Part 1</title>
            <description><![CDATA[<p>If you haven't played with it yet, one of the things you'll immediately notice about SharePoint 2010 is that the UI is extremely AJAX centric.  For instance modifying or adding list items is either done in-line with partial page refreshes or via lightbox popups.  It's very pleasant to use.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/03/client-side-ajax-applications-in.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>


<p>One of the consequences of this Web 2.0 design is that the expectations of SharePoint end users will significantly increase.  No longer will long delays and/or full page refreshes in your SharePoint based custom applications be acceptable.  End users may not be able to clearly articulate it, but unless as developers we update our techniques to match the new technology our SharePoint based applications will begin to feel stale and will stick out from the rest of SharePoint 2010.</p>
<p>Fortunately Microsoft has stepped up the support it offers Web 2.0 developers in a big way.  One of the most compelling features is in how SharePoint exposes all list data via REST/ATOM <i>and</i> JSON.  This feature combined with the new templating feature of ASP.Net AJAX 4 allows developers to easily write fast, responsive user interfaces.  I will explore these two technologies in the following series:</p>

<p>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html">Part 1 - Exploring WCF Data Services in SharePoint 2010</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html">Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates</a><br />
<a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_2.html">Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates</a><br/>
<a href="http://www.nearinfinity.com/blogs/lee_richardson/aspajax_4_templates_part_4_-_j.html">Part 4 - jQuery and Manual JSON Object Manipulation</a>
</p>

<p><b>Why do we need yet another framework?</b></p>
<p>If you attempt to develop Web 2.0 applications in SharePoint with the techniques you have today there are really only two approaches: ASP.Net AJAX and server side controls or manually coding JavaScript, probably with jQuery or other JavaScript Libraries.  If you take the ASP.Net AJAX approach you'll undoubtedly be using an UpdatePanel to get partial page refreshes and then writing ASP.Net code like you always have.  There are several problems with this approach:</p>

<ul>
<li>It sends the entire ViewState with every asynchronous request - this can result in slow, unresponsive apps (this can actually sneak up on you once you have a lot of production data as happened to me recently)</li>
<li>Even without a ViewState the UpdatePanel transmits large amounts of HTML (rather than lightweight JSON data)</li>
<li>It runs through the entire page lifecycle on updates, executing everything on the page even if it isn't relevant to what you're doing</li>
<li>ASP.Net AJAX doesn't have the simplicity of an ETag based HTTP caching like with a REST solution</li>
<li>Finally SharePoint just doesn't work well with UpdatePanel, I can't tell you how many issues I've had with various controls not working out of the box</li>
</ul>

<p>And if you take the manual JavaScript rout you are faced with a number of different problems:</p>

<ul>
<li>You have to write <i>a lot</i> of plumbing code</li>
 <ul>
  <li>You have to write a service to return your data</li>
  <li>You have to pay particular attention to security and permissions since you're exposing your API's to the world</li>
  <li>You have to convert your data (ideally JSON) into HTML with probably string concatenation or document.createElement statements</li>
 </ul>
<li>Your UI code is not clearly separated from your data access code making your code hard to maintain</li>
<li>Saving data back to the server involves even more plumbing code</li>
</ul>

<p>SharePoint 2010 combined with ASP.Net AJAX 4.0 solves these problems.  It probably introduces new problems too, but I haven't run into too many thus far.  So over the next couple of posts I hope to convince you that we do need yet another web framework and that Microsoft is headed in a great direction with these technologies.</p>
<p><b>So How Does it Work?</b></p>
<p>In WSS 3.0 you were able to access list data with the SOAP based Lists.asmx.  This technique worked well for .Net desktop apps or server side application pages, but not so well with client side JavaScript.  SharePoint 2010 exposes its list data with REST based ListData.svc (though WCF Data Services which I'll describe in more detail below).  Once you install <a href=" http://ajax.codeplex.com/releases/view/35895 ">WCF Data Services</a> on a machine with SharePoint 2010 you can simply navigate to http://[server]/[optional site]/_vti_bin/ListData.svc and see all of the lists you have permission to access.  The result will look like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;?</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">xml</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA"> </span>
 <span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:red;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">version</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">=</span><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA">&quot;<span style="color:blue">1.0</span>&quot;<span style="color:blue"> </span>
 <span style="color:red">encoding</span><span style="color:blue">=</span>&quot;<span 
  style="color:blue">iso-8859-1</span>&quot;<span style="color:blue"> </span>
 <span style="color:red">standalone</span><span style="color:blue">=</span>&quot;<span 
  style="color:blue">yes</span>&quot;<span style="color:blue">?&gt;<br />
 &lt;</span><span style="color:#A31515">service</span><span style="color:blue">
 </span><span style="color:red">xml:base</span><span style="color:blue">=</span>&quot;<span 
  style="color:blue">http://localhost/mySite/_vti_bin/ListData.svc/</span>&quot;<span 
  style="color:blue">
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span><span style="color:red">
 xmlns:atom</span><span style="color:blue">=</span>&quot;<span style="color:blue">http://www.w3.org/2005/Atom</span>&quot;<span 
  style="color:blue">
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span><span style="color:red">
 xmlns:app</span><span style="color:blue">=</span>&quot;<span style="color:blue">http://www.w3.org/2007/app</span>&quot;<span 
  style="color:blue">
 <br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span><span style="color:red">xmlns</span><span 
  style="color:blue">=</span>&quot;<span style="color:blue">http://www.w3.org/2007/app</span>&quot;<span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="color:#A31515">workspace</span><span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">atom:title</span><span 
  style="color:blue">&gt;</span>Default<span style="color:blue">&lt;/</span><span 
  style="color:#A31515">atom:title</span><span style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">collection</span><span 
  style="color:blue"> </span><span style="color:red">href</span><span 
  style="color:blue">=</span>&quot;<span style="color:blue">Iterations</span>&quot;<span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">atom:title</span><span 
  style="color:blue">&gt;</span>Iterations<span style="color:blue">&lt;/</span><span 
  style="color:#A31515">atom:title</span><span style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:#A31515">collection</span><span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">collection</span><span 
  style="color:blue"> </span><span style="color:red">href</span><span 
  style="color:blue">=</span>&quot;<span style="color:blue">UserStories</span>&quot;<span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">atom:title</span><span 
  style="color:blue">&gt;</span>UserStories<span style="color:blue">&lt;/</span><span 
  style="color:#A31515">atom:title</span><span style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:#A31515">collection</span><span 
  style="color:blue">&gt;<br />
 <span style="mso-spacerun:yes">&nbsp; </span>&lt;/</span><span style="color:#A31515">workspace</span><span 
  style="color:blue">&gt;<br />
 &lt;/</span><span style="color:#A31515">service</span><span style="color:blue">&gt;</span></span></p>

<p>You can then append the names of lists (e.g. http://localhost/site/_vti_bin/ListData.svc/UserStories) and immediately view the list items in the list as an ATOM feed.  A typical result looks like this:</p>

 <p class="MsoNormal">
  <span style="font-size:
9.5pt;font-family:Consolas;color:blue">&lt;?</span><span style="font-size:9.5pt;
font-family:Consolas;color:#A31515">xml</span><span style="font-size:9.5pt;
font-family:Consolas;color:blue"> </span>
  <span style="font-size:9.5pt;
font-family:Consolas;color:red">version</span><span style="font-size:9.5pt;
font-family:Consolas;color:blue">=</span><span style="font-size:9.5pt;
font-family:Consolas">&quot;<span style="color:blue">1.0</span>&quot;<span style="color:blue">
  </span><span style="color:red">encoding</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">iso-8859-1</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">standalone</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">yes</span>&quot;<span style="color:blue">?&gt;<br />
  &lt;</span><span style="color:#A31515">feed</span><span style="color:blue"> </span>
  <span style="color:red">xml:base</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://localhost/mySite/_vti_bin/ListData.svc/</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span>
  <span style="color:red">xmlns:d</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span>
  <span style="color:red">xmlns:m</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/metadata</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span>
  <span style="color:red">xmlns</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://www.w3.org/2005/Atom</span>&quot;<span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span 
   style="color:#A31515">title</span><span style="color:blue"> </span>
  <span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">text</span>&quot;<span style="color:blue">&gt;</span>UserStories<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">title</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span 
   style="color:#A31515">id</span><span style="color:blue">&gt;</span>http://localhost/mySite/_vti_bin/ListData.svc/UserStories<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">id</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span 
   style="color:#A31515">updated</span><span style="color:blue">&gt;</span>2010-03-20T02:20:26Z<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">updated</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">self</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories</span>&quot;<span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span 
   style="color:#A31515">entry</span><span style="color:blue"> </span>
  <span style="color:red">m:etag</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">W/</span><span style="color:red">&amp;quot;</span><span 
   style="color:blue">3</span><span style="color:red">&amp;quot;</span>&quot;<span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">id</span><span style="color:blue">&gt;</span>http://localhost/mySite/_vti_bin/ListData.svc/UserStories(2)<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">id</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">title</span><span style="color:blue"> </span>
  <span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">text</span>&quot;<span style="color:blue">&gt;</span>Blah<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">title</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">updated</span><span style="color:blue">&gt;</span>2010-03-19T15:13:28-05:00<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">updated</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">author</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">name</span><span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span 
   style="color:#A31515">author</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">edit</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStoriesItem</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)</span>&quot;<span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/related/Predecessors</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/atom+xml;type=feed</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Predecessors</span>&quot;<span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)/Predecessors</span>&quot;<span 
   style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/related/Priority</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/atom+xml;type=entry</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Priority</span>&quot;<span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)/Priority</span>&quot;<span style="color:blue"> 
  /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/related/Status</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/atom+xml;type=entry</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Status</span>&quot;<span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)/Status</span>&quot;<span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/related/Iteration</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/atom+xml;type=entry</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Iteration</span>&quot;<span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)/Iteration</span>&quot;<span style="color:blue"> 
  /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">link</span><span style="color:blue"> </span>
  <span style="color:red">rel</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/atom+xml;type=feed</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">title</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Attachments</span>&quot;<span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">href</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">UserStories(2)/Attachments</span>&quot;<span 
   style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">category</span><span style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">term</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Microsoft.SharePoint.DataService.UserStoriesItem</span>&quot;<span 
   style="color:blue">
  <br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  </span><span style="color:red">scheme</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">http://schemas.microsoft.com/ado/2007/08/dataservices/scheme</span>&quot;<span 
   style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">content</span><span style="color:blue"> </span>
  <span style="color:red">type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">application/xml</span>&quot;<span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span 
   style="color:#A31515">m:properties</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:ContentTypeID</span><span 
   style="color:blue">&gt;</span>0x01080070E2807D369BD94FBD6C057D3110E6D3<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:ContentTypeID</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Title</span><span style="color:blue">&gt;</span>Do 
  Something<span style="color:blue">&lt;/</span><span style="color:#A31515">d:Title</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:PriorityValue</span><span 
   style="color:blue">&gt;</span>(2) Normal<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:PriorityValue</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:StatusValue</span><span 
   style="color:blue">&gt;</span>Not Started<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:StatusValue</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Complete</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.Double</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">m:null</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">true</span>&quot;<span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:AssignedToID</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue"> </span><span style="color:red">m:null</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">true</span>&quot;<span 
   style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:TaskGroupID</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue"> </span><span style="color:red">m:null</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">true</span>&quot;<span 
   style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Description</span><span 
   style="color:blue">&gt;</span><span style="color:red">&amp;lt;</span>div<span 
   style="color:red">&amp;gt;&amp;lt;</span>/div<span style="color:red">&amp;gt;</span><span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:Description</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:StartDate</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.DateTime</span>&quot;<span style="color:blue">&gt;</span>2010-02-20T00:00:00<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:StartDate</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:DueDate</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.DateTime</span>&quot;<span style="color:blue"> </span>
  <span style="color:red">m:null</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">true</span>&quot;<span style="color:blue"> /&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Points</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.Double</span>&quot;<span style="color:blue">&gt;</span>3<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:Points</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:IterationID</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue">&gt;</span>3<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:IterationID</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:ID</span><span style="color:blue"> </span>
  <span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.Int32</span>&quot;<span style="color:blue">&gt;</span>2<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:ID</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:ContentType</span><span 
   style="color:blue">&gt;</span>Task<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:ContentType</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Modified</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.DateTime</span>&quot;<span style="color:blue">&gt;</span>2010-03-19T15:13:28<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:Modified</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Created</span><span style="color:blue">
  </span><span style="color:red">m:type</span><span style="color:blue">=</span>&quot;<span 
   style="color:blue">Edm.DateTime</span>&quot;<span style="color:blue">&gt;</span>2010-02-20T15:32:26<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:Created</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:CreatedByID</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue">&gt;</span>1<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:CreatedByID</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:ModifiedByID</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue">&gt;</span>1<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:ModifiedByID</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Owshiddenversion</span><span 
   style="color:blue"> </span><span style="color:red">m:type</span><span 
   style="color:blue">=</span>&quot;<span style="color:blue">Edm.Int32</span>&quot;<span 
   style="color:blue">&gt;</span>3<span style="color:blue">&lt;/</span><span 
   style="color:#A31515">d:Owshiddenversion</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Version</span><span style="color:blue">&gt;</span>3.0<span 
   style="color:blue">&lt;/</span><span style="color:#A31515">d:Version</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
  &lt;</span><span style="color:#A31515">d:Path</span><span style="color:blue">&gt;</span>/mySite/Lists/User 
  Stories<span style="color:blue">&lt;/</span><span style="color:#A31515">d:Path</span><span 
   style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:
#A31515">m:properties</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span 
   style="color:#A31515">content</span><span style="color:blue">&gt;<br />
  <span style="mso-spacerun:yes">&nbsp; </span>&lt;/</span><span 
   style="color:#A31515">entry</span><span style="color:blue">&gt;<br />
  &lt;/</span><span style="color:#A31515">feed</span><span style="color:blue">&gt;<br 
   style="mso-special-character:line-break" />
  <![if !supportLineBreakNewLine]>
  <br style="mso-special-character:line-break" />
  <![endif]></span><o:p></o:p></span>
 </p>

<p>You can append various parameters to filter, sort, or paginate your data from this page.  For example http://localhost/site/_vti_bin/ListData.svc/UserStories?$filter=(PriorityValue eq '(2) Normal')&$orderby=Title will return list items whose priority is normal sorted by title.  See <a href="http://msdn.microsoft.com/en-us/magazine/cc668784.aspx ">Query Expressions</a> on MSDN for more details.</p>

<p>Now if you're interested you can take it a step further by viewing the data as JSON.  To do this you'll need to modify the HTTP headers.  Fortunately there is a tool from Microsoft for viewing, replaying, and modify HTTP sessions called <a href="http://www.fiddler2.com/fiddler2/ ">Fiddler</a>.  After you install it open Fiddler from the add-in in your web browser (I used IE, but Firefox should work too).  Then refresh the web page for a list (in my case ListData.svc/UserStories).  Now in Fiddler drag the last request to the Request Builder, ensure "Automatically Authenticate" is checked in options, and replace "Accept: */*" with "Accept application/json". When you click Execute you should see something like:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA">{<br />
 <span style="color:maroon">&quot;d&quot;</span> : {<br />
 <span style="color:maroon">&quot;results&quot;</span>: [<br />
 {<br />
 <span style="color:maroon">&quot;__metadata&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)&quot;</span>,
 <br />
 <span style="color:maroon">&quot;etag&quot;</span>: <span style="color:maroon">&quot;W/\&quot;3\&quot;&quot;</span>,
 <br />
 <span style="color:maroon">&quot;type&quot;</span>: <span style="color:maroon">
 &quot;Microsoft.SharePoint.DataService.UserStoriesItem&quot;<br />
 </span>}, <span style="color:maroon">&quot;ContentTypeID&quot;</span>:
 <span style="color:maroon">&quot;0x01080070E2807D369BD94FBD6C057D3110E6D3&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Title&quot;</span>: <span style="color:maroon">&quot;Blah&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Predecessors&quot;</span>: {<br />
 <span style="color:maroon">&quot;__deferred&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)/Predecessors&quot;<br />
 </span>}<br />
 }, <span style="color:maroon">&quot;Priority&quot;</span>: {<br />
 <span style="color:maroon">&quot;__deferred&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)/Priority&quot;<br />
 </span>}<br />
 }, <span style="color:maroon">&quot;PriorityValue&quot;</span>: <span style="color:maroon">
 &quot;(2) Normal&quot;</span>, <span style="color:maroon">&quot;Status&quot;</span>: {<br />
 <span style="color:maroon">&quot;__deferred&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)/Status&quot;<br />
 </span>}<br />
 }, <span style="color:maroon">&quot;StatusValue&quot;</span>: <span style="color:maroon">
 &quot;Not Started&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Complete&quot;</span>: <span style="color:
blue">null</span>,
 <br />
 <span style="color:maroon">&quot;AssignedToID&quot;</span>: <span style="color:blue">null</span>,
 <br />
 <span style="color:maroon">&quot;TaskGroupID&quot;</span>: <span style="color:blue">null</span>,
 <br />
 <span style="color:maroon">&quot;Description&quot;</span>: <span style="color:maroon">
 &quot;&lt;div&gt;&lt;/div&gt;&quot;</span>,
 <br />
 <span style="color:maroon">&quot;StartDate&quot;</span>: <span style="color:maroon">
 &quot;\/Date(1266624000000)\/&quot;</span>,
 <br />
 <span style="color:maroon">&quot;DueDate&quot;</span>: <span style="color:blue">null</span>,
 <br />
 <span style="color:maroon">&quot;Points&quot;</span>: 3,
 <br />
 <span style="color:maroon">&quot;Iteration&quot;</span>: {<br />
 <span style="color:maroon">&quot;__deferred&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)/Iteration&quot;<br />
 </span>}<br />
 }, <span style="color:maroon">&quot;IterationID&quot;</span>: 3,
 <br />
 <span style="color:maroon">&quot;ID&quot;</span>: 2,
 <br />
 <span style="color:maroon">&quot;ContentType&quot;</span>: <span style="color:maroon">
 &quot;Task&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Modified&quot;</span>: <span style="color:
maroon">&quot;\/Date(1269011608000)\/&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Created&quot;</span>: <span style="color:maroon">
 &quot;\/Date(1266679946000)\/&quot;</span>,
 <br />
 <span style="color:maroon">&quot;CreatedByID&quot;</span>: 1,
 <br />
 <span style="color:maroon">&quot;ModifiedByID&quot;</span>: 1,
 <br />
 <span style="color:maroon">&quot;Owshiddenversion&quot;</span>: 3,
 <br />
 <span style="color:maroon">&quot;Version&quot;</span>: <span style="color:maroon">&quot;3.0&quot;</span>,
 <br />
 <span style="color:maroon">&quot;Attachments&quot;</span>: {<br />
 <span style="color:maroon">&quot;__deferred&quot;</span>: {<br />
 <span style="color:maroon">&quot;uri&quot;</span>: <span style="color:maroon">
 &quot;http://localhost/demoprep/_vti_bin/ListData.svc/UserStories(2)/Attachments&quot;<br />
 </span>}<br />
 }, <span style="color:maroon">&quot;Path&quot;</span>: <span style="color:maroon">
 &quot;/demoprep/Lists/User Stories&quot;<br />
 </span>}<br />
 ]<br />
 }<br />
 }<br style="mso-special-character:line-break" />
 <![if !supportLineBreakNewLine]>
 <br style="mso-special-character:line-break" />
 <![endif]></span></p>

<p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/S6YnvZgs-4I/AAAAAAAABr0/lFSbUWxfsAc/s1600-h/Fiddler.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 191px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/S6YnvZgs-4I/AAAAAAAABr0/lFSbUWxfsAc/s400/Fiddler.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5451088094233951106" /></a>
</p>

<p>That's SharePoint data as JavaScript Object Notation.  Notice the etag and href's to associated list data.  Cool.</p>

<p>But ListData.svc isn't just for reading data.  To experiment with it try deleting a list item.  To do this in fiddler set the HTTP verb to "DELETE", set the URL to a particular list item's URL (e.g. http://localhost/site/_vti_bin/ListData.svc/UserStories(2) where 2 is the ID for a list item), leave Request Headers empty, and hit Execute.  Refresh the list of items and yours is gone.  Permanently.  The item isn't even in the recycle bin.</p>
<p><b>Security in WCF Data Services</b></p>
<p>So at this point you are undoubtedly concerned about security.  Just to give some background ListData.svc is provided by a technology called <a href="http://en.wikipedia.org/wiki/ADO.NET_Data_Services">WCF Data Services</a>, which was formerly called ADO.Net Data Services, which was code named Astoria.  And WCF Data Services is an implementation of the open data protocol (OData) which <a href=" http://www.hanselminutes.com/default.aspx?showID=223 ">Scott Hanselman</a> has an excellent podcast about.</p>
<p>This technology was originally designed for exposing database data.  And in this scenario you do have to handle your own security.  SharePoint 2010, however, takes things a step further by giving you WCF Data Services (nearly) out of the box while also handling your authorization security.</p>
<p>For instance if you modify the row level permissions for a list item to deny read permissions to a user then ListData.svc will not return that list item for that user.  If you try to access the URL for that list item directly SharePoint returns a 404.  If you try to modify or delete a list item you don't have permissions to modify then SharePoint returns a 401 Unauthorized.</p>
<p>Very cool.  I find this especially nice because you don't have to worry about maintaining your security code.  It's intimately tied to SharePoint 2010's security model which is already quite sophisticated.</p>
<p>Incidentally, security is not all that's included when you use these services.  SharePoint also performs data validation and returns the appropriate HTTP error codes if you for instance violate the new uniqueness constraint.</p>
<p><b>Summary</b></p>
<p>SharePoint offers everything you've seen so far (nearly) out of the box and without a line of code.  This sets the stage for writing some nice client side applications with technologies like ASP.Net AJAX 4.0 client site templating.  Which is exactly what I intend to do in <a href="http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications_1.html">Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates</a>.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/client_side_ajax_applications.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ADO.Net Data Services</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">AJAX</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint 2010</category>
            
            <pubDate>Sun, 21 Mar 2010 18:37:06 -0500</pubDate>
        </item>
        
        <item>
            <title>[video] How To Create Burndown Charts For User Stories in SharePoint</title>
            <description><![CDATA[ <p>I love tracking user stories in SharePoint.  It's free (assuming you have access to a Windows Server 2003 or 2008 machine with WSS turned on) and is extremely flexible.  Adding new custom columns is easy.  Adding custom views is easy.  Bulk editing is amazingly simple and powerful (assuming you're willing to use IE).  And building a custom home page "portal" with all the states of your team's workflow (e.g. unassigned, stories I'm working on, my resolved stories, to peer test, etc) is easy and is intuitive to use.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2010/02/video-how-to-create-burndown-charts-for.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>

<p>This 13 minute screencast shows you how to create a user stories list in SharePoint and build burn up and burn down charts off of the data using Microsoft Excel.  It includes the custom fields you'll need in SharePoint, the formula's you'll have to create in Excel, and shows tips along the way like how to simplify refreshing your reports when data changes.</p>

<object width="580" height="435"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9404991&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=e97000&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=9404991&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=e97000&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="580" height="435"></embed></object>

<p>Once you've watched the screencast if you want to implement this yourself here is the information you'll need:</p>

<p><b>Custom SharePoint Columns</b></p>

<ul>
<li>Iteration (Choice column e.g. Iteration00, Iteration01, zBacklog)</li>
<li>Released (Date - the date the iteration was closed out)</li>
<li>Points (Number)</li>
<li>Created Date (for demo only, you should be able to use "Created" on your project)</li>
</ul>

<p><b>Calculated Columns in Excel</b></p>

<ul>
<li>Total Points to Date
  <ul>
  <li>The total points on a specific date including backlog, current iteration and all completed stories</li>
  <li>=SUMIF([Created Date],CONCATENATE("<=",Table_owssvr_1[[#This Row],[Released]]),[Points])</li>
  </ul>
</li>
<li>Completed To Date
  <ul>
  <li>Total points for stories released prior to current story's release date</li>
  <li>=SUMIF([Released],CONCATENATE("<=",Table_owssvr_1[[#This Row],[Released]]),[Points])</li>
  </ul>
</li>
<li>Backlog
  <ul>
  <li>What remains to be completed at a point in time (e.g. don't include user stories added to the backlog in iteration 4 if this is for a task in iteration 03)</li>
  <li>=Table_owssvr_1[[#This Row],[Total Points to Date]]-Table_owssvr_1[[#This Row],[Completed to Date]]</li>
  </ul>
</li>
</ul>

<p><b>Burndown Pivot Table Values</b></p>

<ul>
<li>Row: Released</li>
<li>Filter: Released After [Some Date]</li>
<li>Values: Max(Backlog)</li>
</ul>

<p><b>Burnup Pivot Table Values</b></p>

<ul>
<li>Row: Released</li>
<li>Filter: Released After</li>
<li>Values
  <ul>
  <li>Max(Total Points to Date)</li>
  <li>Max(Completed To Date)</li>
  </ul>
</li>
</ul>

<p><b>Summary</b></p>
<p>I hope you found the presentation useful and if you are currently using SharePoint for tracking user stories please comment on your experiences.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/video_how_to_create_burndown_c.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/video_how_to_create_burndown_c.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Agile Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">agile</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">burndown</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">burnup</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">excel</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">project management</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
            <pubDate>Fri, 12 Feb 2010 16:46:16 -0500</pubDate>
        </item>
        
        <item>
            <title>Business Process Modeling for Software Developers</title>
            <description><![CDATA[<p>As a software developer I never thought I'd be saying this (I suppose eight years of working for the company that invented this technique might bias me), but you can not underestimate the value of business process modeling when starting a new project.  This is especially true if it's a small project and you don't have the benefit of a dedicated requirements analyst.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/12/business-process-modeling-for-software.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p>As a consultant (or as a person who is learning someone else's business) your job is to understand your customers existing business <i>better than they do themselves</i>.  And you need to be on the same page with others regarding how you are going to change their day to day functions.  And that's what business process modeling is for.</p>

<p>You may ignore this document after the first week on the project, in fact I would encourage you to. But even if you throw it away immediately after creating it, the process of developing the document will still:</p>

<ul>
<li>Flush out important questions</li>
<li>Show your customer you understand their world</li>
<li>Help document the project to other developers</li>
<li>Facilitate communication (especially with the people who pay the bills)</li>
<li>Generate user stories (requirements) </li>
<li>Identify the entities that can feed into an <a href="http://rapidapplicationdevelopment.blogspot.com/2007/06/entity-relationship-diagram-example.html">Entity Relationship Diagram</a> (or database I suppose)</li>
<li>Aid making good choices for the decisions it be hard to undo later (like whether to manually code workflows or use <a href="http://en.wikipedia.org/wiki/Windows_Workflow_Foundation">Windows Workflow Foundation</a>)</li>
<li>More clearly identify pain points and areas where your software can help end users; and</li>
<li>Identify metrics that can help determine project success from an ROI and product owner's perspective</li>
</ul>

<p>Convinced this is a tool you need in your toolbelt yet?  As long as the answer isn't "I only write code leave me alone" then check out this quick how-to:</p>

<p><b>Start with the AS-IS diagram</b></p>

<p>As soon as possible on a new project you should plan to interview your future end users.  This shouldn't be an unstructured Q&amp;A session.  You should start with a rough draft of what you think their business process is and ask questions that identify the places where you were wrong.<p>

<p>In order to start the diagram you need to identify both the end users and existing systems and put those in "swimlanes" down the left side of a diagram.  Swimlanes are important because they help you be explicit about who is performing what activities.  Then flush out activities in the happy path in appropriate swimlanes like so:</p>
 
<p><a href="http://3.bp.blogspot.com/_gez10dNhuPk/SzISYvjEwvI/AAAAAAAABrg/8X9h_xxiDvw/s1600-h/AS-IS.gif"><img style="cursor:pointer; cursor:hand;width: 400px; height: 344px;" src="http://3.bp.blogspot.com/_gez10dNhuPk/SzISYvjEwvI/AAAAAAAABrg/8X9h_xxiDvw/s400/AS-IS.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5418413517969867506" /></a></p>
 
<p>As soon as you talk to end users (like the clerk in the example above) you will discover unhappy paths.  What if the warehouse is out of a product?  What if the payment was declined?  What happens if a customer needs to return something?</p>

<p>Obviously you document these using standard activity diagram notation:</p>

<p><a href="http://2.bp.blogspot.com/_gez10dNhuPk/SzISZP5NmgI/AAAAAAAABro/Q6AeYSTx7eo/s1600-h/Choice.gif"><img style="cursor:pointer; cursor:hand;width: 389px; height: 400px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/SzISZP5NmgI/AAAAAAAABro/Q6AeYSTx7eo/s400/Choice.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5418413526652656130" /></a></p>

<p><b>Identifying Pain Points/Opportunities</b></p>
<p>The interesting part about unhappy paths is how often they occur, how they affect the customers of your customer, and ultimately how they affect your customer's bottom line.  For instance, how often is payment declined in the example above?  Fairly frequently?  Can you get an actual percentage?  If it turns out it's because the original application failed to validate credit cards, then a small amount of programming effort can provide a large benefit to length of time until order fulfillment.  Sometimes you can make the process more efficient without writing a line of code.</p>

<p>And at the end of your project if you can show that you've decreased the average length of time it takes to go through the process, ideally by showing less time was spent in unhappy paths, you will likely have made yourself one happy customer.  This can be especially effective if your new system can show statistics (like percent of orders that are declined) and compare those to the old process.</p>
<p><b>Developing the TO-BE diagram</b></p>
<p>AS-IS process diagrams are completely useless unless you can effectively describe what the process will look like after you implement your new system.  The process of developing these documents is pretty similar to the AS-IS diagram except of course you're trying to fix the pain points.</p>

<p>One technique I like for generating a backlog of user stories (tasks) is to put unique numbers with each step in the TO-BE process, then ensure there is at least one user story per step in the process.  You may be surprised at how easily activities in your new project's swimlane map to user stories.</p>
<p><b>Summary</b></p>
<p>I'm a fan of writing code as soon as possible on a project, but if you fail to understand an end user's business process you may be writing the wrong code.  Business process modeling can ensure you're writing the right code to solve the most important problems first.  And that may be the difference between project success and project failure.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/business_process_modeling_for.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/business_process_modeling_for.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Agile Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">agile</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">process</category>
            
            <pubDate>Wed, 23 Dec 2009 09:01:57 -0500</pubDate>
        </item>
        
        <item>
            <title>Ruby on Rails, a Microsoft Developer&apos;s Perspective</title>
            <description><![CDATA[<p>I suppose I'm a pretty hard core Microsoft developer.  I've been doing Microsoft .Net C# development since the .Net framework was first released in 2002.  Before that, starting in 1997 about when the technology was first released, I developed in Visual Basic with classic ASP (Active Server Pages).  So that's twelve years of Microsoft development all told.  Which is why the Ruby on Rails class I've been taking this week is so interesting.  Ruby represents a significant branching out for me.  So these are my initial impressions.  I am a complete Ruby neophyte, so please keep all flames at least friendly in tone :).</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/11/ruby-on-rails-microsoft-developers.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p><b>Dynamic Typing</b></p>
<p>Let's get to the heart of this Ruby stuff.  I thought I would passionately hate dynamic typing.  I was getting ready to fill pages ranting about its evils.  But that moment never came.  Don't get me wrong the Visual Studio strongly typed intellisense no-reading-documentation-needed experience is far nicer than the NetBeans look-it-up-in-irb-with-.methods experience.  But the feeling was more like mild to moderate annoyance rather than unbridled hatred.  Like when I mistyped a variable and Ruby decided it was a new variable initialized as nil.  Annoying, and hard to track down, but hey I'm a Ruby newbie, experts probably don't make these mistakes, right?  Anyway, I would be interested to hear how non-trivial, well tested applications perform with refactoring (e.g. variables/fields in views?) and how bad things get during O&amp;M.</p>
<p><b>Speed of Development</b></p>
<p>I figured speed of development would be Ruby's saving grace.  It was that and more.  The Ctrl-S-Alt-Tab-Ctrl-R-zero-delay development cycle is frickin' amazing!  It made development feel more fun than it has in a long time.  Part of that may be the slower-than-molasses-in-December speed of development I experience today on my (not 2010) SharePoint project.  Regardless, even if I were working in an ASP.Net MVC project I suspect the extra speed of development in Rails by skipping the main compilation and JIT compilation steps would increase the enjoyment of a Ruby project enough to equal out the lack of strong typing.</p>
<p><b>Active Record vs LINQ</b></p>
<p>Perhaps I'm just not experienced enough with active record, but to me the syntax feels contrived, non-intuitive, and just kind of agitating.  I mean it's cool that you can write </p>
<p><code style="color: black">p = Person.find_all_by_first_name_and_last_name("Lee", "Richardson")</code>
</p>
<p>Ugly as sin, but cool.  The alternative doesn't feel much better: </p>
<p><code style="color: black">p = Person.all(:conditions => <br />&nbsp;&nbsp;&nbsp;&nbsp;{ :first_name => "Lee", :last_name => "Richardson" })</code>
</p>
<p>Uch.  Of course I am biased.  I'm passionate about LINQ.  I love LINQ more than any single feature in Microsoft development.  I think LINQ may be the most brilliant stroke of genius Microsoft (Anders Hejlsberg) has ever had.  And I don't think I realized how passionately I felt about the technology until I didn't have it.  So for me I'll stick with:</p>
<p><code style="color: black">Person p = ctx.People.Where(p => <br />&nbsp;&nbsp;&nbsp;&nbsp;p.FirstName == "Lee" && p.LastName == "Richardson");</code></p>
<br />
<p><b>Duck Typing</b></p>
<p>My mind was blown when the instructor showed us polymorphism without inheritance.  I can't argue about how incredibly powerful it is.  I just cringe to think of the potential misuse.  But without any real Ruby experience I'll have to just leave it at "Wow!"</p>
<p><b>Mocking</b></p>
<p>It's pretty scary that you can override the functionality of any method anywhere in Ruby.  But when the instructor showed us overriding DateTime.now for the purposes of mocking I had an "ah ha!" moment.  Mocking DateTime.Now in C# is an awful experience that involves an intermediate class with a virtual "Now()" method.  Ruby sure got C# on that one.</p>
<p><b>YAML</b></p>
<p>It's no secret that I passionately hate XML.  And it's no secret that Microsoft passionately loves XML.  Pity about the mismatch.  Ruby on Rails really endeared itself to me when its designers recognized that XML is a travesty against humanity and used <a href="http://en.wikipedia.org/wiki/Yaml">YAML Ain't Markup Language</a> instead.  Nice!</p>
<p><b>Interactive Ruby Console</b></p>
<p>The Interactive Ruby Console (IRB) is just wonderful.  Now I can at least get that functionality today in C# with <a href="http://www.nearinfinity.com/blogs/joe_ferner/">Joe Ferner's</a> excellent <a href="http://devtoolbox.codeplex.com/">Developer's Toolbox</a>.  What I can't get is the Interactive Rails Console (ruby script/console).  Now that is awesome.  I can't wait for C# 4.0 which I suspect will have this.  For now RoR++, C#-- .</p>
<p><b>Tooling</b></p>
<p>I'm not sure how related this is to dynamic typing, but surprisingly I really, really missed Visual Studio.  Perhaps RubyMine is better that NetBeans.  I sure wasn't impressed with Komodo.  I just felt like constantly switch between my IDE and various console windows, and a database viewer felt clumsy yet somehow necessary with Rails.  It just felt so 1999.</p>
<p><b>Summary</b></p>
<p>There's no doubt about it, I could be very happy on a Ruby project.  The no XML thing is just a perk, the fast development cycles and bringing fun back to coding again is truly awesome.  But am I ready to give up Microsoft development full time just yet?  No way.  LINQ, strong typing, and believe it or not Visual Studio tip the scales back to about equal.  Now if only Microsoft could somehow make compilation instantaneous.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/ruby_on_rails_a_microsoft_deve.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/ruby_on_rails_a_microsoft_deve.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">LINQ</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ruby</category>
            
            <pubDate>Wed, 18 Nov 2009 10:42:15 -0500</pubDate>
        </item>
        
        <item>
            <title>SharePoint 2010 Expectations Meet Reality</title>
            <description><![CDATA[<p>The current version of SharePoint and I have a love hate relationship.  Since I want to be able to look forward to a more joyful and fulfilling relationship with the tool/platform, I made a list of my biggest frustrations before I left for the SharePoint 2010 conference (<a href="http://www.bing.com/twitter/search?q=%23spc09&form=QB ">#spc09</a>).  My objective was to return with most of the items checked off as resolved and to have a bunch of new functionality that I hadn't realized I needed.  SharePoint 2010 easily fulfils the second promise with stuff like Business Data Services (Awesome!) and Visio Data Services (Amazing!).  But I don't want to try to recap the whole conference so here's just how it compares to my initial list:</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/10/sharepoint-2010-expectations-meet.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p><b>Testability</b></p>
<p>SharePoint is <a href="http://rapidapplicationdevelopment.blogspot.com/2009/08/sharepoint-wild-west-of-software.html">notoriously hard to unit test</a>.  The good news is Microsoft provided a whole session devoted to software development best practices that included a good chunk on unit testing.  It was wonderful to see!</p>
<p>The bad news: SharePoint 2010 will not have public constructors and classes will still be sealed (final).  The good news to the bad news: After discussing this issue with Chris Keyser I discovered that Peli de Halleux of Microsoft Research has a free tool called <a href="http://research.microsoft.com/en-us/projects/pex/default.aspx">Pex</a> that solves the whole problem.  It allows what it calls detours, which allow you to mock non-virtual methods.  This stuff is amazing and I'll blog more about it later.</p>
<p>Summary: Testability is better even for existing SharePoint installs -- so between <a href=" http://sporm.codeplex.com/">Sporm</a> and Pex this is a non-issue -- I'm happy.</p>
<p><b>No Referential Integrity</b></p>
<p>It kills me that if you create an employee list item that references a company list item and you delete the company list item then nothing happens.  No cascading delete.  No error message.  Just an orphan record.  SharePoint 2010 now supports both true referential integrity through errors and cascading deletes!</p>
<p>Summary: Awesome!</p>
<p><b>Validation is Terrible</b></p>
<p>Ever tried to validate by pattern in SharePoint (e.g. social security number)?  How about range validate (e.g. date of birth can't be after today)?  Or maybe validate one field against another?  The answer is you can't.  Not easily or consistently.  If you handle validation in an event receiver then the user doesn't get the error until after a postback on a separate page.  And custom field controls are a lot of work and they don't work in datasheet view.</p>
<p>SharePoint 2010 mostly solves these validation issues by allowing field level and list level validation.  The error messages even show in datasheet view.  The bad news is that pattern matching is not currently supported (e.g. you can't validate social security number).</p>
<p>Summary: Good stuff, need to see the final version to be extremely happy.</p>
<p><b>Poor Documentation</b></p>
<p>Ever noticed that blogs give you better details on SharePoint APIs than MSDN does?  I don't even bother looking on MSDN for SharePoint content anymore.  Since the hands on labs didn't contain any documentation I'll have to refer to what Steve Ballmer said during the Q&A session, which was that better documentation will be a priority.</p>
<p>Summary: high hopes, but TBD.</p>
<p><b>Views Don't Allow Precedence</b></p>
<p>If you've ever needed a view with A and (B or C) and ended up with (A and B) or C, you know where I'm coming from.  As a developer you can implement precedence in CAML, but as an end user you're stuck.  Sadly this issue is still not fixed in SharePoint 2010.</p>
<p>Summary: Fail.</p>
<p><b>Re-Deployment is Hard</b></p>
<p>Currently redeploying lists is hard; redeploying web parts without overwriting user settings is hard; and redeploying workflows is very hard.</p>
<p>Without documentation and intermittent Internet <a href="http://www.nearinfinity.com/blogs/joe_ferner/">Joe Ferner</a> and I had a hard time manually confirming that this is better.  We also missed a key session on Thursday that talked about it.  There were some tweets that looked promising, but I'll have to wait until Thursday's presentations are posted to be able to comment for sure.</p>
<p>Summary: Good I think, but still TBD.</p>
<p><b>Massive Duplication in CAML Instantiated Lists</b></p>
<p>Using CAML to instantiate a list is currently awful in SharePoint.  It's like 5 pages of CDATA and HTML and XML with massive duplication.  Sadly SharePoint 2010 doesn't solve the root problem: list instantiation looks exactly the same.  The good news is that along with just about every other aspect of SharePoint 2010 development, Visual Studio makes this task mind numbingly easy to do.  If you can just try not to look in that file that was auto-generated for you, then you should be fine.</p>
<p>Summary: Better.</p>
<p><b>Poor Usability</b></p>
<p>Once you get used to the current version of SharePoint the user interface is extremely consistent and many users really like it.  But if you were to compare it to any modern Web 2.0 site it's a complete failure.  SharePoint 2010 does an excellent job of implementing selective refresh/AJAX/Web 2.0.  But to me it feels more complicated.  Maybe this is because it introduces the ribbon, which I have never liked.  Maybe it just is more complicated.  In any event I'm not the best judge of usability, so I'll have to wait and see what others say.</p>
<p>Summary: Definitely better, but jury's still out.</p>
<p><b>Can't Reference a List <i>AND</i> Content Type</b></p>
<p>Suppose you have a Calendar list.  The list supports two content types: Events, and Iterations (sprints).  It's a nice architecture because you want to view iterations and events in the same calendar views.  Now if you have a User Story list, wouldn't it be nice to have a lookup field that points only to Iterations?  Sadly you couldn't do this before and you won't be able to for the foreseeable future.</p>
<p>Summary: Fail.</p>
<p><b>CAML for Queries</b></p>
<p>Technically this wasn't on my list because I use <a href="http://sporm.codeplex.com">Sporm</a>, but on behalf of my non-spormified software development brethren let me say that writing <a href="http://rapidapplicationdevelopment.blogspot.com/2009/09/sporm-out-of-depths-of-sharepoints-xml.html">queries in CAML is awful</a>.</p>
<p>SharePoint 2010 makes enormous strides in this area.  I won't go into great detail, but you can now use LINQ on the server side <i>and on the client side</i>!</p>
<p>Summary: Awesome!</p>
<p><b>Summary</b></p>
<p>Lots of TBD, lots of awesomeness, still some fail.  Worth upgrading?  Absolutely.  Will it still be a love hate relationship?  Probably, but at the moment it's looking pretty darn good.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/sharepoint_2010_expectations_m.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/sharepoint_2010_expectations_m.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">LINQ</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">testing</category>
            
            <pubDate>Sat, 24 Oct 2009 01:26:55 -0500</pubDate>
        </item>
        
        <item>
            <title>Sporm - Out of the Depths of SharePoint&apos;s XML Hell</title>
            <description><![CDATA[<p>In my last post I described how a new open source tool called <a href="http://sporm.codeplex.com/">sporm</a> significantly simplifies <a href=" http://rapidapplicationdevelopment.blogspot.com/2009/09/unit-testing-sharepoint-past-present.html">unit testing SharePoint</a>.  Making SharePoint unit testable is my absolute favorite feature of sporm because SharePoint is notoriously hard to unit test.  But sporm provides other benefits as well and its ability to pull us out of the depths of verbose loosely typed XML hell and into LINQ excellence is next on my list of favorite features.  So in this post I'll describe the pre-sporm technique of querying with CAML, how to query data using sporm, and finally how sporm supports SharePoint's unique architecture of allowing multiple content types per list and what that means to you.</p>

<p><b>Caml's Are Ugly</b></p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/09/sporm-out-of-depths-of-sharepoints-xml.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p><i>Warning: if you're new to SharePoint then what you're about to see may shock and upset you.  If, like me, you hate both XML and loose typing then you will agree that CAML is awful, but bear with me I promise sporm will make it better.  Much better.</i></p>

<p>CAML or Collaborative Application Markup Language is how one queries for data in SharePoint.  A simple query might look like this:</p>

<p>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">Query</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&gt;<br />        <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">Where</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">And</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">And</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">Eq</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">FieldRef</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> </span>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:red;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">Name</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">=</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&#39;<span style="color:blue">First_Name</span>&#39;<span             style="color:blue"> /&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">Value</span><span style="color:blue"> </span>        <span style="color:red">Type</span><span style="color:blue">=</span>&#39;<span             style="color:blue">Text</span>&#39;<span style="color:blue">&gt;</span>Lee<span             style="color:blue">&lt;/</span><span style="color:#A31515">Value</span><span             style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span             style="color:#A31515">Eq</span><span style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">BeginsWith</span><span style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">FieldRef</span><span style="color:blue"> </span>        <span style="color:red">Name</span><span style="color:blue">=</span>&#39;<span             style="color:blue">Last_Name</span>&#39;<span style="color:blue"> /&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">Value</span><span style="color:blue"> </span>        <span style="color:red">Type</span><span style="color:blue">=</span>&#39;<span             style="color:blue">Text</span>&#39;<span style="color:blue">&gt;</span>Rich<span             style="color:blue">&lt;/</span><span style="color:#A31515">Value</span><span             style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span             style="color:#A31515">BeginsWith</span><span style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:#A31515">And</span><span style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color:#A31515">Leq</span><span             style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">FieldRef</span><span style="color:blue"> </span>        <span style="color:red">Name</span><span style="color:blue">=</span>&#39;<span             style="color:blue">Dob</span>&#39;<span style="color:blue"> /&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span             style="color:#A31515">Value</span><span style="color:blue"> </span>        <span style="color:red">Type</span><span style="color:blue">=</span>&#39;<span             style="color:blue">DateTime</span>&#39;<span style="color:blue">&gt;</span>2009-01-01T00:00:00Z<span             style="color:blue">&lt;/</span><span style="color:#A31515">Value</span><span             style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:#A31515">Leq</span><span style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color:#A31515">And</span><span            style="color:blue">&gt;<br />        <span style="mso-spacerun:yes">&nbsp; </span>&lt;/</span><span style="color:#A31515">Where</span><span             style="color:blue">&gt;<br />        &lt;/</span><span style="color:#A31515">Query</span><span style="color:blue">&gt;<br             style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span></span>    </p>

<p>Simple right?  ;) In case you didn't catch the meaning from the slightly, uh verbose, query this asks for records with a First_Name of "Lee", a Last_Name starting with "Rich" and a "Dob" less than or equal January 1 2009.</p>

<p>There are a couple of things to note about this query:</p>

<ul>
<li>Field names are loosly typed.  If Dob were ever renamed to DateOfBirth the query would fail at runtime (probably during a demo to a customer, or if you're lucky during integration tests), but certainly not at compile time.</li>
<li>And is a binary operator.  This forces explicit precedence and removes the need for parenthesis, but at the cost of readability.</li>
<li>Types must be explicitly defined.  I guess this is necessary since it's XML, but somehow I just don't feel like this should be necessary.</li>
<li>It's XML.  Ok obviously, but the point is you have to type everything twice.  &lt;BeginsWith&gt; &lt;/BeginsWith&gt;.  Ouch, so verbose, so angley, I so hate XML.</li>
</ul>

<p>Now, there are tools that make this better.  U2U's free <a href=" http://www.u2u.be/Res/Tools/CamlQueryBuilder.aspx ">CAML Query Builder</a> tool significantly improves the experience of querying SharePoint data.</p>

<p><a href="http://3.bp.blogspot.com/_gez10dNhuPk/Sq2PcGTvHUI/AAAAAAAABqM/YB6rGTZrIpA/s1600-h/CamlQueryBuilder.jpg"><img style="WIDTH: 400px; HEIGHT: 268px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5381114842670112066" border="0" alt="" src="http://3.bp.blogspot.com/_gez10dNhuPk/Sq2PcGTvHUI/AAAAAAAABqM/YB6rGTZrIpA/s400/CamlQueryBuilder.jpg" /></a></p>

<p>But it makes you wonder if something is wrong when you need a tool to retrieve data from your data store.  Do you typically use tools to assist when you're writing SQL?  Probably not.  But like I said hang in there, sporm make things better.</p>

<p><b>Unlinq my Caml</b></p>

<p>If you were to write the same query as above using sporm it would look like this:</p>

<p>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#2B91AF;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">IQueryable</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&lt;<span style="color:#2B91AF">Employee</span>&gt; employees =         GetEmployees().Where(e =&gt;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>e.FirstName ==        <span style="color:#A31515">&quot;Lee&quot;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&amp;&amp; e.LastName.StartsWith(<span             style="color:#A31515">&quot;Rich&quot;</span>)<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&amp;&amp; e.Dob &lt;= <span style="color:blue">        new</span> <span style="color:#2B91AF">DateTime</span>(2009, 1, 1));<br             style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span>    </p>

<p>Just a little easier to read than CAML, right?  A couple of things to note:</p>

<ul>
<li>Fields are strongly typed.  If you were to rename FirstName the compiler would catch every single instance at design time.</li>
<li>Operators are standard C# operators.  &&, .StartsWith(), and <= are all familiar and concise and use a standard, known precedence.</li>
<li>Types are standard C# types.  You never have to explicitly say that "Rich" is a string, it just is.</li>
<li>Your query is actual C# code.  The lambda (closure) and the fact that it uses <a href="http://rapidapplicationdevelopment.blogspot.com/2008/03/how-systemlinqwhere-really-works.html">deferred execution</a> might throw off a junior developer in some scenarios, but the query is readable and works exactly the same as if you were querying in memory objects or querying a database with LINQ to SQL or the Entity Framework.</li>
</ul>

<p>Nice!  What's beautiful about this is that sporm converts your C# directly into CAML using C# 3.0's <a href="http://rapidapplicationdevelopment.blogspot.com/2008/03/expression-trees-why-linq-to-sql-is.html">expression trees</a> feature.  What sporm can't convert to CAML it executes in memory transparently to you.  Sporm uses log4net and outputs its CAML queries to the console by default, so it is a good idea to watch the output if you're concerned about performance.</p>

<p>Now the following isn't relevant to the comparison with CAML, but I would be negligent if I didn't explain how the GetEmployees() function works.</p>

<p><b>SP != DB B/C of Content Types</b></p>

<p>First of all GetEmployees looks like this:</p>

<p>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">private</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">        <span style="color:#2B91AF">IQueryable</span>&lt;<span style="color:#2B91AF">Employee</span>&gt;         GetEmployees() {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>        <span style="color:#2B91AF">MySPDataContext<br />        </span><span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetCurrent()<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetList&lt;<span             style="color:#2B91AF">Employees</span>&gt;()<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.OfType&lt;<span             style="color:#2B91AF">Employee</span>&gt;();<br />        }<br style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span>   </p>

<p>How it works is that the static GetCurrent() method retrieves sporm's context object, which knows how to query a SharePoint site, from either the web context or thread local storage; next the GetList() method tells sporm which list you want to query; and the OfType() method tells sporm which content type within the list you want to query.  This last part is important because sporm supports SharePoint's ability to have multiple content types per list, which other LINQ providers like LINQ to SharePoint do not.  But what are content types and why should you care?</p>

<p>SharePoint's List/Content Type architecture seems odd at first, but it allows interesting scenarios not available in a traditional database.  For instance you might have a calendar list that contains multiple types of records (list items) in the same list.  Your calendar list might contain some combination of the following three record types: meetings with unique fields like Organizer (a person); iterations with unique fields like DeployedToProduction (a Boolean); and actions with unique fields like RelatedEmployee (a reference to another list).  This architecture allows SharePoint to view all three types of records in a single view: like a per month calendar view.  The data might look like this:</p>

<table border="1">
<tr>
<td><b>Title</b></td>
<td><b>Start</b></td>
<td><b>End</b></td>
<td><b>ContentType</b></td>
<td><b>Organizer</b></td>
<td><b>Deployed To Production</b></td>
<td><b>Related Employee</b></td>
</tr>
<tr>
<td>Iteration16</td>
<td>1/12/09</td>
<td>1/19/09</td>
<td>Iteration</td>
<td>&nbsp;</td>
<td>false</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Stakeholder Demo</td>
<td>1/19/09 3 PM</td>
<td>&nbsp;</td>
<td>Meeting</td>
<td>Lee Richardson</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Tag Trunk</td>
<td>1/19/09</td>
<td>&nbsp;</td>
<td>Action</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Lee Richardson</td>
</tr>
</table>

<p>Sporm's unique architecture supports this scenario by allowing you to retrieve iterations like this:</p>

<p>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">return</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">        <span style="color:#2B91AF">MySPDataContext<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetCurrent()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetList&lt;<span style="color:#2B91AF">Calendar</span>&gt;()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.OfType&lt;<span style="color:#2B91AF">Iteration</span>&gt;();<br             style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span>    </p>

<p>Or get meetings from the same list like this:</p>

<p>        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">return</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">        <span style="color:#2B91AF">MySPDataContext<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetCurrent()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetList&lt;<span style="color:#2B91AF">Calendar</span>&gt;()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.OfType&lt;<span style="color:#2B91AF">Meeting</span>&gt;();<br             style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>      <br style="mso-special-character:line-break" />        <![endif]></span>    </p>

<p>While you may only use multiple content types per list occasionally you can feel comfortable knowing that sporm will support you when you need it.  The rest of the time you can arrange your architecture to accommodate your 90% scenario of one content type per list.  I'll discuss the architecture I'm using on my current project in my next post.</p>

<p>For now I hope this has clarified some of the benefits of using sporm, and I hope that you'll consider using it on your next SharePoint project.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/sporm_-_out_of_the_depths_of_s.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/sporm_-_out_of_the_depths_of_s.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">LINQ</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
            <pubDate>Sun, 13 Sep 2009 21:10:03 -0500</pubDate>
        </item>
        
        <item>
            <title>Unit Testing SharePoint - Past, Present, and Sporm</title>
            <description><![CDATA[<p>As I described in <a href=" http://rapidapplicationdevelopment.blogspot.com/2009/08/sharepoint-wild-west-of-software.html">SharePoint: The Wild West of Software Development</a> there is a serious problem when you develop for SharePoint: ensuring quality through unit testing is really, really hard.  And that's where a new open source tool just released today called <a href=" http://sporm.codeplex.com/ ">sporm</a> (SharePoint Object Relational Mapper) comes in.  While sporm provides many benefits besides simplified unit testing I wanted to focus on this topic first, because sporm's approach, which models the <a href="http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx">entity framework</a> in the way it supports POCO's, is a unique feature not available with other SharePoint tools like LINQ to SharePoint.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/09/unit-testing-sharepoint-past-present.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script>
</div>

<p>I'll start by describing the unit testing problem, then provide a conventional solution with mocking, then finish with the elegance of a sporm based solution.</p>

<p><b>Simple Unit Testing Turns Ugly</b></p>

<p>I would bet anyone that attempts to develop a tiered solution with SharePoint ends up with entities that look something like this:</p>

<p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-align:none;text-autospace:none">        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:blue;mso-no-proof:yes">public</span><span             style="font-size:10.0pt;font-family:&quot;Courier New&quot;;mso-no-proof:yes">        <span style="color:blue">class</span> <span style="color:#2B91AF">Employee</span>         {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:blue">public</span> <span style="color:#2B91AF">SPListItem</span>         ListItem { <span style="color:blue">get</span>; <span style="color:blue">private</span>        <span style="color:blue">set</span>; }<br />        <br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> </span>        <span style="color:gray">&lt;summary&gt;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> The constructor         requires that you pass in a list item        <br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> that is used by         your strongly typed properties<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> </span>        <span style="color:gray">&lt;/summary&gt;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:blue">public</span> Employee(<span style="color:#2B91AF">SPListItem</span>         listItem) {<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        </span>ListItem = listItem;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />        <br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> </span>        <span style="color:gray">&lt;summary&gt;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> This provides your         entities strong typing to hide        <br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> the native weak         typing in SharePoint<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:gray">///</span><span style="color:green"> </span>        <span style="color:gray">&lt;/summary&gt;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="color:blue">public</span> <span style="color:blue">virtual</span>        <span style="color:blue">string</span> LastName {<br />      <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        </span><span style="color:blue">get</span> { <span style="color:blue">return</span>         (<span style="color:blue">string</span>)ListItem[<span style="color:#A31515">&quot;LastName&quot;</span>];         }<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        </span><span style="color:blue">set</span> { ListItem[<span             style="color:#A31515">&quot;LastName&quot;</span>] = <span style="color:blue">value</span>;         }<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />        }<br style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]><o:p></o:p></span>    </p>

<p>And if you have some function that you'd like to unit test like this:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:gray;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">///</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:green;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> </span>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:gray;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&lt;summary&gt;<br />        ///</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:green;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> Typically returns &quot;[LastName], [FirstName]&quot; but skips        <br />        </span>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:gray;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">///</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:green;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> the comma if either is missing<br />        </span>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;o-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:gray;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">///</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:green;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> </span>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:gray;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">&lt;/summary&gt;<br />        </span>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">public</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> <span style="color:blue">string</span> GetNameFormatted() {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">bool</span>         noFirst = <span style="color:blue">string</span>.IsNullOrEmpty(FirstName);<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">bool</span>         noLast = <span style="color:blue">string</span>.IsNullOrEmpty(LastName);<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">if</span>         (noFirst &amp;&amp; noLast) <span style="color:blue">return</span>        <span style="color:#A31515">&quot;&quot;</span>;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">if</span>         (noFirst) <span style="color:blue">return</span> LastName;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">if</span>         (noLast) <span style="color:blue">return</span> FirstName;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>        <span style="color:blue">string</span>.Format(<span style="color:#A31515">&quot;{0},         {1}&quot;</span>, LastName, FirstName);<br />        }<br />        <br style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span>    </p>

<p>Now you face a major problem: LastName is tightly coupled with SPListItem.  And SPListItem only contains internal constructors making it unmockable.  So if you keep the tight coupling and pass an SPListItem into the constructor then you need a connection to SharePoint and an employee list (table) and you need to create an employee list item (record), then you test it, and finally you ought to clean up after yourself and delete the list item.  Talk about a simple unit test turned fragile integration test.  Yuck.</p>

<p><b>Mocking the Solution</b></p>

<p>So at this point you're undoubtedly thinking it's time to mock.  To do this you'll have to make a public constructor that takes no arguments and mark your properties virtual.  Then you can write a test like this:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">[<span style="color:#2B91AF">TestMethod</span>]<br />        <span style="color:blue">public</span> <span style="color:blue">void</span>         TestGetNameFormatted_FirstAndLastExist_LastCommaFirst() {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">        MockRepository</span> mocks = <span style="color:blue">new</span>        <span style="color:#2B91AF">MockRepository</span>();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Employee</span>         mockEmployee = mocks.StrictMock&lt;<span style="color:#2B91AF">Employee</span>&gt;();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Expect</span>.Call(mockEmployee.FirstName).Return(<span             style="color:#A31515">&quot;Lee&quot;</span>).Repeat.Any();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Expect</span>.Call(mockEmployee.LastName).Return(<span             style="color:#A31515">&quot;Richardson&quot;</span>).Repeat.Any();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mocks.ReplayAll();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span>         actual = mockEmployee.GetNameFormatted();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mocks.VerifyAll();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Assert</span>.AreEqual(<span             style="color:#A31515">&quot;Richardson, Lee&quot;</span>, actual);<br />        }</span></p>

<p>And then if you're like me you absolutely hate your unit tests.  Because let alone that you had to modify your production code to accommodate unit testing, more importantly your unit tests are now unreadable.  All of them.  Even in simple methods without dependencies your unit tests contain almost as much plumbing code as actual test code.  Enter sporm.</p>

<p><b>Unmocking with Sporm</b></p>

<p>Sporm is an open source tool released on codeplex that was developed by fellow <a href="http://www.nearinfinity.com/">Near Infinity</a> employee <a href=" http://www.nearinfinity.com/blogs/joe_ferner/ ">Joe Ferner</a> (who, incidentally, is one of the most brilliant developers I know).  While this is a version 1.0 product Joe has been using it on his project and independently I've been using it on my project for several months now, so it is relatively mature.</p>

<p>So how it works is that at design time sporm will read from your SharePoint site and generate partial classes for each of your list items and each of your content types.  The generated classes don't inherit from anything, giving you the ability architect your solution how you see fit.  And the properties are auto-properties, making the classes just pure POCO.  Here's an example if you're interested:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">[<span style="color:#2B91AF">SPOrmContentType</span>(Name=<span             style="color:#A31515">&quot;Employee&quot;</span>)]<br />        <span style="color:blue">public</span> <span style="color:blue">partial</span>        <span style="color:blue">class</span> <span style="color:#2B91AF">Employee</span>         : <span style="color:#2B91AF">ISPOrmContentType</span> {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">static</span> <span style="color:blue">class</span>        <span style="color:#2B91AF">FieldTitles</span> {<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">const</span> <span style="color:blue">string</span>         FirstName = <span style="color:#A31515">&quot;First Name&quot;</span>;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />        <br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">static</span> <span style="color:blue">class</span>        <span style="color:#2B91AF">FieldStaticName</span> {<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">const</span> <span style="color:blue">string</span>         FirstName = <span style="color:#A31515">&quot;FirstName&quot;</span>;<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />        <br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>[<span style="color:#2B91AF">SPOrmIdField</span>()]<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">virtual</span> <span style="color:blue">int</span> Id {        <span style="color:blue">get</span>; <span style="color:blue">set</span>; }<br />        <br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>[<span style="color:#2B91AF">SPOrmField</span>(Title         = <span style="color:#2B91AF">FieldTitles</span>.FirstName, StaticName =        <span style="color:#2B91AF">FieldStaticName</span>.FirstName)]<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>      <span style="color:blue">virtual</span> <span style="color:blue">string</span>         FirstName { <span style="color:blue">get</span>; <span style="color:blue">set</span>;         }<br />        }<br style="mso-special-character:line-break" />        <![if !supportLineBreakNewLine]>        <br style="mso-special-character:line-break" />        <![endif]></span>    </p>

<p>Since generated entities look like that, your entities can now look like this:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">public</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> <span style="color:blue">partial</span>        <span style="color:blue">class</span> <span style="color:#2B91AF">Employee</span>         {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>        <span style="color:blue">string</span> GetNameFormatted() {<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">bool</span>         noFirst = <span style="color:blue">string</span>.IsNullOrEmpty(FirstName);<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">bool</span>         noLast = <span style="color:blue">string</span>.IsNullOrEmpty(LastName);<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">...<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />        }</span></p>

<p>Now if that isn't a picture of beauty to you then you haven't been working with SharePoint.  But wait, I hear you asking, how does this have anything to do with SharePoint?  How would an instance of an employee be able to retrieve the data in a SharePoint ListItem?  The answer is in the DataContext.  In your production code you write something like this:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">public</span><span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> <span style="color:blue">static</span>         Employee FindById(<span style="color:blue">int</span> id) {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>        <span style="color:#2B91AF">MySPDataContext<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetCurrent()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.GetList&lt;TList&gt;()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.OfType&lt;TContentType&gt;()<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.FirstOrDefault(c =&gt; c.Id ==         id);<br />        }</span></p>

<p>While it might not look so pretty at first you can hide these details in a base type and the nice thing is that it does handle SharePoint's ability to have multiple content types per list (which LINQ to SharePoint does not do, incidentally).  But for now all you need to know is that when you return an Employee thorugh MySPDataContext it subtypes your Employee class and returns you a proxy at runtime.  The proxy overrides each property to return you the appropriate value in the SPListItem.  And if you instantiate an Employee directly (as you would in unit testing) then you can use it like a pure POCO.  If you're familiar with the entity framework this should sound extremely similar.  The result is that you can write your unit tests like this:</p>

<p>        <span style="font-size:10.0pt;line-height:115%;font-family:&quot;Courier New&quot;;mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">[<span style="color:#2B91AF">TestMethod</span>]<br />        <span style="color:blue">public</span> <span style="color:blue">void</span>         TestGetNameFormatted_FirstAndLastExist_CommaSeparate() {<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Employee</span>         employee = <span style="color:blue">new</span> <span style="color:#2B91AF">        Employee</span> {<br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>FirstName =        <span style="color:#A31515">&quot;Lee&quot;</span>,        <br />        <span style="mso-tab-count:2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>LastName =        <span style="color:#A31515">&quot;Richardson&quot;<br />        </span><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>};<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span>         actual = employee.GetNameFormatted();<br />        <span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">Assert</span>.AreEqual(<span             style="color:#A31515">&quot;Richardson, Lee&quot;</span>, actual);<br />        }</span></p>

<p>No SharePoint dependencies.  No mocking.  Nothing but pure, unadulterated unit test.  Now that a thing of beauty.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/unit_testing_sharepoint_-_past.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/unit_testing_sharepoint_-_past.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">testing</category>
            
            <pubDate>Wed, 09 Sep 2009 15:44:18 -0500</pubDate>
        </item>
        
        <item>
            <title>SharePoint: The Wild West of Software Development</title>
            <description><![CDATA[<p>Some argue that Microsoft developers lack rigor -- that techniques like unit testing and continuous integration are virtually unheard of in this space. That's rubbish. I would be shocked if the percentage of developers that track code coverage is significantly different for the .Net or Java spaces (not quite mainstream, but respectable). Mind you I'm talking .Net development in general. SharePoint, now that's another story.<p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/08/sharepoint-wild-west-of-software.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>

<p>The shadowy world of SharePoint is one in which source control is a distant memory, where no distinction is drawn between development, test and production environments, and where roaming bandits take over small towns with no fear of the law.</p>

<p><a href="http://4.bp.blogspot.com/_gez10dNhuPk/Son--92lb_I/AAAAAAAABps/a2B3pE9iuW4/s1600-h/WildWest.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 264px;" src="http://4.bp.blogspot.com/_gez10dNhuPk/Son--92lb_I/AAAAAAAABps/a2B3pE9iuW4/s400/WildWest.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5371104388324880370" /></a></p>

<p>Why is this?  How has it come to be?  The answer is that for the most part SharePoint treats code and data as one in the same.  End users can modify data stores: they can add, delete and modify tables (Lists) and columns (Fields) at will.  They can open up SharePoint Designer and modify pages, customize workflows, rob banks, and run local Sherriff's out of town.</p>

<p>And that's why end users <i>love</i> SharePoint.  It removes the slow, burdensome bureaucracy involved in doling out development resources from large centrally planned corporate or government IT departments and places that power directly in the hands of end users, allowing them to get their jobs done faster and to adapt to change quicker.  And that is why I maintain that as software developers SharePoint, or a product like it, is in our future -- like it or not.</p>

<p>But the power given to end users makes rigor and good design extremely hard for developers because the production machine you deployed to last month may look completely different now that you're ready to redeploy.  And Microsoft makes good design even harder with an inflexible API.  Critical classes like SPSite (think SqlConnection) contain no public constructor, rendering them completely unmockable (unless you're willing to spend $450 <i>per developer</i> for some <a href="http://www.typemock.com/Buy.php">TypeMock Isolator</a> magic).  And vital classes like SPList (think DataSet) are marked final, crippling your ability to make nice strongly typed entities in your architectures.</p>

<p>So what is a Type-A, quality minded software developer to do?</p>

<p>The thing to keep in mind is that the challenges that SharePoint places on developers and architects simultaneously make good coding practices harder (but not impossible) while making them more important than ever.</p>

<p>Because that column you thoughtfully added as required may get reset to optional by an end user in production, you need to write more good tests that validate once solid assumptions.  Because you can't inherit SPList, you'll need to encapsulate it, requiring more code per entity.  Because you can't mock essential SharePoint classes you will need to write more integration tests instead of unit tests.  Because you're writing integration tests your tests will be more fragile and you'll spend more time fixing the test code than the real code.</p>

<p>And because you're spending more time focusing on quality while your Wild West, short term focused competition in the SharePoint world slings code together, they will appear faster and better able to get applications out the door.  It can be frustrating, because over time your well designed and well tested application will be more maintainable and will cost IT departments less.  But end users frequently don't understand this, so as long term minded SharePoint developers we must focus on educating end users.</p>

<p>Combat the short term focused mindset by keeping everything in .wsp files, storing code in source control, avoiding the temptation to apply fixes in production, using continuous integration (yes, for SharePoint!), and most importantly tracking code coverage (yes, code coverage for SharePoint code!).  Put quality metrics in status reports for management to see.  Track defects and make your stats publicly available (since you'll have significantly fewer over time than code slingers, and you want end users asking for stats).  In short remind the world that quality counts, even in the shadowy realms of SharePoint.  If we work together we can bring law and order to the ... um, West.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/sharepoint_the_wild_west_of_so.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/sharepoint_the_wild_west_of_so.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">code coverage</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">continous integration</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">quality</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">SharePoint</category>
            
            <pubDate>Mon, 17 Aug 2009 21:27:42 -0500</pubDate>
        </item>
        
    </channel>
</rss>

