<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" 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" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-25631453</atom:id><lastBuildDate>Thu, 26 Jan 2012 11:57:18 +0000</lastBuildDate><category>linqtosql</category><category>mocks</category><category>linq</category><category>appharbor</category><category>javascript</category><category>learn something new</category><category>personal</category><category>silverlight</category><category>unittest</category><category>mmnet</category><category>gReadie</category><category>harris</category><category>nancy</category><category>ncg</category><category>YUI</category><category>mongodb</category><category>ravendb</category><category>mvc</category><category>wp7dev</category><category>C#</category><category>node</category><category>wp7</category><category>wpf</category><category>ozfox</category><category>dt</category><category>design</category><category>asp.net</category><category>glimpse</category><category>heroku</category><category>dotnet</category><category>svfpug</category><category>open-source</category><category>vfp</category><category>vista</category><category>node-webkit</category><category>knockout</category><title>Chris Sainty</title><description>A technical blog about software development. Usual topics include C#, Node.js, WP7, RavenDb, Nancy.</description><link>http://csainty.blogspot.com/</link><managingEditor>noreply@blogger.com (Chris Sainty)</managingEditor><generator>Blogger</generator><openSearch:totalResults>75</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/rss+xml" href="http://feeds.feedburner.com/ChrisSainty" /><feedburner:info uri="chrissainty" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-2526950740026506989</guid><pubDate>Wed, 25 Jan 2012 23:07:00 +0000</pubDate><atom:updated>2012-01-26T10:07:52.155+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">personal</category><category domain="http://www.blogger.com/atom/ns#">open-source</category><category domain="http://www.blogger.com/atom/ns#">node</category><category domain="http://www.blogger.com/atom/ns#">glimpse</category><category domain="http://www.blogger.com/atom/ns#">nancy</category><category domain="http://www.blogger.com/atom/ns#">appharbor</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Getting deeper into Open Source</title><description>&lt;p&gt;It’s about 8 months since my &lt;a href="https://github.com/csainty/ravendb/commit/852a65cf300fa86a6ec69ee61f63b1841333bddf" target="_blank"&gt;first&lt;/a&gt; contribution to an open source project. It was followed up minutes later by one to reverse all the accidental formatting changes I made. Damn you Visual Studio!&lt;/p&gt; &lt;p&gt;I am happy to say that it was not an isolated contribution though.&lt;/p&gt; &lt;p&gt;Now I am by no means a prolific contributor and my spare time is more often spent tinkering with my own ideas and projects rather than working hard on open source. However, there has been a steady enough flow of pull requests and projects to keep me satisfied that I am at least involved.&lt;/p&gt; &lt;p&gt;&lt;a href="https://github.com/ravendb/ravendb" target="_blank"&gt;RavenDb&lt;/a&gt; and &lt;a href="https://github.com/NancyFx/Nancy" target="_blank"&gt;Nancy&lt;/a&gt; are where most of my focus has been. Two great examples of modern C# open source development.&lt;/p&gt; &lt;p&gt;In my own right there have been RavenDb plugins for &lt;a href="https://github.com/csainty/Glimpse.RavenDb" target="_blank"&gt;Glimpse&lt;/a&gt; and &lt;a href="https://github.com/csainty/MvcMiniProfiler.RavenDb" target="_blank"&gt;MvcMiniProfiler&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Straying from C# there is even a start being made on a &lt;a href="https://github.com/csainty/node-raven" target="_blank"&gt;Node.js client for RavenDb&lt;/a&gt;. Getting started with Node has been an absolute blast, and my first serious attempt at adding a new language to my skill set since C#. Sure I’ve dabbled with jQuery heavy javascript in the past to add a little life to a web page, but truly learning the object model and scoping rules of javascript is a different beast entirely.&lt;/p&gt; &lt;p&gt;Most recently, as in last week, I have been pitching in at &lt;a href="http://code52.org/" target="_blank"&gt;Code52&lt;/a&gt;, a new idea for this year which tackles a new project every week. It has been very .NET focussed so far, but that is simply a product of the founding core of developers having .NET backgrounds. At the end of the day, the people who are in the chat room at the start of each project are the ones who decide the technology stack. I hope to get them doing a Node project at some point this year.&lt;/p&gt; &lt;p&gt;The project from last week was &lt;a href="https://github.com/Code52/Ideastrike" target="_blank"&gt;IdeaStrike&lt;/a&gt; a UserVoice inspired (clone?) site that you can simply deploy to AppHarbor and manage yourself to track ideas and gather feedback about your product. You can see it in action at &lt;a href="http://ideastrike.apphb.com/"&gt;http://ideastrike.apphb.com/&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;It uses Nancy and Entity Framework. I wouldn’t call it a best practice example of either at the moment, it is tough to refactor a project that goes from start to finish in a week. It is however a good example of a non-trivial application, with (some) tests, in Nancy.&lt;/p&gt; &lt;p&gt;Even though the week is up, the project does not stop there. People are always welcome to fork, change, commit and send through a pull request.&lt;/p&gt; &lt;p&gt;A full list of previous projects, that will update over the year, can be found at &lt;a href="http://code52.org/projects.html"&gt;http://code52.org/projects.html&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;This week the focus is a cross-platform multiplayer game. Much further out of my comfort zone, but a great chance to learn some XNA, and eventually Android and iOS when those clients are added.&lt;/p&gt; &lt;p&gt;Now this is a fairly reflective post, not my usual style, but the point is really just to spread the word. There are lots of interesting projects around, big and small, in almost any language you care to use. Just pick one and jump in.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-2526950740026506989?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/TjXjhSLWyDk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/TjXjhSLWyDk/getting-deeper-into-open-source.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2012/01/getting-deeper-into-open-source.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-7459871213345928558</guid><pubDate>Mon, 16 Jan 2012 07:50:00 +0000</pubDate><atom:updated>2012-01-16T18:50:58.431+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">node</category><category domain="http://www.blogger.com/atom/ns#">node-webkit</category><title>Running a NodeJS server alongside your NodeJS desktop app</title><description>&lt;p&gt;The node-webkit project added a new feature yesterday, one which I requested. So I feel I should put up a quick post about it and why I think it could be useful.&lt;/p&gt; &lt;p&gt;The change was simple enough, giving you the ability to pass a callback to node-webkit that is called when the application is closing.&lt;/p&gt; &lt;p&gt;The primary reason I wanted this was to allow you to create, and then clean up, a local web server within the lifetime of your application.&lt;/p&gt; &lt;p&gt;It was previously possible to create the server, but when you closed the app, the process would stay open with the webserver waiting for requests.&lt;/p&gt; &lt;p&gt;The callback looks something like this.&lt;/p&gt; &lt;p&gt;&lt;script src="https://gist.github.com/1619653.js?file=app.js"&gt;&lt;/script&gt;&lt;/p&gt; &lt;p&gt;So why exactly is this useful? Well I have a couple of uses in mind.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Some libraries and UI controls have only been coded to fetch their data with an HTTP request. This gives you a simple way of using such a library or control. You just point it at the local server and handle the request.&lt;/li&gt; &lt;li&gt;If you did all data access across the HTTP layer, then you remove one more piece of uncommon code between a web and desktop application, now the difference between the two is just the URL it is pointing at.&lt;/li&gt; &lt;li&gt;It allows you to pre-process previously static files. This means you could compile your LESS or CoffeeScript files as they are being served. It also means you could serve HTML from a ViewEngine such as &lt;a href="http://jade-lang.com/" target="_blank"&gt;Jade&lt;/a&gt; instead of from static files on disk.&lt;/li&gt;&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-7459871213345928558?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/cKsNQID8olo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/cKsNQID8olo/running-nodejs-server-alongside-your.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2012/01/running-nodejs-server-alongside-your.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-5814689327629067619</guid><pubDate>Fri, 13 Jan 2012 00:47:00 +0000</pubDate><atom:updated>2012-01-13T11:47:43.628+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">node</category><category domain="http://www.blogger.com/atom/ns#">node-webkit</category><title>Further thoughts on NodeJS desktop applications</title><description>&lt;p&gt;I have been working on a more complete demo of creating a desktop app with NodeJS.&lt;/p&gt; &lt;p&gt;This one will use a full UI (&lt;a href="http://www.kendoui.com/" target="_blank"&gt;KendoUI&lt;/a&gt;) and a Sqlite database to create a basic CRUD style app based on the Northwind dataset. Someone really needs to put together another (and actually well designed) standard database that people can use for apps like this.&lt;/p&gt; &lt;p&gt;While putting this together I have been considering reasons why you might actually write an application like this.&lt;/p&gt; &lt;p&gt;Something that dawned on me is that I am only really using Node in a very thin data layer. My Views and View Models are all standard HTML/JS. Which means the only thing I would need to do to switch this application I am writing to being on the web would be to replace the data layer which is currently using Node to access Sqlite with one that goes across the network to a REST service.&lt;/p&gt; &lt;p&gt;This means I am effectively writing an identical web and desktop app at the same time. Which opens up some interesting offline capabilities.&lt;/p&gt; &lt;p&gt;Add a build time dependency injector to switch between the Node and REST data layers, and a synchronisation mechanism (assuming you want the user to be able to use either) and you have the web and desktop versions of your app running the exact same codebase.&lt;/p&gt; &lt;p&gt;Now that is pretty darn interesting.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-5814689327629067619?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/kcpHqQU2qno" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/kcpHqQU2qno/further-thoughts-on-nodejs-desktop.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2012/01/further-thoughts-on-nodejs-desktop.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-7724822284027989051</guid><pubDate>Tue, 10 Jan 2012 05:40:00 +0000</pubDate><atom:updated>2012-01-10T16:40:51.956+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">node</category><category domain="http://www.blogger.com/atom/ns#">node-webkit</category><category domain="http://www.blogger.com/atom/ns#">knockout</category><title>Creating desktop apps with NodeJS</title><description>&lt;p&gt;Last week an interesting thread was started on the NodeJS mailing list.&lt;/p&gt; &lt;p&gt;&lt;a title="https://groups.google.com/d/msg/nodejs/iy7Re33dwyU/yxwLlx1aUNMJ" href="https://groups.google.com/d/msg/nodejs/iy7Re33dwyU/yxwLlx1aUNMJ"&gt;https://groups.google.com/d/msg/nodejs/iy7Re33dwyU/yxwLlx1aUNMJ&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Roger Wang from the Intel Open Source Technology Center posted about a new project from their team called node-webkit.&lt;/p&gt; &lt;p&gt;&lt;a title="https://github.com/rogerwang/node-webkit" href="https://github.com/rogerwang/node-webkit"&gt;https://github.com/rogerwang/node-webkit&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;node-webkit brings WebKit to NodeJS. With it, client side applications&lt;br&gt;can be written with a HTML/CSS UI on NodeJS platform. We believe the&lt;br&gt;async I/O framework and Javascript language is a perfect combination for&lt;br&gt;client (mobile) side applications.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Basically it allows you to write HTML/JS/Node client side applications using webkit as the renderer.  &lt;p&gt;This is very interesting, and in some respects like the path Microsoft are taking with the HTML/JS WinRT in Windows 8.  &lt;p&gt;Currently this is Linux only. But with Node and WebKit both being cross-platform, it is only a matter of time until it gets onto other platforms.  &lt;p&gt;Getting started with a fresh Ubuntu 11.10 install in a VM I had to do the following to get it all installed.  &lt;ul&gt; &lt;li&gt;Open up a text editor and edit the file /etc/apt/sources.list  &lt;li&gt;Add a new line at the end “deb http://libwebkitnode.s3.amazonaws.com/ oneiric/”  &lt;li&gt;sudo apt-get update  &lt;li&gt;sudo apt-get install git-core nodejs-dev libwebkitnode-dev libev-dev  &lt;li&gt;git clone &lt;a title="https://github.com/rogerwang/node-webkit.git" href="https://github.com/rogerwang/node-webkit.git"&gt;https://github.com/rogerwang/node-webkit.git&lt;/a&gt;  &lt;li&gt;cd node-webkit  &lt;li&gt;node-waf configure build&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can then test it is running with “node tests/helloworld.js tests/testfs.html”&lt;/p&gt; &lt;p&gt;If everything goes to plan you, up should pop a window that lists the files in the current directory.&lt;/p&gt; &lt;p&gt;Take a look at the tests/testfs.html to see how they have done that.&lt;/p&gt; &lt;p&gt;Now on to my first test project. I am once again making a twitter search, it really is one of the easiest APIs around to quickly run up a test against.&lt;/p&gt; &lt;p&gt;All the below code is on github at &lt;a title="https://github.com/csainty/node-webkit-twitter" href="https://github.com/csainty/node-webkit-twitter"&gt;https://github.com/csainty/node-webkit-twitter&lt;/a&gt;&lt;/p&gt; &lt;p&gt;One note, I put a copy of the node-webkit into the node_modules folder. I am sure it will come to npm eventually, but for now this was the easiest method.&lt;br&gt;When I tried to reference it from it’s own folder, it could be found, but then my other dependencies couldn’t. I must be misunderstanding something there.&lt;/p&gt; &lt;p&gt;Our app.js is very simple, this is the entry point to the app, configures the webkit browser surface and loads an initial page.&lt;/p&gt;&lt;script src="https://gist.github.com/1587194.js?file=app.js"&gt;&lt;/script&gt; &lt;p&gt;index.html is also pretty straight forward, it is just basic HTML with Knockout bindings. It includes script references for jQuery, &lt;a href="http://csainty.blogspot.com/2011/10/learn-something-new-knockout-js.html" target="_blank"&gt;Knockout&lt;/a&gt; and our own index.js&lt;/p&gt;&lt;script src="https://gist.github.com/1587194.js?file=index.html"&gt;&lt;/script&gt; &lt;p&gt;Now for index.js, this is where the really interesting code is.&lt;/p&gt;&lt;script src="https://gist.github.com/1587194.js?file=index.js"&gt;&lt;/script&gt; &lt;p&gt;You can freely mix your traditional browser based HTML with your node.&lt;/p&gt; &lt;p&gt;So we call in our dependency on the &lt;a href="https://github.com/mikeal/request" target="_blank"&gt;request&lt;/a&gt; module. &lt;br&gt;We then use jQuery to delay our execution until the page is loaded. &lt;br&gt;We use Knockout to create our ViewModel which binds itself to the HTML.&lt;br&gt;Then in the search function on the ViewModel we call out to request to fetch the data from twitter.&lt;/p&gt; &lt;p&gt;Now of cource everything in this little demo can be done client side already. But I wanted to keep it simple, we can get to the filesystem (as the intel demo shows) and we can use existing libraries to get to a database or other persistence layer.&lt;/p&gt; &lt;p&gt;To fire it up just run “node app.js”&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-cfwDbp_TcvY/TwvPW5ZODHI/AAAAAAAAAJ8/-0LgIbO_aUE/s1600-h/Node%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Node" border="0" alt="Node" src="http://lh3.ggpht.com/-0J5hc-Bjch8/TwvPYASPxaI/AAAAAAAAAKE/-c45HL1kgN4/Node_thumb%25255B1%25255D.png?imgmax=800" width="375" height="282"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I hope to put together a more in-depth demo soon, one that involves local storage, and one of the HTML5 UI frameworks to pretty it up a bit. I’ll keep you posted on how that goes.&lt;/p&gt; &lt;p&gt;Remember I am on twitter these days as well &lt;a href="http://twitter.com/csainty" target="_blank"&gt;@csainty&lt;/a&gt;. So follow me there if you want to know what I am up to.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-7724822284027989051?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/xxyZdm4sJ2I" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/xxyZdm4sJ2I/creating-desktop-apps-with-nodejs.html</link><author>noreply@blogger.com (Chris Sainty)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-0J5hc-Bjch8/TwvPYASPxaI/AAAAAAAAAKE/-c45HL1kgN4/s72-c/Node_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2012/01/creating-desktop-apps-with-nodejs.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-7690078217695311605</guid><pubDate>Tue, 29 Nov 2011 22:32:00 +0000</pubDate><atom:updated>2011-11-30T09:32:21.472+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">nancy</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">appharbor</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">mongodb</category><category domain="http://www.blogger.com/atom/ns#">knockout</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Tutorial: Nancy + MongoDb + AppHarbor</title><description>&lt;p&gt;Time for a quick tutorial on how to get a site up and running on &lt;a href="https://appharbor.com/" target="_blank"&gt;AppHarbor&lt;/a&gt; using &lt;a href="http://www.nancyfx.org" target="_blank"&gt;Nancy&lt;/a&gt; and &lt;a href="http://www.mongodb.org/" target="_blank"&gt;MongoDb&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;First up you are going to need Git installed. On windows my preference for Git is this kit &lt;a title="http://code.google.com/p/gitextensions/" href="http://code.google.com/p/gitextensions/"&gt;http://code.google.com/p/gitextensions/&lt;/a&gt;. It installs everything you need and gives you a nice GUI to work with plus some basic integrations with Visual Studio.&lt;/p&gt;  &lt;p&gt;(Just in case you have missed the craze that is Git, it is a version control system. A very good one. Go learn about it)&lt;/p&gt;  &lt;p&gt;Next you will need &lt;a href="http://nuget.org/" target="_blank"&gt;NuGet&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;(In case you missed nuget, it is a package manager for .NET development. Use it to maintain third party libraries you are using in your applications)&lt;/p&gt;  &lt;p&gt;Finally, you are also going to need an account at &lt;a href="https://appharbor.com/user/new" target="_blank"&gt;AppHarbor&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;(In case you have missed AppHarbor, it is a new form of hosting for asp.net web applications. You push your code to their server, they build it, run your unit tests and then deploy it. From there you can scale the application and install add-ons etc.)&lt;/p&gt;  &lt;p&gt;The end result of this tutorial is the app hosted on AppHarbor here &lt;a href="http://nancymongo.apphb.com/"&gt;http://nancymongo.apphb.com/&lt;/a&gt; which is a basic message posting app that I have used before when playing around with Nancy. It super simple and boils down to two api methods with a page to interact with them.&lt;/p&gt;  &lt;p&gt;All the code is on GitHub here &lt;a title="https://github.com/csainty/NancyMongo" href="https://github.com/csainty/NancyMongo"&gt;https://github.com/csainty/NancyMongo&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;Setting up AppHarbor&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;p&gt;We are going to start with AppHarbor, once you have an account set up, go to the Applications page and create a new application.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Ty7ixR6Yv_I/TtVdDzdK0SI/AAAAAAAAAGs/6blzn8tHKX0/s1600-h/CreateAppHbApp2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="CreateAppHbApp" border="0" alt="CreateAppHbApp" src="http://lh4.ggpht.com/-MxwBBkQaBS4/TtVdE74H3LI/AAAAAAAAAGw/RKO6mxfmBmQ/CreateAppHbApp_thumb.png?imgmax=800" width="244" height="118" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This will give you the URL for your git repository where we will later be pushing the code. So keep this page open or the URL handy.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-lJyeMnovCMU/TtVdFfNHbYI/AAAAAAAAAG4/Fw-72ouSvN8/s1600-h/GitUrl2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="GitUrl" border="0" alt="GitUrl" src="http://lh6.ggpht.com/-wQ7p3-N4ORQ/TtVdGR1v2DI/AAAAAAAAAHA/5noX_OdiqbE/GitUrl_thumb.png?imgmax=800" width="244" height="79" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Down the bottom of this page is an Add-ons section. Hit “View Available Add-ons”&lt;/p&gt;  &lt;p&gt;As you can see there are quite a few, since we are using Mongo here, Click through to MongoHQ.&lt;/p&gt;  &lt;p&gt;MongoHQ are a hosted MongoDb provider, they are partnered up with AppHarbor so that it is a single click install to create an instance on their servers for your AppHarbor site. Even better, the build process on AppHarbor will perform a replacement on your web.config file to insert the correct URL to the instance. So you can have a development/testing server configured locally and when you push to the server it will switch to the production server for you!&lt;/p&gt;  &lt;p&gt;Add the free sandbox MongoDb instance to your site.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-3X6pXkTYZXI/TtVdHia9j5I/AAAAAAAAAHM/nMCSlSlXb-4/s1600-h/MongoHQ2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="MongoHQ" border="0" alt="MongoHQ" src="http://lh5.ggpht.com/-FO91lDhQBhE/TtVdJLuv5eI/AAAAAAAAAHQ/GYH0eXbtX50/MongoHQ_thumb.png?imgmax=800" width="244" height="166" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You should be sent back to the application page with a message saying your instance is configured. Now if you click through to the “Variables” tab you can see a MONGOHQ_URL variable. Any values set up in this tab will be added/replaced in the AppSettings section of your web.config file at build time.&lt;/p&gt;  &lt;p&gt;We are going to break with convention here a little. Normally you do not need to know the value of that key since it is the production server. But to save us setting up test/dev MongoDb instance on our own machines, we are going to point at it for development as well. There is some CSS on the page that truncates the value, but if you view source and search for mongodb:// you can get the full value.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-VWny3pVoo4E/TtVdJyawllI/AAAAAAAAAHY/tseLIbscWfU/s1600-h/MongoURL2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="MongoURL" border="0" alt="MongoURL" src="http://lh4.ggpht.com/-TDXoNjAaw-c/TtVdKaNRq_I/AAAAAAAAAHg/xiQjtrW2RfI/MongoURL_thumb.png?imgmax=800" width="244" height="27" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It includes your username, password and database name. So don’t go sharing this value, and if you are pushing your code to the public, make sure you remove it first, like I have.&lt;/p&gt;  &lt;p&gt;Keep that value at hand, it’s time to jump into Visual Studio.&lt;/p&gt;  &lt;h2&gt;Building our App&lt;/h2&gt;  &lt;p&gt;Create a new ASP.NET Empty Web Application.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-cBZ0d9NycqA/TtVdLTHgRKI/AAAAAAAAAHo/aUZYZlDU95o/s1600-h/EmptyWebApp2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EmptyWebApp" border="0" alt="EmptyWebApp" src="http://lh6.ggpht.com/-h2rOGfvLvHI/TtVdMuFGXrI/AAAAAAAAAH0/34rf3nHwAA8/EmptyWebApp_thumb.png?imgmax=800" width="244" height="30" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Fire up NuGet (either the GUI from right clicking the references folder in your project and choosing Manage NuGet Packages, or from the command line)&lt;/p&gt;  &lt;p&gt;Install the following packages by searching for them and hitting the install button&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Nancy &lt;/li&gt;    &lt;li&gt;Nancy.Hosting.AspNet &lt;/li&gt;    &lt;li&gt;KnockoutJS &lt;/li&gt;    &lt;li&gt;Official MongoDb C# driver &lt;/li&gt;    &lt;li&gt;NuGetPowerTools &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-sbmiSPnQr5s/TtVdNruhwGI/AAAAAAAAAH4/t4xm9lJybpY/s1600-h/NuGet2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="NuGet" border="0" alt="NuGet" src="http://lh3.ggpht.com/-iT8poC_To0U/TtVdOmnXWXI/AAAAAAAAAIA/TFNjuwZKH2s/NuGet_thumb.png?imgmax=800" width="244" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;One more thing with NuGet, we are going to need to jump into the NuGet “Package Manager Console” from the Tools menu | Library Package Manager sub-menu&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-fghvqD7wUDM/TtVdPlvZdjI/AAAAAAAAAII/ZDcA2Gx5YV8/s1600-h/Console2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Console" border="0" alt="Console" src="http://lh4.ggpht.com/-jp_HQZ74AyM/TtVdQvX8CeI/AAAAAAAAAIQ/QXnOeEEmrlQ/Console_thumb.png?imgmax=800" width="244" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Once the console loads type “enable-packagerestore” and hit enter.&lt;/p&gt;  &lt;p&gt;This command was added by the nugetpowertools and adds a build step into your project file that ensures all the nuget dependencies have been downloaded. This is very useful since you are not going to be uploading a compiled application to AppHarbor, you are sending up your source which is built on their servers. So you have to give them the dependencies some way, and the alternative is to commit them all to your git repository. Doing this bloats your repository for no good reason. Trust me, this step is worth doing on every project you use NuGet for.&lt;/p&gt;  &lt;p&gt;Once that completes you can close the package manager console.&lt;/p&gt;  &lt;p&gt;Now open you your web.config file and add an AppSetting of MONGOHQ_URL with the value you grabbed from AppHarbor.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-ywX1XAIaG9Y/TtVdRhVYupI/AAAAAAAAAIY/QW99u_7VBfY/s1600-h/webconfig2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="webconfig" border="0" alt="webconfig" src="http://lh3.ggpht.com/-7qzj0tKAYMs/TtVdSocPMzI/AAAAAAAAAIg/ZOmuFtcnn30/webconfig_thumb.png?imgmax=800" width="244" height="20" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Just to stress this point one more time, normally you are going to have a dev/test server. You would be putting it’s URL in here and letting AppHarbor override it with the production URL when you publish.&lt;/p&gt;  &lt;p&gt;Now on to some code, to start with add a Models folder with a single Message.cs class.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1403282.js?file=Message.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;Note the Attribute on the Id field, this tells the MongoDb driver which field is the Id and how to generate an Id for that field. There are many different options for Id generation, we are using one of the string methods.&lt;/p&gt;  &lt;p&gt;Now we are going to need a bootstrapper (CustomBootstrapper.cs) to configure Nancy and our Dependency Injection.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1403282.js?file=CustomBootstrapper.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;Bootstrappers are the starting point for all Nancy sites that do a bit more than Hello World.&lt;/p&gt;  &lt;p&gt;First we are adding the Scripts folder as a static content folder. This tells Nancy to automatically handle requests to the Scripts folder as static file requests. The Content folder is added by default, though we don’t use it in this project. There are a number of overrides on the builder we are using here to customise how the mapping works.&lt;/p&gt;  &lt;p&gt;Next we hook up Dependency injection on the various MongoDb driver classes we might want to get a handle on. This localises all our creation and init code so that our Modules can just request what they need and let the injection container provide it.&lt;/p&gt;  &lt;p&gt;Basically we are creating our Server instance using the connection string from web.config then pulling the database name off this connection string to grab out Database instance, we then create a Collection for our Messages to be stored in. The C# MongoDb driver actually manages it’s own object life time, so even if we called MongoServer.Create() multiple times we would always get back the same instance, but I still like to use Dependency Injection rather than have to create these time and time again in my module code.&lt;/p&gt;  &lt;p&gt;So let’s look at the two Modules (PageModule.cs and ApiModule.cs)&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1403282.js?file=PageModule.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1403282.js?file=ApiModule.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;A Module in Nancy is where we wire up how the web server is going to response to requests. I cover it off in &lt;a href="http://csainty.blogspot.com/2011/10/learn-something-new-nancy.html" target="_blank"&gt;this&lt;/a&gt; blog post as well. We inject the Messages collection straight into our Api module without having to worry about how it is being created, or what it’s lifetime is.&lt;/p&gt;  &lt;p&gt;Then finally we have the View (Views/Homepage.html), which is essentially a static HTML page and is processed by the built in view engine.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1403282.js?file=HomePage.html"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;So now we have all the code files in place, run it up and make sure it all works, when it does, it is time to deploy.&lt;/p&gt;  &lt;h2&gt;Creating our Git Repo&lt;/h2&gt;  &lt;p&gt;Now we have a working project, lets put it into Git and send it up to AppHarbor.&lt;/p&gt;  &lt;p&gt;Fir up the GitExtensions GUI and select “Create new repository”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-5usKwypguPc/TtVdTSDDN8I/AAAAAAAAAIo/qWqolHXPakQ/s1600-h/New-Repository2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="New Repository" border="0" alt="New Repository" src="http://lh3.ggpht.com/-s4Kzmjw_16k/TtVdUUZMr6I/AAAAAAAAAI0/jIrDVEIkH_s/New-Repository_thumb.png?imgmax=800" width="175" height="115" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Choose the folder your solution is in and Initialize as a personal repo. (Pro tip: Init a bare repository in your dropbox/mesh folder and push to it for easy offsite backup)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-79pt8rsAnR0/TtVdVribpNI/AAAAAAAAAI4/IPddQ0zSn2I/s1600-h/New-Repository-Location2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="New Repository Location" border="0" alt="New Repository Location" src="http://lh6.ggpht.com/-RSiVa2pEJ5U/TtVdWwU5jMI/AAAAAAAAAJE/Pk9QxmNa4ag/New-Repository-Location_thumb.png?imgmax=800" width="244" height="68" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now you need to edit your .gitignore folder to tell it what files to include and exclude from your folders.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-bpYh7jQ5eJI/TtVdYNmtFiI/AAAAAAAAAJI/rNPRcSAagG0/s1600-h/GitIgnore2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="GitIgnore" border="0" alt="GitIgnore" src="http://lh4.ggpht.com/-dYUrU3J49i4/TtVdZLlKMrI/AAAAAAAAAJQ/pmGXASNfmOA/GitIgnore_thumb.png?imgmax=800" width="244" height="210" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Start by hitting the “Add default” button, remove the *.exe line as we want to include the nuget.exe which was added by NuGetPowerTools. Then add a line “[P]ackages\” at the bottom to filter out the packages folder. This folder contains all the NuGet packages which will be downloaded on the AppHarbor build server by NuGetPowerTools.&lt;/p&gt;  &lt;p&gt;Now you should be able to Commit the changes from the Commands menu.&lt;/p&gt;  &lt;h2&gt;Deploying to AppHarbor&lt;/h2&gt;  &lt;p&gt;Still in GitExtensions, from the Remotes menu choose “manage remote repositories”, click the new button, give it a name and paste in the Git url you were provided when creating your AppHarbor application. Remotes are simply other copies of a repository that you can push code to and pull code from.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-no_NyWMsm7I/TtVdZwDhDwI/AAAAAAAAAJY/ErUQ_320iuk/s1600-h/Remote2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Remote" border="0" alt="Remote" src="http://lh6.ggpht.com/-DZP62nt063w/TtVda0ldirI/AAAAAAAAAJg/nV8CvQviKYA/Remote_thumb.png?imgmax=800" width="244" height="106" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You can then “Push” to this remote (again from the commands menu), which will being the build and deployment process on AppHarbor.&lt;/p&gt;  &lt;p&gt;One thing to watch out for, with OpenSSH selected as your SSH client (chosen when installing Git Extensions) you will have a black window pop up during the push, this is actually asking you for your AppHarbor password, type it in, or right-click and paste (Dont Ctrl-V) and press enter. Not sure what happens if you are using PuTTY.&lt;/p&gt;  &lt;p&gt;If I get a chance I hope to look into the GitExtensions code and improve this if at all possible.&lt;/p&gt;  &lt;h2&gt;It Lives!&lt;/h2&gt;  &lt;p&gt;Now if you go back to your application page in AppHarbor and refresh you should be presented with something like this.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-DWdEMutFlwA/TtVdbgl2P0I/AAAAAAAAAJo/FMAU_xks-dk/s1600-h/PostBuild2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="PostBuild" border="0" alt="PostBuild" src="http://lh3.ggpht.com/-E7rVG5tZL3U/TtVdcijXSqI/AAAAAAAAAJw/s10baZP37E8/PostBuild_thumb.png?imgmax=800" width="244" height="110" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will have the status of your build, which you can dig into to get the full console output from the build process. Assuming the build worked, you will also have a link to your app. Click it and be amazed.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-7690078217695311605?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/G7MZCgCDnrQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/G7MZCgCDnrQ/tutorial-nancy-mongodb-appharbor.html</link><author>noreply@blogger.com (Chris Sainty)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-MxwBBkQaBS4/TtVdE74H3LI/AAAAAAAAAGw/RKO6mxfmBmQ/s72-c/CreateAppHbApp_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/11/tutorial-nancy-mongodb-appharbor.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-1389607301571265426</guid><pubDate>Thu, 27 Oct 2011 05:52:00 +0000</pubDate><atom:updated>2011-10-27T16:52:07.788+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">node</category><category domain="http://www.blogger.com/atom/ns#">learn something new</category><category domain="http://www.blogger.com/atom/ns#">heroku</category><title>Learn Something New: Node</title><description>&lt;p&gt;&lt;a href="http://nodejs.org/" target="_blank"&gt;Node&lt;/a&gt; seems to be everywhere at the moment. Long on my list of things to take a look at, I finally took the time to sit down with it yesterday and get it up and running and get a feel for what it does.&lt;/p&gt;  &lt;p&gt;In the process I also took my first look at &lt;a href="http://www.heroku.com/" target="_blank"&gt;Heroku&lt;/a&gt;, which is the cloud hosting platform for Ruby, Node, Java etc.&amp;#160; that &lt;a href="https://appharbor.com/" target="_blank"&gt;AppHarbor&lt;/a&gt; borrows heavily from in the .NET world.&lt;/p&gt;  &lt;p&gt;As always, my code is on &lt;a href="https://github.com/csainty/Node.Test" target="_blank"&gt;GitHub&lt;/a&gt;, and the site is live on &lt;a href="http://blooming-mist-4131.herokuapp.com/" target="_blank"&gt;Heroku&lt;/a&gt;. This sample is literally a Hello World, with so many moving parts, I really wanted to just focus on the raw details of getting Node running first in a Linux VM, then on Windows, then on Heroku.&lt;/p&gt;  &lt;p&gt;Both Node and Heroku provide great instructions to get everything up and running, so they should be your first port of call.&lt;/p&gt;  &lt;p&gt;&lt;a title="https://github.com/joyent/node/wiki/Installation" href="https://github.com/joyent/node/wiki/Installation"&gt;https://github.com/joyent/node/wiki/Installation&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://devcenter.heroku.com/articles/node-js" href="http://devcenter.heroku.com/articles/node-js"&gt;http://devcenter.heroku.com/articles/node-js&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;With how easy Node is to get running on Windows now, there really is no excuse not to give it a go.&lt;/p&gt;  &lt;p&gt;Simply download the stand-alone node.exe from &lt;a href="http://nodejs.org/dist/v0.5.9/node.exe" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Put it in a folder, and create a HelloWorld.js file with the following content.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1318857.js?file=HelloWorld.js"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;Then run &lt;font face="Courier New"&gt;node HelloWorld.js &lt;/font&gt;and hit &lt;a href="http://localhost:8080/"&gt;http://localhost:8080/&lt;/a&gt; in your browser.&lt;/p&gt;  &lt;p&gt;At it’s heart, Node is about IO and sockets. It is not specifically about the web, people have just seen how useful it can be for web development.&lt;/p&gt;  &lt;p&gt;Before you get too far into it, you are likely to want to start plugging in some other packages, such as a routing framework to manage your requests and a view engine to render your HTML&amp;gt; &lt;/p&gt;  &lt;p&gt;This is where the Node Package Manager (&lt;a href="http://npmjs.org/" target="_blank"&gt;npm&lt;/a&gt;) comes in. The node install instructions linked above explain how to install this on windows, which has been seamless for me so far.&lt;/p&gt;  &lt;p&gt;You probably want to look at &lt;a href="http://expressjs.com/" target="_blank"&gt;express&lt;/a&gt; for the general framework roles and &lt;a href="http://jade-lang.com/" target="_blank"&gt;jade&lt;/a&gt; for a view engine.&lt;/p&gt;  &lt;p&gt;Another recent blog post I will call out to take a look at is &lt;a href="http://weblogs.asp.net/jgalloway/archive/2011/10/26/using-node-js-in-an-asp-net-mvc-application-with-iisnode.aspx" target="_blank"&gt;Jon Galloway’s&lt;/a&gt; effort today which includes a lot of detail and goes into hosting the node.exe process inside IIS on windows servers.&lt;/p&gt;  &lt;p&gt;I had a real sense of joy when I fired up Node and started fiddling around. I am fairly comfortable in javascript, and going back into a straight text editor to write my code was a bit like stepping back in time to my teenage years hacking away in qbasic. While my initial investigations were only skin deep, I definitely see myself taking a much deeper look very soon.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-1389607301571265426?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/JGpS_mhPO6o" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/JGpS_mhPO6o/learn-something-new-node.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/learn-something-new-node.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-9217094306162452044</guid><pubDate>Mon, 24 Oct 2011 23:44:00 +0000</pubDate><atom:updated>2011-10-25T10:44:44.023+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><title>My Windows Phone 7 thinks it is developer locked?</title><description>&lt;p&gt;I ran into an interesting problem today that warrants a blog post to hopefully help someone searching when they hit it themselves.&lt;/p&gt;  &lt;p&gt;Last night, I turned on my phone only to be greeted with a helpful message informing me that my application gReadie had been revoked by Microsoft and that I should uninstall it.&lt;/p&gt;  &lt;p&gt;After a moment of panic, I realised that I didn’t actually have a retail copy of gReadie installed on my phone, just the developer build I had been working on. So I didn’t think a lot more about it intending just to copy a new version on when I arrived at the office this morning.&lt;/p&gt;  &lt;p&gt;That plan failed though when Visual Studio informed me my device was developer locked, and I could not deploy my application.&lt;/p&gt;  &lt;p&gt;Strange.&lt;/p&gt;  &lt;p&gt;So I ran the developer unlock tool, it connected to App Hub, then to my device and said my phone was unlocked again. Great, back into Visual Studio, and up pops the same error.&lt;/p&gt;  &lt;p&gt;After a quick tweet to vent my frustration, I gave everything a reboot, unlocked again, and still no luck.&lt;/p&gt;  &lt;p&gt;At this point I logged into App Hub, to check my registration was still valid and see what was up with my device. &lt;/p&gt;  &lt;p&gt;To do this, click you name in the top right corner, then choose the devices tab.&lt;/p&gt;  &lt;p&gt;Bingo!&lt;/p&gt;  &lt;p&gt;Chris’ Phone, Registered 24th Oct 2010, Expiration Date&amp;#160; 24th Oct 2011.&lt;/p&gt;  &lt;p&gt;My unlock registration had expired, and the phone unlock tool shipped with the phone tools does not renew it.&lt;/p&gt;  &lt;p&gt;So I simply hit the remove button inside App Hub, went through the unlock tool once more, and everything was working again.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So keep this in mind as you approach your one year anniversary of owning an unlocked WP7 device. You will need to pop into App Hub and renew the unlock registration yourself.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-9217094306162452044?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/ezYJreP4t5I" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/ezYJreP4t5I/my-windows-phone-7-thinks-it-is.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>1</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/my-windows-phone-7-thinks-it-is.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-4565660389989239767</guid><pubDate>Wed, 12 Oct 2011 00:47:00 +0000</pubDate><atom:updated>2011-10-12T11:47:27.553+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">personal</category><title>I’m now on Twitter</title><description>&lt;p&gt;Just a quick FYI to let people know I am now on Twitter with my own account &lt;a href="http://www.twitter.com/csainty" target="_blank"&gt;@csainty&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Up until now I have been using the &lt;a href="http://www.twitter.com/quidsmobile" target="_blank"&gt;@quidsmobile&lt;/a&gt; account for a mix of personal comments and supporting gReadie. It will go full-time WP7 app support now.&lt;/p&gt;  &lt;p&gt;All my blog posts will be announced on my new personal account, along with other little comments on programming and tech.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-4565660389989239767?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/Zrxii1zeAlk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/Zrxii1zeAlk/im-now-on-twitter.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/im-now-on-twitter.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-2667713463273702490</guid><pubDate>Mon, 10 Oct 2011 10:27:00 +0000</pubDate><atom:updated>2011-10-12T12:02:04.426+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">nancy</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">learn something new</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">knockout</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Learn Something New: Nancy</title><description>Today my toolset of choice for a quick learning session is Nancy. &lt;br /&gt;
&lt;br /&gt;
Reading straight from the box “Nancy is a lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono. The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions”.&lt;br /&gt;
&lt;br /&gt;
Got that? Think of it as a replacement for WebForms or ASP.NET MVC.&lt;br /&gt;
&lt;br /&gt;
Nancy is available in &lt;a href="http://nuget.org/List/Packages/Nancy" target="_blank"&gt;NuGet&lt;/a&gt; or on &lt;a href="https://github.com/NancyFx/Nancy" target="_blank"&gt;GitHub&lt;/a&gt; if you want the source and docs. The docs are well worth a look over, and you are bound to need the aid of a sample project as you find your feet. Having said that, it is really quite simple so you should be up to speed in no time.&lt;br /&gt;
&lt;br /&gt;
These posts are not supposed to be walkthroughs, so I won’t go into detail getting you started other than to say that you start with an “ASP.NET Empty Web Application”, add the Nancy bits from NuGet (grab the &lt;a href="http://nuget.org/List/Packages/Nancy.Hosting.Aspnet" target="_blank"&gt;AspNet&lt;/a&gt; hosting package and &lt;a href="http://nuget.org/List/Packages/Nancy.Viewengines.Razor" target="_blank"&gt;Razor view engine&lt;/a&gt; as well for simplicity), create a subclass of NancyModule and away you go.&lt;br /&gt;
&lt;br /&gt;
You can see my demo live at &lt;a href="http://nancydemo-1.apphb.com/" title="http://nancydemo-1.apphb.com/"&gt;http://nancydemo-1.apphb.com/&lt;/a&gt; and grab the source from &lt;a href="https://github.com/csainty/NancyDemo" title="https://github.com/csainty/NancyDemo"&gt;https://github.com/csainty/NancyDemo&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Where I think Nancy really shines is writing an API / REST service. As the box says, there is so little ceremony that you never feel like you are fighting the framework to perform simple tasks. Even in ASP.NET MVC I find this sort of thing a little clunky feeling. As for WebForms, I did my best to avoid them altogether.&lt;br /&gt;
&lt;br /&gt;
My sample site performs the simple task of allowing the user to type in a message, saving it away and displaying it to other users on the site. All this is handled with a single page and some javascript. Using &lt;a href="http://csainty.blogspot.com/2011/10/learn-something-new-knockout-js.html" target="_blank"&gt;Knockout&lt;/a&gt; JS again.&lt;br /&gt;
&lt;br /&gt;
The interesting code in this project mainly lies in the Modules.&lt;br /&gt;
First we have a PageModule, which is serving requests for regular pages.&lt;br /&gt;
&lt;script src="https://gist.github.com/1274998.js?file=PageModule.cs"&gt;
&lt;/script&gt;&lt;br /&gt;
It really is as simple as that to catch requests to “/” and serve up a View in response.&lt;br /&gt;
&lt;br /&gt;
Second we have the ApiModule, which is handling the API requests being made by AJAX.&lt;br /&gt;
&lt;script src="https://gist.github.com/1274998.js?file=ApiModule.cs"&gt;
&lt;/script&gt;&lt;br /&gt;
Again, you can see that is very simple.&lt;br /&gt;
&lt;br /&gt;
To demonstrate Dependency Injection using Ninject, there is a simple data store interface and an in memory implementation.&lt;br /&gt;
&lt;script src="https://gist.github.com/1274998.js?file=CustomBootstrapper.cs"&gt;
&lt;/script&gt;&lt;br /&gt;
Here we are subclassing the Ninject bootstrapper, there are other implementations, and adding in the bindings we need.&lt;br /&gt;
&lt;br /&gt;
Of course I have barely scratched the surface here on a very intriguing project. I am hoping to put it to real use in something very soon.&lt;br /&gt;
&lt;h3&gt;

 Tools and Services Used&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://knockoutjs.com/"&gt;Knockout JS&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/NancyFx/Nancy"&gt;Nancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appharbor.com/"&gt;AppHarbor&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;  &lt;/li&gt;
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-2667713463273702490?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/rOeuZy6gVRY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/rOeuZy6gVRY/learn-something-new-nancy.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/learn-something-new-nancy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-1473986324507487925</guid><pubDate>Fri, 07 Oct 2011 14:07:00 +0000</pubDate><atom:updated>2011-10-12T12:00:11.888+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">mvc</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">learn something new</category><category domain="http://www.blogger.com/atom/ns#">knockout</category><title>Learn Something New: Knockout JS</title><description>First in my “Learn Something New” series is &lt;a href="http://knockoutjs.com/" target="_blank"&gt;Knockout&lt;/a&gt;, a javascript MVVM framework.&lt;br /&gt;
&lt;br /&gt;
Knockout is beautifully simplistic. You define a ViewModel, bind it to your UI, and away it goes keeping the two in sync. It really is beautiful stuff for a javascript heavy UI.&lt;br /&gt;
&lt;br /&gt;
To learn my way with Knockout, I decided to create a basic twitter search client in javascript. The twitter search API is a great resource for quickly adding data to a “hello world”-esque application. I am bound to revisit it later.&lt;br /&gt;
&lt;br /&gt;
Now let’s get a few more details out of the way, you can see the site up and running at &lt;a href="http://twitches.apphb.com/" title="http://twitches.apphb.com/"&gt;http://twitches.apphb.com/&lt;/a&gt; and you can get the source code at &lt;a href="https://github.com/csainty/Twitches" title="https://github.com/csainty/Twitches"&gt;https://github.com/csainty/Twitches&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The interesting code lives in the only &lt;a href="https://github.com/csainty/Twitches/blob/master/Twitches/Views/Home/Index.cshtml"&gt;View&lt;/a&gt;&amp;nbsp;and the &lt;a href="https://github.com/csainty/Twitches/blob/master/Twitches/Scripts/Site.js"&gt;Javascript&lt;/a&gt;.&lt;br /&gt;
The page basically consists of a textbox to enter a search term, a button to run the search and a UL that is bound to the results. There is some other fluff in there, but this is the core functionality.&lt;br /&gt;
&lt;br /&gt;
Here is a trimmed down version of the javascript to highlight the main features.&lt;br /&gt;
&lt;script src="https://gist.github.com/1270329.js?file=site.js"&gt;
&lt;/script&gt;&lt;br /&gt;
So we define our viewModel, give it an observable value for the search string, an observable array for the results and a function to perform the search.&lt;br /&gt;
We apply these bindings and that is it for the javascript. The actual binding to the UI happens in the UI, using HTML5 data attributes.&lt;br /&gt;
&lt;script src="https://gist.github.com/1270329.js?file=index.html"&gt;
&lt;/script&gt;&lt;br /&gt;
Here are the key elements from the HTML, as you can see we bind the UI with a jQuery.tmpl template, and wire up the value for the textbox and the click event for the button.&lt;br /&gt;
It really is as simple as that.&lt;br /&gt;
&lt;br /&gt;
I highly recommend the &lt;a href="http://learn.knockoutjs.com/" target="_blank"&gt;tutorials&lt;/a&gt; at the Knockout website, they have created a wonderful live tutorial that takes you through each step of the process.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;

Tools and Services Used&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://knockoutjs.com/"&gt;Knockout JS&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC / C#&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://combres.codeplex.com/"&gt;Combres&lt;/a&gt; (Javascript / CSS minifier and combiner)  &lt;/li&gt;
&lt;li&gt;&lt;a href="https://appharbor.com/"&gt;AppHarbor&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.twitter.com/docs"&gt;Twitter API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-1473986324507487925?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/-bDldX-OGVQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/-bDldX-OGVQ/learn-something-new-knockout-js.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/learn-something-new-knockout-js.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-1853255211659415768</guid><pubDate>Fri, 07 Oct 2011 13:14:00 +0000</pubDate><atom:updated>2011-10-08T00:14:37.593+11:00</atom:updated><title>Introducing the “Learn Something New” series</title><description>&lt;p&gt;Today I am introducing what I hope will be a long term project for this blog, my “Learn Something New” series.&lt;/p&gt; &lt;p&gt;The series will be mainly focussed on web development and learning the basics of a tool or framework I did not previously know. Where possible I will be providing all the source on GitHub and links to the project up and running on a free cloud service like AppHarbor or Heroku.&lt;/p&gt; &lt;p&gt;To set a few ground rules&lt;/p&gt; &lt;ul&gt; &lt;li&gt;These projects will not be “best practice”. Where possible I am trying to focus on a single new piece of kit and anything else will be kept at a minimum to make it work.  &lt;li&gt;Unless the post is about a UI tool, then there is likely to be no design work put into the project. See point 1, I am aiming for a quick turn around on each project. &lt;li&gt;These will be frameworks and tools I am new to, so I may make mistakes and I may do things the wrong way. If you see me doing that, I would be more than happy to hear from you and pointed in the right direction.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In the end this is some motivation and structure to my own learning. The blog gets to come along for the ride. So set your expectations appropriately and everything should be cool.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-1853255211659415768?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/c0dzg-aJ5-8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/c0dzg-aJ5-8/introducing-learn-something-new-series.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/introducing-learn-something-new-series.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-8735276358524795835</guid><pubDate>Wed, 05 Oct 2011 23:57:00 +0000</pubDate><atom:updated>2011-10-06T10:57:04.330+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Using ServiceStack.Text for JSON processing on Windows Phone 7</title><description>&lt;p&gt;I recently decided to switch gReadie away from JSON.Net to ServiceStack.Text for it’s heavy JSON processing of the Google Reader API.&lt;/p&gt;  &lt;p&gt;While there was no WP7 dll available in the NuGet package the source was all on GitHub, so using my recently learned Git skills, I forked the project and added my own project file targeted at WP7.&lt;/p&gt;  &lt;p&gt;It was then just a matter of visiting the various #if XBOX and #if SILVERLIGHT directives in the source and adding WINDOWS_PHONE as appropriate to enable and disable code for the platform.&lt;/p&gt;  &lt;p&gt;There are some differences between the SILVERLIGHT and WINDOWS_PHONE versions, as the project looks to target an older Silverlight implementation at the moment, which was turning off some of the performance gains that came from caching LINQ expression trees. So with those all enabled again the code compiles, is faster than JSON.Net for my use case and is now live in the latest version of gReadie.&lt;/p&gt;  &lt;p&gt;All my code changes have been pushed back up to my fork and are available at &lt;a title="https://github.com/csainty/ServiceStack.Text/tree/wp7" href="https://github.com/csainty/ServiceStack.Text/tree/wp7"&gt;https://github.com/csainty/ServiceStack.Text/tree/wp7&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I am yet to send a pull request back to the primary project, so for now you will need to grab my source and compile it yourself if you want to use it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-8735276358524795835?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/GNGKIOugEg4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/GNGKIOugEg4/using-servicestacktext-for-json.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>1</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/10/using-servicestacktext-for-json.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-5659380481264973808</guid><pubDate>Mon, 29 Aug 2011 01:24:00 +0000</pubDate><atom:updated>2011-08-29T11:24:54.674+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>WP7.5 Mango–Isolated Storage Explorer</title><description>&lt;p&gt;One of the most useful new tools with the latest Windows Phone SDK is the Isolated Storage Explorer.&lt;/p&gt;  &lt;p&gt;It is a command line tool used for downloading and uploading the contents of an application’s Isolated Storage folders to either the Emulator or a Device.&lt;/p&gt;  &lt;p&gt;There are two times when this is invaluable.&lt;/p&gt;  &lt;p&gt;The first is when you are deploying a new version and you do not want to lose the data. Since day one I have been annoyed with the frequency that that deployment mechanism decides to delete the application and reinstall it. By using this tool I never need to worry about that again as I can just save a snapshot, deploy, load the snapshot back in.&lt;/p&gt;  &lt;p&gt;The second is when I find a bug with while using a retail copy of my app which I can not hook the debugger into. I can take a snapshot, load it into the emulator and debug.&lt;/p&gt;  &lt;p&gt;To speed the process along I have created four windows .bat files that to perform each of the tasks I need.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1177519.js"&gt; &lt;/script&gt;&lt;/p&gt;  &lt;p&gt;To use these yourself you will need to adjust the path if you are not on a 64bit system, and you will need to replace the GUID with the value from your WMAppManifest file.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-5659380481264973808?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/i2Abr6cGklk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/i2Abr6cGklk/wp75-mangoisolated-storage-explorer.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>1</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/08/wp75-mangoisolated-storage-explorer.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-6040999243873799172</guid><pubDate>Wed, 24 Aug 2011 03:08:00 +0000</pubDate><atom:updated>2011-08-24T13:08:04.880+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Two lessons from a frustrating Mango submission</title><description>&lt;p&gt;I thought I would share two quick lessons today. Learnt while submitting the latest gReadie update to the marketplace.&lt;/p&gt;  &lt;h2&gt;Lesson 1&lt;/h2&gt;  &lt;p&gt;When updating an application in the marketplace, you can not remove supported languages. &lt;/p&gt;  &lt;p&gt;gReadie v1 has been translated into French and German (and unofficially Chinese) by enthusiastic users. gReadie v2 however has not yet had the same treatment.&lt;/p&gt;  &lt;p&gt;Even though gReadie v2 is a whole new application (File | New Project) it is being submitted as an update to gReadie v1 so that all current licenses are maintained.&lt;/p&gt;  &lt;p&gt;Therefore it must adhere to the rules for updates. One of which, I learnt today, is that you can not remove a language.&lt;/p&gt;  &lt;p&gt;With apologies to my French and German users, I had to rush together a mix of human translated (where I had the same text in v1) and Google translated values to get the app into the marketplace. I will do my best to reach out to the original translators and see if they are willing to provide an update for me.&lt;/p&gt;  &lt;p&gt;So keep this in mind if you are considering localising you application, you will need to do the same for all future versions.&lt;/p&gt;  &lt;h2&gt;Lesson 2&lt;/h2&gt;  &lt;p&gt;Be very careful what code is referenced by your Background Agent.&lt;/p&gt;  &lt;p&gt;There are a whole range of APIs that Background Agents can not access, and the code detection for this is fairly blunt. If you reference a class in a class library which has another class that calls the prohibited APIs, your application will fail during submission.&lt;/p&gt;  &lt;p&gt;To provide a more concrete example. gReadie is comprised of many separate class libraries. The two that caused me trouble were Quids.Infrastructure and gReadie.Library.&lt;/p&gt;  &lt;p&gt;Quids.Infrastructure is a bunch of helpers classes (for example code to string HTML tags from text) and some basic ViewModel and ViewPage classes that form the basis of the MVVM implementation used in gReadie.&lt;/p&gt;  &lt;p&gt;Even though my Background Agent just called into the string Extension Method that strips the HTML tags, the code that creates a PhoneApplicationPage was visible both in the ViewPage class and in the Silverlight Toolkit.&lt;/p&gt;  &lt;p&gt;gReadie.Library servers a similar role but more specific to gReadie, it has all the Google API interactions, User Settings and a bunch of other similar code. Included is the code that creates Live Tiles and the code that handles the ProgressIndicator and SystemTray. All of which is prohibited in Background Agents. So even though my agent was just getting at the API and Settings classes, all classes were interrogated and submission failed.&lt;/p&gt;  &lt;p&gt;So if you are building a Background Agent, and you want to share code between it and your main application be very careful about what else is in the shared libraries and be prepared to make UI and Non-UI shared libraries to deal with it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-6040999243873799172?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/IGN4_NqOuSs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/IGN4_NqOuSs/two-lessons-from-frustrating-mango.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>6</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/08/two-lessons-from-frustrating-mango.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-4232616768076069563</guid><pubDate>Fri, 19 Aug 2011 06:09:00 +0000</pubDate><atom:updated>2011-08-19T16:09:40.683+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">linqtosql</category><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Wp7.5 Mango–Background Agents</title><description>&lt;p&gt;Late last year when I implemented the unread count Live Tile in &lt;a href="http://www.quidsmobile.com/greadie/" target="_blank"&gt;gReadie&lt;/a&gt; I found myself stunned at just how complicated it was. It seemed to me that it would make a lot more sense if I could just whack a [LiveTileUpdater] attribute on a static method in a class and the phone would run that method occasionally.&lt;/p&gt;  &lt;p&gt;I was therefore delighted when details about Mango were released as this is basically what Microsoft implemented.&lt;/p&gt;  &lt;p&gt;Background Agents in Mango take the form of a separate assembly, which gets linked in your WMAppManifest.xml&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1156149.js?file=WMAppManifest.xml"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;You should also place a reference to this library in your main app just to make sure the compiler includes it in your .xap file.&lt;/p&gt;  &lt;p&gt;You Background Agent library should contain a class based on ScheduledTaskAgent which performs the actual tasks.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1156149.js?file=ScheduledAgent.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;There are two types of Background Agents, &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.periodictask.aspx" target="_blank"&gt;PeriodicTask&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.resourceintensivetask.aspx" target="_blank"&gt;ResourceIntensiveTask&lt;/a&gt;. Your app is allowed one of each.&lt;/p&gt;  &lt;p&gt;Full details are available &lt;a href="http://msdn.microsoft.com/en-us/library/hh202942.aspx" target="_blank"&gt;here&lt;/a&gt;, but the important parts are that PeriodicTasks run around every 30minutes and can only run for 15 seconds before being killed. ResourceIntensiveTasks run when the phone is plugged in, on wi-fi and charged to over 90% battery, they can run for 10 minutes.&lt;/p&gt;  &lt;p&gt;Finally your task should call either NotifyComplete() or Abort() when it is finished. Abort() will unschedule the task until your app runs again, so you only call it if something is wrong that needs user attention, such as login credentials changing.&lt;/p&gt;  &lt;p&gt;Now that is the good part of the story, there is one more restriction on Background Agents. They are only allowed 5MB of memory, regardless of whether they are Periodic or ResourceIntensive. If you go over this limit the task will be killed.&lt;/p&gt;  &lt;p&gt;Making a useful Background Agent that stays under these limits is incredibly difficult. Especially when so many of the basic framework components (HttPWebRequest, LINQ-to-SQL, IsolatedStorageSettings) appear to have memory leaks.&lt;/p&gt;  &lt;p&gt;From my testing you will lose about half your memory by the time you reach line 1. Your first HttpWebRequest will eat up another roughly 20%, which it never gives back, though multiple requests will stay inside that initial chunk. IsolatedStorageSettings will do a similar thing.&lt;/p&gt;  &lt;p&gt;LINQ-to-SQL is a little more complex, recycling your DataContext and &lt;a href="http://csainty.blogspot.com/2011/08/wp75-mangocompiled-queries.html" target="_blank"&gt;Compiled Queries&lt;/a&gt; will give some back, but recycling them too often will leak as well. So you need to find a nice balance.&lt;/p&gt;  &lt;p&gt;I suggest writing some code to monitor the memory usage between each job (assuming you have multiple to perform, say downloading multiple RSS feeds like gReadie does) and if you stray too high, then perform a garbage collection and recycle your LINQ-to-SQL and see how much you can get back. If it is not enough, then NotifyComplete() and try exit gracefully. It is not bullet-proof but in my testing it allows me to get more work done before running out of memory.&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1156149.js?file=MemoryCheck.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-4232616768076069563?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/WwifMo713E8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/WwifMo713E8/wp75-mangobackground-agents.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/08/wp75-mangobackground-agents.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-3157555770616581054</guid><pubDate>Wed, 17 Aug 2011 06:01:00 +0000</pubDate><atom:updated>2011-08-17T16:11:37.315+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">linqtosql</category><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>WP7.5 Mango–Compiled Queries</title><description>&lt;p&gt;Over the last few weeks I have been doing a complete rewrite of &lt;a href="http://www.quidsmobile.com/greadie-v2-beta/" target="_blank"&gt;gReadie&lt;/a&gt;, my Google Reader client for Windows Phone 7.&lt;/p&gt;  &lt;p&gt;The original codebase for gReadie was really quite cluttered, and I wasn’t going to be able to take advantage of the new features Mango enables without pulling it all out and starting again.&lt;/p&gt;  &lt;p&gt;With most of the rewrite behind me now, It is time to start putting together a few blog posts discussing the new features I am using and lessons learnt along the way.&lt;/p&gt;  &lt;p&gt;One of the features I was most looking forward to in the 7.5 release of the phone is developer access to the underling SQL CE database. Access is provided through LINQ-to-SQL, which I have covered in &lt;a href="http://csainty.blogspot.com/search/label/linqtosql" target="_blank"&gt;detail&lt;/a&gt; previously. What I want to focus on today is improving the performance of your queries by compiling them and caching that result.&lt;/p&gt;  &lt;p&gt;This post assumes you already have your DataContext created and working queries, if you do not, then please start by reading some of the Microsoft tutorials.&lt;/p&gt;  &lt;p&gt;When you make a query with LINQ-to-SQL, the LINQ provider has to examine your LINQ expression and turn it into SQL, this process is done on every query. However, if you have a query you know you are going to call multiple times then you can run this process once, saving a parameterized result and avoid having to do this step on subsequent calls.&lt;/p&gt;  &lt;p&gt;You define and call a Compiled Query like so&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1150888.js?file=CompiledQuery_NoParam.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;p&gt;The first step is to define a delegate that at the very least takes an instance of your DataContext as a parameter (though you can define more) and also defines the result type.&lt;/p&gt;  &lt;p&gt;You then use the CompiledQuery.Compile() method to provide the body for this delegate. The compilation does not happen until your first call, so don’t worry about setting up a lot of these.&lt;/p&gt;  &lt;p&gt;One thing to note is that you can only re-run a compiled query against the same DataContext instance it was compiled against. So you need to ensure they have the same lifespan, and that you are not needlessly recreating your DataContext if you want to run multiple queries.&lt;/p&gt;  &lt;p&gt;From my experience with Background Agents this method also uses less memory than rerunning the compilation each call.&lt;/p&gt;  &lt;p&gt;One final code snippet to show an example with a parameter&lt;/p&gt;  &lt;p&gt;&lt;script src="https://gist.github.com/1150888.js?file=CompiledQuery_Params.cs"&gt;&lt;/script&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-3157555770616581054?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/HhxVthWWqxY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/HhxVthWWqxY/wp75-mangocompiled-queries.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/08/wp75-mangocompiled-queries.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-157351919268260004</guid><pubDate>Tue, 12 Jul 2011 05:24:00 +0000</pubDate><atom:updated>2011-07-12T15:24:10.245+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">unittest</category><category domain="http://www.blogger.com/atom/ns#">mvc</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>ASP.NET MVC3 + Ninject + Moq + Unit Testing</title><description>&lt;p&gt;I answered a question on StackOverflow yesterday which I am pretty happy with, so I thought I would share the link on here.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://stackoverflow.com/questions/6646244/mvc-3-how-to-learn-how-to-test-with-nunit-ninject-and-moq/6646591#6646591" href="http://stackoverflow.com/questions/6646244/mvc-3-how-to-learn-how-to-test-with-nunit-ninject-and-moq/6646591#6646591"&gt;http://stackoverflow.com/questions/6646244/mvc-3-how-to-learn-how-to-test-with-nunit-ninject-and-moq/6646591#6646591&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The question asks for general advice on how to write and test an ASP.NET MVC 3 website that correctly uses Inversion-of-Control, Unit Testing and Mocking.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-157351919268260004?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/oBucGCpAUQk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/oBucGCpAUQk/aspnet-mvc3-ninject-moq-unit-testing.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/07/aspnet-mvc3-ninject-moq-unit-testing.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-5559930358189176459</guid><pubDate>Fri, 08 Jul 2011 11:58:00 +0000</pubDate><atom:updated>2011-07-08T21:58:02.755+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ravendb</category><category domain="http://www.blogger.com/atom/ns#">glimpse</category><category domain="http://www.blogger.com/atom/ns#">mvc</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>A RavenDb profiling plugin for Glimpse</title><description>&lt;p&gt;Today my post is to announce the release of a small plugin I have been working on over the last few days. It is a plugin for the &lt;a href="http://getglimpse.com/" target="_blank"&gt;Glimpse&lt;/a&gt; client side debug tool that integrates profiling information from &lt;a href="http://www.ravendb.net/" target="_blank"&gt;RavenDb&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The plugin is available on NuGet - &lt;a title="http://nuget.org/List/Packages/Glimpse.RavenDb" href="http://nuget.org/List/Packages/Glimpse.RavenDb"&gt;http://nuget.org/List/Packages/Glimpse.RavenDb&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The source is hosted on GitHub - &lt;a title="https://github.com/csainty/Glimpse.RavenDb" href="https://github.com/csainty/Glimpse.RavenDb"&gt;https://github.com/csainty/Glimpse.RavenDb&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Finally there are installation instructions - &lt;a title="https://github.com/csainty/Glimpse.RavenDb/wiki/How-to-use" href="https://github.com/csainty/Glimpse.RavenDb/wiki/How-to-use"&gt;https://github.com/csainty/Glimpse.RavenDb/wiki/How-to-use&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Links out of the way, how about a screenshot or two?&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-QYeTYW9LjT4/ThbwwPIzr2I/AAAAAAAAAGU/qHBJWcsUSng/s1600-h/Glimpse.RavenDb.1%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Glimpse.RavenDb.1" border="0" alt="Glimpse.RavenDb.1" src="http://lh3.ggpht.com/-dqOPds2bbWI/Thbww_jhY7I/AAAAAAAAAGY/X3jtludBamk/Glimpse.RavenDb.1_thumb.png?imgmax=800" width="244" height="48" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-lLG5ugty_ho/ThbwxgsblmI/AAAAAAAAAGc/8XKdWdM2rNA/s1600-h/Glimpse.RavenDb.2%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Glimpse.RavenDb.2" border="0" alt="Glimpse.RavenDb.2" src="http://lh3.ggpht.com/-PbNT-6DIsKQ/ThbwyJv4SmI/AAAAAAAAAGg/diTRXJz43Eo/Glimpse.RavenDb.2_thumb.png?imgmax=800" width="244" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;As you can see, the plugin adds a new tab to the Glimpse UI called RavenDb. On this tab you get information about the servers and sessions involved in the current request. You also get a list of the queries made against your RavenDb instances including the actual documents sent across the wire that you can drill into. It is really quite cool, and the Glimpse team have done a fantastic job creating a framework that is very simple to extend.&lt;/p&gt;  &lt;p&gt;The profiling tools in RavenDb are still young, and as ayende adds functionality (the current unstable builds include timing information currently missing in the stable release) I will update the plugin to bring all that goodness to the UI.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-5559930358189176459?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/Sxk9a1Ejkwc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/Sxk9a1Ejkwc/ravendb-profiling-plugin-for-glimpse.html</link><author>noreply@blogger.com (Chris Sainty)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-dqOPds2bbWI/Thbww_jhY7I/AAAAAAAAAGY/X3jtludBamk/s72-c/Glimpse.RavenDb.1_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/07/ravendb-profiling-plugin-for-glimpse.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-8023995134833538387</guid><pubDate>Wed, 22 Jun 2011 13:26:00 +0000</pubDate><atom:updated>2011-06-22T23:26:11.938+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ravendb</category><category domain="http://www.blogger.com/atom/ns#">mvc</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>RavenDB Profiling with ASP.NET MVC</title><description>&lt;p&gt;I have recently been using (and occasionally contributing to) &lt;a href="http://www.ravendb.net/" target="_blank"&gt;RavenDB&lt;/a&gt;, a NoSQL (or Document) database for .NET written by Oren Eini, aka &lt;a href="http://ayende.com" target="_blank"&gt;ayende&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;My biggest contribution yet has been to help with the basic &amp;quot;glue&amp;quot; to drive the new UI for profiling RavenDB requests in an ASP.NET MVC web application.&lt;/p&gt;  &lt;p&gt;There is a live demo up on Oren's blog right now, simply look for and click on the RavenDB Profiler box in the top left hand corner.&lt;/p&gt;  &lt;p&gt;If you are working with RavenDB and want to add this to your own project, it is really simple. As of right now you are going to need to grab an &lt;a href="http://builds.hibernatingrhinos.com/builds/ravendb-unstable" target="_blank"&gt;unstable build&lt;/a&gt;, at least 391. But these changes will make it into the stable builds soon enough.&lt;/p&gt;  &lt;p&gt;You then need to explicitly add a reference to Raven.Client.MvcIntegration to your project. There are security risks with showing the profiling data to just anyone, so you need to explicitly add the support.&lt;/p&gt;  &lt;p&gt;Next go to the code where you create your DocumentStore and pass a reference off to the profiler.&lt;/p&gt;  &lt;p align="left"&gt;&lt;font size="3" face="Times New Roman"&gt;Raven.Client.MvcIntegration.RavenProfiler.InitializeFor(myDocumentStore);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Finally in your master page &amp;lt;head&amp;gt; section add (assuming the Razor view engine)&lt;/p&gt;  &lt;p align="left"&gt;&lt;font size="3" face="Times New Roman"&gt;@Raven.Client.MvcIntegration.RavenProfiler.CurrentRequestSessions()&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The only other dependency is jQuery, if you are not already using jQuery you can add it off the Google CDN, or from Nuget.&lt;/p&gt;  &lt;p&gt;It is as simple as that, all the sessions and requests involved in producing your page will be visible for you to drill into. Also if your page makes any AJAX requests (using jQuery) these will be picked up and their sessions added to the results window! That was one of my contributions :)&lt;/p&gt;  &lt;p&gt;The profiler is still very much in it's early stages, there is a lot more to come yet, but the base is now firmly in place I believe and ready to be built on top of.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-8023995134833538387?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/FMU-Isra0NU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/FMU-Isra0NU/ravendb-profiling-with-aspnet-mvc.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/06/ravendb-profiling-with-aspnet-mvc.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-3005825471432915718</guid><pubDate>Mon, 10 Jan 2011 23:03:00 +0000</pubDate><atom:updated>2011-01-11T10:03:04.548+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>WP7 - Authenticated Push Notifications</title><description>&lt;p&gt;This post is going to offer a few tips about changing your Windows Phone 7 push notification service from unauthenticated to authenticated.&lt;/p&gt;  &lt;p&gt;Specifically it will focus on the challenges I ran into hosting a WCF service, in IIS7 on a cheap shared hosting account.&lt;/p&gt;  &lt;p&gt;It will not be a full step by step tutorial, there are a lot of those out there, though I found many missed a few steps. If you are starting out, see the &lt;a href="http://msdn.microsoft.com/en-us/library/ff941099.aspx" target="_blank"&gt;MSDN&lt;/a&gt; documentation.&lt;/p&gt;  &lt;p&gt;The reason you will want an authenticated service is that it allows you to send an unlimited amount of updates to the phone. If the service is not authenticated it will be limited to 500 per device per day. Which might be plenty for some services, but was not going to be enough for me. Users do not like their Live Tiles pausing for half a day simply because they are a heavy user.&lt;/p&gt;  &lt;p&gt;To authenticate your service, you need to add an SSL certificate to your web server and then upload a copy to your Windows Phone developer account. When it comes time to submit your application to the marketplace, you choose this certificate in the submission process and it becomes live in the Microsoft systems.&lt;/p&gt;  &lt;p&gt;Your hosting provider should have a standard process to do this, you just need to make sure they send you a copy of the certificate.&lt;/p&gt;  &lt;p&gt;The certificate I used came from &lt;a href="http://www.rapidssl.com/" target="_blank"&gt;RapidSSL&lt;/a&gt; and was just the default option for my hosting provider. Microsoft does have a list of &lt;a href="http://msdn.microsoft.com/en-us/library/gg521150.aspx" target="_blank"&gt;valid providers&lt;/a&gt;, so be sure to check.&lt;/p&gt;  &lt;h3&gt;Problem #1 - Adding an SSL endpoint to an IIS7 WCF Service&lt;/h3&gt;  &lt;p&gt;The first problem you will come up against is that when WCF generates a WSDL for your secure service, it will pick up the machine name of the box it is on, and not your domain name.&lt;/p&gt;  &lt;p&gt;This is a very widely talked about problem, and the usually offered solution is to run some vbs script that adds an SSL host header to your website because the IIS interface itself can not add host headers to SSL bindings.&lt;/p&gt;  &lt;p&gt;What is not very well talked about is how to manage this on shared hosting. As helpful as my support guy was, he was not keen on running some random piece of vbs script for me.&lt;/p&gt;  &lt;p&gt;So the real solution is actually to use a new (4.0) setting in the web.config file called &amp;quot;useRequestHeadersForMetadataAddress&amp;quot;, if you are not on a host that supports 4.0, find one that does.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;behaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;serviceBehaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;behavior&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;useRequestHeadersForMetadataAddress&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;defaultPorts&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;port&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;443&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;scheme&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;https&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;defaultPorts&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;useRequestHeadersForMetadataAddress&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;serviceMetadata&lt;/span&gt; &lt;span class="attr"&gt;httpGetEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;httpsGetEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;serviceDebug&lt;/span&gt; &lt;span class="attr"&gt;includeExceptionDetailInFaults&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;behavior&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;serviceBehaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;behaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;You also need to turn on Transport security for your binding. Though this is standard WCF, nothing special here.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;basicHttpBinding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;security&lt;/span&gt; &lt;span class="attr"&gt;mode&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Transport&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;basicHttpBinding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;On the phone, if you grab the metadata from your secure service, then it should point everything correctly, but if you need to do it by hand, the service configuration file will be along these lines.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.serviceModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;basicHttpBinding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                    &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;BasicHttpBinding_Service&amp;quot;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                    &lt;span class="attr"&gt;maxBufferSize&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;2147483647&amp;quot;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;                    &lt;span class="attr"&gt;maxReceivedMessageSize&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;2147483647&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;security&lt;/span&gt; &lt;span class="attr"&gt;mode&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Transport&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;basicHttpBinding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;client&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;endpoint&lt;/span&gt; &lt;span class="attr"&gt;address&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;https://[yourservicedomain]/[yourservicename].svc&amp;quot;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                            &lt;span class="attr"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;basicHttpBinding&amp;quot;&lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                            &lt;span class="attr"&gt;bindingConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;BasicHttpBinding_Service&amp;quot;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                            &lt;span class="attr"&gt;contract&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;[ContractName]&amp;quot;&lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                            &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;BasicHttpBinding_Service&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;client&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.serviceModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;



&lt;p&gt;Note the Transport security on line 8 and the https address on line 13.&lt;/p&gt;

&lt;h3&gt;Problem #2 - (403) Forbidden&lt;/h3&gt;

&lt;p&gt;The next problem you will encounter, is that when you actually POST your notification to the Microsoft servers you will get a (403) Forbidden response back.&lt;/p&gt;

&lt;p&gt;I could not find a single piece of Microsoft documentation on this, and a single obscure reference on a forum finally pointed me in the right direction.&lt;/p&gt;

&lt;p&gt;When you make your POST, you actually need to attach the certificate to it. Microsoft will then match this against the one you uploaded to them to ensure you are who you say you are.&lt;/p&gt;

&lt;p&gt;You do this using the ClientCertificates collection on your HTTP Request.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;// Standard header code&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;request.ClientCertificates.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; X509Certificate2(&lt;span class="str"&gt;&amp;quot;[Path To Certificate]&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;[Password]&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream requestStream = request.GetRequestStream()) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    requestStream.Write(payload, 0, payload.Length);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;WebResponse response = request.GetResponse();&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;



&lt;p&gt;Once this is added in you should be finally able to send authenticated push notifications.&lt;/p&gt;

&lt;p&gt;Hopefully this saves a few people some time as I pulled my hair out over the course of a weekend solving both of these.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-3005825471432915718?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/pl3HFxgAs88" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/pl3HFxgAs88/wp7-authenticated-push-notifications.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>6</thr:total><feedburner:origLink>http://csainty.blogspot.com/2011/01/wp7-authenticated-push-notifications.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-5945364718702986493</guid><pubDate>Fri, 22 Oct 2010 00:33:00 +0000</pubDate><atom:updated>2010-10-22T11:33:59.383+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><title>Windows Phone 7–Images</title><description>&lt;p&gt;Now about that Image Control. I mentioned in my last post that it seems to download on the UI thread, or at least block the UI thread while downloading.&lt;/p&gt;  &lt;p&gt;Personally I think this is going to be a major issue with v1 apps in the marketplace when used on 3G connections.&lt;/p&gt;  &lt;p&gt;It is actually a difficult thing to test, so here is the methodology I have been using and the code I am using to get around the issue.&lt;/p&gt;  &lt;p&gt;First you are going to want a local IIS server, put an image on the server, and then we are ready to go with the phone tools. We are later going to throttle the bandwidth on the server, if you do not have a local server you will need to find a way to throttle your network connection on the PC you are using. I am sure it is possible but have not looked at it.&lt;/p&gt;  &lt;p&gt;For this post I am just creating a basic Windows Phone Application, add the following XAML to the Grid in the MainPage.xaml and pop in your image URL.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&amp;lt;!--ContentPanel - place additional content here--&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;lt;Grid x:Name=&lt;span class="str"&gt;&amp;quot;ContentPanel&amp;quot;&lt;/span&gt; Grid.Row=&lt;span class="str"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; Margin=&lt;span class="str"&gt;&amp;quot;12,0,12,0&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &amp;lt;ScrollViewer&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        &amp;lt;StackPanel&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            &amp;lt;TextBlock Text=&lt;span class="str"&gt;&amp;quot;Above&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;            &amp;lt;Image Source=&lt;span class="str"&gt;&amp;quot;[Your Image URL]&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            &amp;lt;TextBlock Text=&lt;span class="str"&gt;&amp;quot;Below&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &amp;lt;/ScrollViewer&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now if you run this app, up will pop your image and you will be able to pan up and down since we are in a ScrollViewer.&lt;/p&gt;

&lt;p&gt;Now let’s see what happens on a slow connection, for this you will want to set a bandwidth throttle on your web server. In IIS 6 you do this from the Performance tab of the site properties. In IIS 7 go into Advanced Settings | Connection Limits | Maximum Bandwidth. I have been setting it to between 1 and 5 kBps. This should make the image take a few seconds to download.&lt;/p&gt;

&lt;p&gt;If we now run our application again (you will need to close the emulator and let it restart as it caches), before the image loads, try scroll the page. You should find that you can not, but then once the image loads you will be able to again. Now consider how that would appear to a user on a slow 3G connection if they had a page of images to load.&lt;/p&gt;

&lt;p&gt;So on to our fix.&lt;/p&gt;

&lt;p&gt;Add the following two classes to the project (changing the namespace as appropriate)&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ComponentModel;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Net;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Controls;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Media.Imaging;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; BlogImageApp&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ImageExtension&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetSource(DependencyObject obj) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)obj.GetValue(SourceProperty);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetSource(DependencyObject obj, &lt;span class="kwrd"&gt;string&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;            obj.SetValue(SourceProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        &lt;span class="rem"&gt;// Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty SourceProperty =&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            DependencyProperty.RegisterAttached(&lt;span class="str"&gt;&amp;quot;Source&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ImageExtension), &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyMetadata(SourceChange));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SourceChange(DependencyObject sender, DependencyPropertyChangedEventArgs e) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            Image imageControl = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; Image;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (imageControl == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; url = (&lt;span class="kwrd"&gt;string&lt;/span&gt;)e.NewValue &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (DesignerProperties.IsInDesignTool) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;                imageControl.Source = &lt;span class="kwrd"&gt;new&lt;/span&gt; BitmapImage(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(url, UriKind.Absolute));&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                HttpWebRequest request = HttpWebRequest.CreateHttp(url);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                request.AllowReadStreamBuffering = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;                request.BeginGetResponse(RequestComplete, &lt;span class="kwrd"&gt;new&lt;/span&gt; CallbackData { Request = request, ImageControl = imageControl });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RequestComplete(IAsyncResult result) {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            CallbackData data = (CallbackData)result.AsyncState;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            HttpWebResponse response = (HttpWebResponse)data.Request.EndGetResponse(result);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;            data.ResponseStream = response.GetResponseStream();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;            ((App)App.Current).RootFrame.Dispatcher.BeginInvoke(&lt;span class="kwrd"&gt;new&lt;/span&gt; Action&amp;lt;CallbackData&amp;gt;(x =&amp;gt; {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;                BitmapImage imagesource = &lt;span class="kwrd"&gt;new&lt;/span&gt; BitmapImage();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;                imagesource.SetSource(x.ResponseStream);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;                x.ImageControl.Source = imagesource;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;            }), data);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CallbackData&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; HttpWebRequest Request { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Image ImageControl { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Stream ResponseStream { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;What this code does is create a new attached property we can use on the Image control. When set it will download the image in the background and then set the source once it has downloaded. It would be fairly easy to hook this up to use a loading image in the meantime, but I have not done that here.&lt;/p&gt;

&lt;p&gt;A few interesting lines&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Line 31 – We check if we are in the designer and bypass all this if we are.&lt;/li&gt;

  &lt;li&gt;Line 35 – This is needed for when we set the image source. You will get an exception without it.&lt;/li&gt;

  &lt;li&gt;Line 36– I have, uncharacteristically for me, not used a lambda here. I decided in this case it was very difficult to read since I am passing a few bits of information around.&lt;/li&gt;

  &lt;li&gt;Line 44 – You need to create the BitmapImage on the UI thread, otherwise you get an exception.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this in place and the project recompiled we need to add a reference to the namespace in our MainPage.xaml. Add the following line to the &amp;lt;phone:PhoneApplicationPage&amp;gt; tag (again replacing the namespace as appropriate)&lt;/p&gt;

&lt;p&gt;xmlns:local=&amp;quot;clr-namespace:BlogImageApp&amp;quot;&lt;/p&gt;

&lt;p&gt;Then we can change our Image control and set the new attached property instead of the default Source property.&lt;/p&gt;

&lt;p&gt;&amp;lt;Image local:ImageExtension.Source=&amp;quot;[Your Image Url]&lt;a href="http://httest.ntl.quids.com.au/attach/Images/_43840B91-867E-44B3-AF0F-A7AE1634F3BC.jpg&amp;quot;"&gt;&amp;quot;&lt;/a&gt; /&amp;gt;&lt;/p&gt;

&lt;p&gt;Now run up the app, again after closing the emulator to clear the cache, and this time you should be able to scroll around to your heart’s content while waiting for the image to load.&lt;/p&gt;

&lt;p&gt;I have only used this code to download a couple of images at a time, if you had a page with dozens of images I would suggest working with only a couple of downloaders and queue work items for them, otherwise you might tie up too many resources and block the whole phone, not just the UI.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-5945364718702986493?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/hAdlZKWE6Qk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/hAdlZKWE6Qk/windows-phone-7images.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2010/10/windows-phone-7images.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-6088405555173488592</guid><pubDate>Wed, 20 Oct 2010 00:09:00 +0000</pubDate><atom:updated>2010-10-20T11:09:24.504+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wp7dev</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dotnet</category><title>Windows Phone 7–Asynchronous Programming</title><description>&lt;style type="text/css"&gt;

.csharpcode {
	overflow: scroll;
}

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;p&gt;I am going to start putting together some posts on my experience writing our first Windows Phone 7 application, &lt;a href="http://www.quidsmobile.com/gReadie/" target="_blank"&gt;gReadie&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;One thing that will strike you quickly if you go to make an app that communicates over the internet is that everything has to be done asynchronously. While this is bound to annoy at first, it is actually a good design decision by the development team because it forces the developer to keep the UI responsive. Sadly there is at least one instance where they broke their own rules but we will get to that another time, I will just say watch out for the Image control.&lt;/p&gt;  &lt;p&gt;My preferred way of handling asynchronous programing is with a callback structure that uses delegates/lambdas. You could also use events but I find most of the memory leaks I create in applications are to do with events and not releasing subscriptions. Luckily for us we now have lambdas that make callbacks a piece of cake to write, you just need to watch out for a few gotchas. If you prefer delegates to lambdas, then the second point here will not apply to you, but the first will still catch the very novice.&lt;/p&gt;  &lt;p&gt;I am going to put together an application that simply lists the top 10 trending topics on twitter. It is a simple easy to access api that will serve our purposes well.&lt;/p&gt;  &lt;p&gt;You can call up the api right now in your browser &lt;a href="http://api.twitter.com/1/trends.json"&gt;http://api.twitter.com/1/trends.json&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So we start with a new Windows Phone Pivot application, It comes prepopulated with a list control and a nice ViewModel structure that is a good base to work from.&lt;/p&gt;  &lt;p&gt;The first thing you will want to do is add a reference to System.Servicemodel.Web and another to System.Runtime.Serialization. These dlls contain the classes we need for parsing the JSON we get back from twitter. Next you will want to go into the LoadData method on the ViewModels\MainViewModel.cs class and comment out (or remove) all the sample data.&lt;/p&gt;  &lt;p&gt;Now we have an app that will load up and display nothing. Perfect.&lt;/p&gt;  &lt;p&gt;To parse the JSON we are going to need some classes to parse it into, and here they are.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[System.Runtime.Serialization.DataContract]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TrendsResult&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    [System.Runtime.Serialization.DataMember(Name = &lt;span class="str"&gt;&amp;quot;as_of&amp;quot;&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; AsOf { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    [System.Runtime.Serialization.DataMember(Name = &lt;span class="str"&gt;&amp;quot;trends&amp;quot;&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Trend[] Trends { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[System.Runtime.Serialization.DataContract]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Trend&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    [System.Runtime.Serialization.DataMember(Name = &lt;span class="str"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Url { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    [System.Runtime.Serialization.DataMember(Name = &lt;span class="str"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Put these where you like in the project (I use a JSON subfolder) and add using statements etc to your preferences. I am not going into details about JSON in this post so that is all you get for now sorry.&lt;/p&gt;

&lt;p&gt;With these in place we can now fill out our LoadData method and actually perform the request and parse the results. Filling out the Items collection already provided in the project template.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadData() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    HttpWebRequest request = HttpWebRequest.CreateHttp(&lt;span class="str"&gt;&amp;quot;http://api.twitter.com/1/trends.json&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    request.BeginGetResponse(result =&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        HttpWebResponse response = (HttpWebResponse)((HttpWebRequest)result.AsyncState).EndGetResponse(result);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        DataContractJsonSerializer s = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataContractJsonSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(TrendsResult));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        TrendsResult trends = (TrendsResult)s.ReadObject(response.GetResponseStream());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Trend trend &lt;span class="kwrd"&gt;in&lt;/span&gt; trends.Trends) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = trend.Name, LineTwo = trend.Url });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    }, request);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.IsDataLoaded = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now this code seems quite reasonable, assuming of course that you have learnt lambdas and can read it. We make a request, when it is done we pass the result text into the deserializer to create the objects we built above and then process these into the ViewModel.&lt;/p&gt;

&lt;p&gt;If you run it though, it will crash with the error “Invalid cross thread access” and this is the first lesson about callbacks. They do not fire on the UI thread and therefore they can not change the UI. But you may notice the callback doesn’t actually change the UI. It just adds an item to a collection. But because this collection it bound to the UI, when it changes it triggers events that change the UI.&lt;/p&gt;

&lt;p&gt;So the first thing we need to do is move the call that adds the item to the collection onto the UI thread. Luckily this is easy enough and involves another lambda! 
  &lt;br /&gt;We simply change the content of the foreach loop to be&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;((App)App.Current).RootFrame.Dispatcher.BeginInvoke(() =&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = trend.Name, LineTwo = trend.Url });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;});&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The key here is getting a handle on the Dispatcher. This is the class that controls the UI thread, there are a few ways you can get it, every page has a Dispatcher property, or if have Microsoft.Phone.Reactive.dll referenced then you can use the Scheduler class (my preferred way), or you can get at the App.RootFrame that is the parent UI object in the application which is what I have done above.&lt;/p&gt;

&lt;p&gt;From the Dispatcher you can pass in an Action (callback/delegate/lambda.. choose your own terminology) for the UI thread to execute.&lt;/p&gt;

&lt;p&gt;Now if you run this version up, you will notice that it works. Except hang on, all the trends are the same. Don’t worry you didn’t mess up the Json parsing, though this would be the first thought of many and they could waste a lot of time looking in the wrong direction.&lt;/p&gt;

&lt;p&gt;This brings us to the second lesson about callbacks and it goes to the way lambdas are actually compiled. Notice in line 2 above I reference trend.Name and trend.Url, but the trend object is not actually created inside the lambda, so think for a second about how it is in scope. If you took the content of the Lambda and turned it into a method/delegate (which is what the compiler does) that was called then it becomes clear that we have some trickery going on behind the scenes.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;((App)App.Current).RootFrame.Dispatcher.BeginInvoke(DoItemAdd);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoItemAdd() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = trend.Name, LineTwo = trend.Url });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;What the compiler does is add a field to the class, which it sets before the call and uses inside the method. So it would look something like this, you can see it in reflector if you like&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; Trend _Compiler_Trend;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadData() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    ...&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    _Compiler_Trend = trend;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    ((App)App.Current).RootFrame.Dispatcher.BeginInvoke(DoItemAdd);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    ...&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoItemAdd() {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = _Compiler_Trend.Name, LineTwo = _Compiler_Trend.Url });&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now it should be clearer what is happening here. BeginInvoke is asynchronous so our foreach loop keeps updating the _Compiler_Trend without waiting for the last call to DoItemAdd to be finished with it. Therefore when it does get around to running the DoItemAdd calls the field is in an unknown state.&lt;/p&gt;

&lt;p&gt;Luckily we also have a solution to this problem. The BeginInvoke call can also take an Action&amp;lt;T&amp;gt; and a parameter of generic type T to pass in when calling the code.&lt;/p&gt;

&lt;p&gt;So we can rewrite the method like this&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadData() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    HttpWebRequest request = HttpWebRequest.CreateHttp(&lt;span class="str"&gt;&amp;quot;http://api.twitter.com/1/trends.json&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    request.BeginGetResponse(result =&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        HttpWebResponse response = (HttpWebResponse)((HttpWebRequest)result.AsyncState).EndGetResponse(result);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        DataContractJsonSerializer s = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataContractJsonSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(TrendsResult));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        TrendsResult trends = (TrendsResult)s.ReadObject(response.GetResponseStream());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Trend trend &lt;span class="kwrd"&gt;in&lt;/span&gt; trends.Trends) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            ((App)App.Current).RootFrame.Dispatcher.BeginInvoke(&lt;span class="kwrd"&gt;new&lt;/span&gt; Action&amp;lt;ItemViewModel&amp;gt;(item =&amp;gt; {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(item);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            }), &lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = trend.Name, LineTwo = trend.Url });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    }, request);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.IsDataLoaded = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Only lines 8,9 and 10 are different. Now we are creating a lambda that takes a parameter of type ItemViewModel, adds that passed item into the collection and we give the dispatcher the item to pass in. If we run this code it works!&lt;/p&gt;

&lt;p&gt;If we pulled apart this code to see it like the compiler does it would look more like this, and I should note you can write your code this way if lambdas bend your mind that bit too much, but I personally find them much easier to read and manage.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadData() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    HttpWebRequest request = HttpWebRequest.CreateHttp(&lt;span class="str"&gt;&amp;quot;http://api.twitter.com/1/trends.json&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    request.BeginGetResponse(result =&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        HttpWebResponse response = (HttpWebResponse)((HttpWebRequest)result.AsyncState).EndGetResponse(result);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        DataContractJsonSerializer s = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataContractJsonSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(TrendsResult));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        TrendsResult trends = (TrendsResult)s.ReadObject(response.GetResponseStream());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Trend trend &lt;span class="kwrd"&gt;in&lt;/span&gt; trends.Trends) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            ((App)App.Current).RootFrame.Dispatcher.BeginInvoke(DoItemAdd, &lt;span class="kwrd"&gt;new&lt;/span&gt; ItemViewModel { LineOne = trend.Name, LineTwo = trend.Url });&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    }, request);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;.IsDataLoaded = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoItemAdd(ItemViewModel item) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Items.Add(item);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It should be clear now that there are no scope issues with this code.&lt;/p&gt;

&lt;p&gt;So there you have it, a twitter trend downloader that has hopefully pointed out a few things you should look out for when starting down the asynchronous path required by Windows Phone 7.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-6088405555173488592?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/HZo4Sput_lE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/HZo4Sput_lE/windows-phone-7asynchronous-programming.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>6</thr:total><feedburner:origLink>http://csainty.blogspot.com/2010/10/windows-phone-7asynchronous-programming.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-318836494810033488</guid><pubDate>Mon, 11 Oct 2010 11:43:00 +0000</pubDate><atom:updated>2010-10-11T22:43:34.837+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wp7</category><title>Quids Mobile</title><description>&lt;p&gt;I have set up a quick WordPress site today to host information about our mobile development separately to our main software site. I will also use it to post future updates rather than polluting my otherwise coding focussed blog.&lt;/p&gt;  &lt;p&gt;So for anyone interested in following the apps we create head over to &lt;a href="http://www.quidsmobile.com"&gt;www.quidsmobile.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I promise I will make my next post about something I have learnt on the new platform and get back onto a technology focus.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-318836494810033488?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/ZW_32yEjNzA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/ZW_32yEjNzA/quids-mobile.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2010/10/quids-mobile.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-7741490711876713057</guid><pubDate>Sat, 09 Oct 2010 05:06:00 +0000</pubDate><atom:updated>2010-10-09T16:07:30.398+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><title>Windows Phone 7 Marketplace–Early Access</title><description>&lt;p&gt;I received notification this morning that gReadie will be accepted into the early access program for the Windows Phone 7 Marketplace. So sometime Monday I will be logging in and submitting. Hopefully it also means the app will be in the marketplace from day 1.&lt;/p&gt;  &lt;p&gt;I recorded one last video that takes a run right through the app. I already have a huge list of features to go into future releases but the last few days have involved making sure the app is well tested and running as nicely as I can manage on the emulator. I am very keen to get a real device and see how it goes on there.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:ac643152-d216-403b-808c-647e4dccd781" class="wlWriterEditableSmartContent"&gt;&lt;div id="a8d35a0f-566f-40f9-ac83-eedb47554667" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;object width="448" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/I-VqU7N4s6I?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/I-VqU7N4s6I?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="336"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-7741490711876713057?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/Aescqij4z5c" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/Aescqij4z5c/windows-phone-7-marketplaceearly-access.html</link><author>noreply@blogger.com (Chris Sainty)</author><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2010/10/windows-phone-7-marketplaceearly-access.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-25631453.post-5041874375421898577</guid><pubDate>Wed, 06 Oct 2010 00:52:00 +0000</pubDate><atom:updated>2010-10-06T11:52:42.140+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gReadie</category><category domain="http://www.blogger.com/atom/ns#">wp7</category><title>Another gReadie Video</title><description>&lt;p&gt;I have posted another gReadie video to YouTube.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:8a366dc1-36e8-4c85-843c-fa4469b21b79" class="wlWriterEditableSmartContent"&gt;&lt;div id="e52b3af9-99cb-4515-b2f2-1b0ead30cc98" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=76peMOcUJNk&amp;amp;feature=youtube_gdata_player" target="_new"&gt;&lt;img src="http://lh6.ggpht.com/_NNjUBRB0uwA/TKvIWdmh0II/AAAAAAAAAF4/WGfvEUfNe8Q/videof5346eeef8f9%5B3%5D.jpg?imgmax=800" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('e52b3af9-99cb-4515-b2f2-1b0ead30cc98'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;object width=\&amp;quot;448\&amp;quot; height=\&amp;quot;252\&amp;quot;&amp;gt;&amp;lt;param name=\&amp;quot;movie\&amp;quot; value=\&amp;quot;http://www.youtube.com/v/76peMOcUJNk?hl=en&amp;amp;hd=1\&amp;quot;&amp;gt;&amp;lt;\/param&amp;gt;&amp;lt;embed src=\&amp;quot;http://www.youtube.com/v/76peMOcUJNk?hl=en&amp;amp;hd=1\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; width=\&amp;quot;448\&amp;quot; height=\&amp;quot;252\&amp;quot;&amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/object&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="width:448px;clear:both;font-size:.8em"&gt;gReadie–Sharing Preview&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;This video quickly shows off the services the app is now connected to.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25631453-5041874375421898577?l=csainty.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisSainty/~4/6O5Duptc7gc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/ChrisSainty/~3/6O5Duptc7gc/another-greadie-video.html</link><author>noreply@blogger.com (Chris Sainty)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_NNjUBRB0uwA/TKvIWdmh0II/AAAAAAAAAF4/WGfvEUfNe8Q/s72-c/videof5346eeef8f9%5B3%5D.jpg?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csainty.blogspot.com/2010/10/another-greadie-video.html</feedburner:origLink></item></channel></rss>

