SilverlightShow: Silverlight Community http://www.silverlightshow.net/ Silverlight articles, Silverlight tutorials, Silverlight videos, Silverlight samples SilverlightShow.net http://www.rssboard.org/rss-specification Argotic Syndication Framework 2008.0.2.0, http://www.codeplex.com/Argotic en-US estoychev@completit.com (Emil Stoychev) Windows Phone 8: Voice Commands <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx" data-count="horizontal" data-text="Check out @Mister_Goodcat's article: '#WindowsPhone8 - Voice Commands!' #wpdev #wp8" data-url="http://slshow.net/X62NaN">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>Part of the last article was a detailed look at the possibility of speech recognition from within your app. A logical continuation of this technology and feature is to seek deeper integration with the operating system by using voice commands. Voice commands are a way for you to register certain phrases with the Windows Phone OS that are recognized when the user invokes the built-in voice recognition, without your app being active or even launched. In this article I will explain what it takes to use this feature, and what you can achieve with it.</p> <h2>Voice Commands Explained</h2> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>Typically, your application will be used for a limited set of operations, with the same actions executed all the time. Let's say you have created some sort of news reader, then the most common action probably will be that the users launch the app, navigate to the unread items, and then start reading the new available content. If your app searches for points of interest in the local area, users will launch it, navigate to the search page and enter their search term, then look through the results. In all these situations, it can become quite annoying to perform these individual steps over and over again, even if it only requires a handful of taps and swipes. Wouldn't it be great to have shortcuts for this?</p> <p>One way to create those shortcuts on the phone is to use secondary tiles. These allow the user to pin commonly used pages or functionality of your app to their start screen, which then can be invoked directly, without e.g. going through an application's menu first. Secondary tiles are still quite limited and static though, in the sense that they do not provide a way to pass dynamically changing parameters to your application. This for example is something that can be achieved with voice commands.</p> <h3>Command Structure</h3> <p>As we have learned in the previous part [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx">1</a>] voice recognition is a very complex topic that requires a lot of computational power (which is why it is outsourced to external services), and it also has several implications depending e.g. on the language the user has set their phone to. To provide better recognition results, a common technique hence is to provide fixed phrases that the recognizer can understand more accurately. This is also the way voice commands work. To add more flexibility and make the commands less static, those phrases can be varied in wording slightly, or have variable placeholders. Let's take a look at a typical command as it can be used for voice commands on Windows Phone:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/command_2.png"><img title="command" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="command" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/command_thumb.png" width="477" height="191" /></a></p> <p>The matching algorithm for voice commands expects an identifier that is used to match commands to a particular app. It's important to make that identifier unique to your app so it cannot be confused with other apps or even built-in voice commands of the phone. Obviously though you would want to make the command your app's title or similar. The actual phrase then is compared to the phrases defined by the app to determine what command should actually be invoked. Let's take a look at the decomposition of that command itself:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/phrase_2.png"><img title="phrase" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="phrase" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/phrase_thumb.png" width="263" height="213" /></a>After matching the command to your app, the amount of possible matches for the phrase has narrowed down tremendously already (only phrases defined in your app will be recognized). To aid further in the recognition process, in this case "poke … gorillas" is a static, fixed part defined for recognition. The only degrees of freedom for the recognizer now are optional words like "and" as well as true dynamic values that can take one of a set of values that you can freely define and change over time. In the following paragraphs I'll explain how this translates into the technical details for Windows Phone developers.</p> <h2>Voice Commands on Windows Phone</h2> <p>To enable your app for voice commands, you need to specify the "ID_CAP_SPEECH_RECOGNITION" capability in your manifest, just as explained in the last part [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx">2</a>]. You don't need the microphone capability until of course you plan on using speech recognition from within your app also.</p> <p>Once set up, you can start with voice commands right away and very easily by adding a new xml file that holds the required definitions. To get you started, an item template for voice command definitions is provided for you:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/new_voice_command_definition_2.png"><img title="new_voice_command_definition" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="new_voice_command_definition" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/new_voice_command_definition_thumb.png" width="640" height="442" /></a></p> <p>The content of a file that can process the above sample command looks like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd"><?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="kwrd"><</span><span class="html">VoiceCommands</span> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/voicecommands/1.0"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">CommandSet</span> <span class="attr">xml:lang</span><span class="kwrd">="en-US"</span> </pre> <!--CRLF--> <pre class="alt"> <span class="attr">Name</span><span class="kwrd">="DefaultCommandSet"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">CommandPrefix</span><span class="kwrd">></span>Gorilla Garden<span class="kwrd"></</span><span class="html">CommandPrefix</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">Example</span><span class="kwrd">></span>poke 3 gorillas<span class="kwrd"></</span><span class="html">Example</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">Command</span> <span class="attr">Name</span><span class="kwrd">="PokeGorilla"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">Example</span><span class="kwrd">></span> poke 3 gorillas <span class="kwrd"></</span><span class="html">Example</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">ListenFor</span><span class="kwrd">></span> [and] poke {number} gorillas <span class="kwrd"></</span><span class="html">ListenFor</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">ListenFor</span><span class="kwrd">></span> [and] poke [a] gorilla <span class="kwrd"></</span><span class="html">ListenFor</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">Feedback</span><span class="kwrd">></span> Poking gorillas... <span class="kwrd"></</span><span class="html">Feedback</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">Navigate</span> <span class="attr">Target</span><span class="kwrd">="Gorillas.xaml"</span> <span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"></</span><span class="html">Command</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">PhraseList</span> <span class="attr">Label</span><span class="kwrd">="number"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">Item</span><span class="kwrd">></span> 1 <span class="kwrd"></</span><span class="html">Item</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"><</span><span class="html">Item</span><span class="kwrd">></span> 2 <span class="kwrd"></</span><span class="html">Item</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd"><</span><span class="html">Item</span><span class="kwrd">></span> 3 <span class="kwrd"></</span><span class="html">Item</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"></</span><span class="html">PhraseList</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="kwrd"></</span><span class="html">CommandSet</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="kwrd"></</span><span class="html">VoiceCommands</span><span class="kwrd">></span></pre> <!--CRLF--></div> </div> <p>One of the important details is to provide a "Name" attribute for your command sets. This unfortunately is not added by default in the template, so make sure to do that manually. If a command set does not have a name, you cannot programmatically access it, and it is also not accounted for when you try to e.g. read the number of command sets that you have already installed on the phone.</p> <p>Another detail to note is that each command set is associated with a language, in this case US-English. This allows you to specify different commands for all the different languages you expect users to use, which solves some of the basic problems with speech recognition already. Please mind that the number of sets for each language is limited to one, so you have to define all commands for a language in one command set element.</p> <p>The command prefix definition is used to match a spoken command to your app, just like explained above. The "Example" element just below is used in the UI of the phone when the user starts the voice recognition by holding down the start button of the phone. You may have noticed that there is a question mark button in that default UI. Tap that button and you will be taken to a help screen that e.g. lists all the apps installed on the phone which support voice commands. Here you can read what is written in the "Example" element of your command set:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/help_screen_2.png"><img title="help_screen" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="help_screen" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/help_screen_thumb.png" width="288" height="480" /></a></p> <p>When you tap the entry of an app here, you are taken to further details, in particular the list of supported commands for this app. Each command in turn can have an "Example" element in the definition file, to give the user samples of the command's usage:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/help_screen_command_2.png"><img title="help_screen_command" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="help_screen_command" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/help_screen_command_thumb.png" width="288" height="480" /></a></p> <p>In addition to the example text that is shown in the above UI each command entry can have the following sub elements:</p> <ul> <li>"ListenFor": this denotes an actual phrase that is listened for. You can add multiple phrases that differ slightly, for example in the definition file above I've added two versions for singular and plural. Make sure that all phrases are meant to invoke the same logical command, and don't mix in phrases that are actually meant to do something different.</li> <li>"Feedback": when the app is invoked as result of the recognized command, the phone reads back to the user what is defined here.</li> <li>"Navigate": this important element determines what page is being navigated to when your app is launched as a result of a voice command recognition. If you leave out the "Target" attribute, then the configured main page is used. However, you can navigate to sub pages directly (as with secondary tiles, for example), which is used here in the example also.</li> </ul> <p>Phrases can contain two special elements to achieve what has been discussed in theory above:</p> <ul> <li>You can add words in <em>square braces</em> to mark them as optional. With the above sample, the command "start Gorilla Garden and poke a gorilla" works equally to simply saying "Gorilla Garden – poke gorilla".</li> <li>By using curly braces, you can add placeholders which are then matched to so-called phrase lists. These are sets of possible values the user can say in place of the markers. In the above sample, a phrase list "{number}" is used. You can also use a special placeholder "{*}" to virtually allow any spoken value, however you won't have access to that value later – it'll only show up as "…" in the recognized result.</li> </ul> <p>I'll return to the topic of phrase lists below, as they play a vital part in making your commands more dynamic.</p> <h3>Registering Voice Commands</h3> <p>Registration of voice commands must be performed from your code. The involved namespace for voice commands is Windows.Phone.Speech.VoiceCommands [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207367(v=vs.105).aspx">3</a>] which currently provides access only to the two classes VoiceCommandService [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.voicecommands.voicecommandservice(v=vs.105).aspx">4</a>] and VoiceCommandSet [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.voicecommands.voicecommandset(v=vs.105).aspx">5</a>]. The former helps you registering your voice command definition file as well as provide access to already installed (and named) voice command sets. Usually the installation only needs to be performed once, however in certain situations the voice data of your app may be wiped, for example in backup/restore situations. It's no problem to perform the installation e.g. each time your application is started, but you can also try and play a bit nicer, like for example like:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">if</span> (VoiceCommandService.InstalledCommandSets.Count == 0)</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> await VoiceCommandService.InstallCommandSetsFromFileAsync(<span class="kwrd">new</span> Uri(<span class="str">"ms-appx:///SampleVoiceCommands.xml"</span>));</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--></div> </div> <p>Note the URI argument that points to the definition file in your app. This is enough for registration, commands can be used right away now, and your application and commands will appear in the help UI of the voice recognition feature on the phone, as shown above.</p> <h3>Working with Phrase Lists</h3> <p>One important thing to remember is that the definition of voice commands and phrases cannot be changed dynamically. The only parts that are accessible and can be changed from your code after you've installed the voice command definition file are the phrase lists. These however can be accessed comfortably and e.g. extended whenever you need it. For example, let's say you allow the user to launch your app and automatically display some custom data they created before. This is a typical scenario where static phrase lists won't work, as the potential values highly depend on the content users create. You can then use the following method to update the list whenever required, and instantly enable your voice commands to recognize the changed phrase lists.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">VoiceCommandSet defaultCommandSet;</pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">if</span> (VoiceCommandService.InstalledCommandSets.TryGetValue(<span class="str">"DefaultCommandSet"</span>, <span class="kwrd">out</span> defaultCommandSet))</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> IEnumerable<<span class="kwrd">string</span>> newValues = <span class="kwrd">new</span>[] { <span class="str">"1"</span>, <span class="str">"2"</span>, <span class="str">"3"</span>, <span class="str">"4"</span> };</pre> <!--CRLF--> <pre class="alt"> await defaultCommandSet.UpdatePhraseListAsync(<span class="str">"number"</span>, newValues);</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--></div> </div> <p>In the above snippet, I try to access the command set named "DefaultCommandSet" as it has been defined in the definition file before, and then update the "number" phrase list. In the original definition, this list only supported the values 1, 2, and 3, but after the update the voice recognition now also works for the value 4. </p> <h3>Processing Voice Commands</h3> <p>The last missing puzzle piece is how you actually process commands. After all, you want to access in particular the dynamic parts of a command the user has spoken in your app to determine what to do exactly. If you are a bit familiar with Windows Phone you probably are already thinking "navigation arguments", which is spot on. As in many other cases, these arguments are passed to the target page in its query string dictionary. </p> <p>The following keys for this are well known:</p> <ul> <li>voiceCommandName: contains the name of the command that was recognized</li> <li>reco: contains the recognized part, e.g. the phrase defined in the corresponding "ListenFor" element</li> <li>[phrase list name]: contains the value of the recognized phrase list entry</li> </ul> <p>Let's look at a snippet for the gorilla example:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnNavigatedTo(NavigationEventArgs e)</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> var arguments = NavigationContext.QueryString;</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">if</span> (arguments.ContainsKey(<span class="str">"voiceCommandName"</span>))</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> var voiceCommand = arguments[<span class="str">"voiceCommandName"</span>];</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">switch</span> (voiceCommand)</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">case</span> <span class="str">"PokeGorilla"</span>:</pre> <!--CRLF--> <pre class="alt"> var numberOfGorillas = 1;</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">if</span> (arguments.ContainsKey(<span class="str">"number"</span>))</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> var number = arguments[<span class="str">"number"</span>];</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">int</span>.TryParse(number, <span class="kwrd">out</span> numberOfGorillas);</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// do something with the command data</span></pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>First I check for available command data. In a second step, I check whether the phrase list value "number" is available. If it's not, then the user has spoken the generic command for a single gorilla poke. Conversion of the "number" argument to a real integer should never fail, as the voice recognition system only passes on values defined by me. For example, even if you desperately try to say "10" or other invalid values for the "number" phrase list, the first value (1) will be returned here.</p> <h2>Conclusion</h2> <p>Even if there probably are quite some users who don't use voice commands on a daily basis or never will even discover that feature on their phones, the effort it takes for a developer to add support for it is minmal. So if it makes sense for your app and you can think of some great shortcuts, I'm sure the power users aware of voice commands will love to see your ideas.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Voice-Commands.aspx Mon, 25 Feb 2013 14:27:00 GMT Windows Phone 8: Speech <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx" data-count="horizontal" data-text="Check out @Mister_Goodcat's article: '#WindowsPhone8 - Speech!' #wpdev #wp8" data-url="http://slshow.net/Y5EhEl">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>Windows Phone 7 already has some speech features built into the system, for example voice commands that can be invoked by holding down the start button. As with many other features of this first generation of the platform, accessibility to these was extremely limited for app developers. Once again Windows Phone 8 not only heavily improves this situation, but it also adds a variety of completely new features that both developers and users will benefit from. In this article, I'll take a closer look at text to speech and its counterpart, speech to text (speech recognition).</p> <h2>Required Setup</h2> <p>By now you're probably already used to some preparation that needs to be done before you can start using certain Windows Phone features in your apps. Speech is no different. If you want to use either text to speech or speech recognition, you need to specify the corresponding capability ID_CAP_SPEECH_RECOGNITION in your WMAppManifest.xml file, or you'll receive exceptions when you try to access any of the involved APIs. Since speech recognition also uses the microphone to record the user's voice, you need to additionally specify ID_CAP_MICROPHONE if you want to use it. As always, this can be performed using the visual manifest editor:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/cap_editor_4.png"><img title="cap_editor" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="cap_editor" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/cap_editor_thumb_1.png" width="532" height="480" /></a></p> <p>… or manually in the Xml file directly:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/cap_xml_4.png"><img title="cap_xml" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="cap_xml" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/cap_xml_thumb_1.png" width="437" height="119" /></a></p> <p>With that out of the way, let's start using the new features!</p> <h2>Text to Speech</h2> <p>Text to Speech, or TTS for short, is one of the features that can be used increadibly easily with just a few lines of code, but on the other hand can also become quite complex, solely depending on how far you as a developer are willing to take it. TTS is a built-in feature of Windows Phone 8, meaning you do not have to have an online connection for it to work; all speech synthesis is performed on the local device. </p> <p>The fundamental class for TTS is located in the Windows.Phone.Speech.Synthesis namespace [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.synthesis(v=vs.105).aspx">1</a>] and named "SpeechSynthesizer" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.synthesis.speechsynthesizer(v=vs.105).aspx">2</a>]. You'll find that no matter what speech features you use on Windows Phone 8, the involved APIs always provide their functionality in asynchronous flavors only. This also is true for the synthesis of speech, even though it is performed locally. Luckily working with them still is extremely simple by making use of the async and await keywords in C#. The simplest sample to make the phone talk to you looks something like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var synthesizer = <span class="kwrd">new</span> SpeechSynthesizer();</pre> <!--CRLF--> <pre class="alteven">await synthesizer.SpeakTextAsync(<span class="str">"Hallo World!"</span>);</pre> <!--CRLF--></div> </div> <p>When you try this you will hear a pretty natural sounding voice. What voice in particular is used for speech in this case depends on the selection you have made on the "speech" settings screen of your phone:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/speech_settings_2.png"><img title="speech_settings" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="speech_settings" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/speech_settings_thumb.png" width="480" height="800" /></a></p> <p>Here you can switch between both male and female voices as well as choose between various languages that are supported. This already hints to a problem that you will inevitably run into: if you select "German" as language here, the English text "Hallo World!" will sound like spoken by the bad guys in an Indiana Jones movie. Although funny, it's probably not what you want to achieve in your app. To work around this, you have to use the "InstalledVoices" class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.synthesis.installedvoices(v=vs.105).aspx">3</a>] in code which provides access to both the default voice (configured in the above shown settings screen) as well as all available other voices on the phone. That way you can select whatever voice you intend to use, independently of the user's settings. Like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var synthesizer = <span class="kwrd">new</span> SpeechSynthesizer();</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// select the US-English voice</span></pre> <!--CRLF--> <pre class="alteven">var englishVoice = InstalledVoices.All</pre> <!--CRLF--> <pre class="alt"> .Where(voice => voice.Language.Equals(<span class="str">"en-US"</span>))</pre> <!--CRLF--> <pre class="alteven"> .FirstOrDefault();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">if</span> (englishVoice != <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// let the synthesizer use the English voice</span></pre> <!--CRLF--> <pre class="alt"> synthesizer.SetVoice(englishVoice);</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven">await synthesizer.SpeakTextAsync(<span class="str">"Hallo World!"</span>);</pre> <!--CRLF--></div> </div> <p>The available speech synthesizer features don't stop at this point though. Windows Phone supports the so-called "Speech Synthesis Markup Language" (SSML) that allows you to control the very details and characteristics of synthetic speech in great detail. To this end, the synthesizer class has various methods that allow you to speak SSML from both local [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.synthesis.speechsynthesizer.speakssmlasync(v=vs.105).aspx">4</a>] and remote [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.synthesis.speechsynthesizer.speakssmlfromuriasync(v=vs.105).aspx">5</a>] locations, and some of the other members offered by the class also only make sense for SSML speech. SSML lets you control things like pitch and volume, pauses between words and dynamically switching between different voices, on a very granular level. If you want to learn more about this topic, a quick description of the features can be found on MSDN [<a href="http://msdn.microsoft.com/en-us/library/hh361578">6</a>] whereas the full documentation is made available by the W3C [<a href="http://www.w3.org/TR/speech-synthesis/">7</a>].</p> <h2>Speech Recognition</h2> <p>The counterpart to text to speech is speech recognition, or speech to text. As you probably can imagine, this is a lot harder to achieve than synthesizing text to speech. The latter one "only" has to work out a way to create proper sounds from well-defined source material (text) that has comparably little stumbling blocks (like acronyms or names). Speech recognition on the other hand potentially has to work with millions of different voices, all with their own characteristics. In addition to inherent details like pitch and tone people around the world also show dramatic differences in pronounciation and emphasizing syllables, even when they formally speak the same language (think dialects).</p> <p>Speech recognition for Windows Phone hence is mostly performed by remote systems, which require that some preprocessed audio material is uploaded and analyzed by specialized, high-performance systems running somewhere in the cloud. So, to use speech recognition, the device needs to have a working data connection.</p> <p>The involved namespace with speech recognition is Windows.Phone.Speech.Recognition [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition(v=vs.105).aspx">8</a>] and simply by taking a quick look at it you can see that there's a lot more types available than for synthesis here. However, most of the work still comes down to few fundamental classes, in particular the "SpeechRecognizer" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechrecognizer(v=vs.105).aspx">9</a>] and "SpeechRecognizerUI" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechrecognizerui(v=vs.105).aspx">10</a>]. Both allow you to do speech recognition, but the latter provides the (customizable) default user interface a Windows Phone user most likely is familiar with. Again starting with the topic can be quite simple at first, with only a few lines of code:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// create and customize the UI</span></pre> <!--CRLF--> <pre class="alteven">var recognizerUI = <span class="kwrd">new</span> SpeechRecognizerUI();</pre> <!--CRLF--> <pre class="alt">recognizerUI.Settings.ListenText = <span class="str">"I'm listening..."</span>;</pre> <!--CRLF--> <pre class="alteven">recognizerUI.Settings.ExampleText = <span class="str">"Speech recognition on Windows Phone!"</span>;</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="rem">// perform the recognition</span></pre> <!--CRLF--> <pre class="alt">var speechRecognitionUIResult = await recognizerUI.RecognizeWithUIAsync();</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// make sure to check the status before processing any results</span></pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">if</span> (speechRecognitionUIResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded)</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> ResultText.Text = speechRecognitionUIResult.RecognitionResult.Text;</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>The visual result of this looks like:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_ui_2.png"><img title="recognizer_ui" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="recognizer_ui" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_ui_thumb.png" width="480" height="378" /></a></p> <p>The default UI also has additional dialogs that are shown for example when the recognition failed…</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_ui_sorry_2.png"><img title="recognizer_ui_sorry" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="recognizer_ui_sorry" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_ui_sorry_thumb.png" width="480" height="377" /></a></p> <p>… or was successful:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_result_2.png"><img title="recognizer_result" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="recognizer_result" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/recognizer_result_thumb.png" width="480" height="378" /></a></p> <p>The behavior of that UI can be customized slightly by changing the settings on the "SpeechRecognizerUI" instance. For example, you can turn off the result screen, or that the recognized result is read back to the user. </p> <p>One important detail is to always check the "ResultStatus" property of the returned "SpeechRecognitionUIResult" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechrecognitionuiresult(v=vs.105).aspx">11</a>] because speech recognition can fail due to a variety of reasons:</p> <ul> <li>Another speech recognition is in progress (usually indicates a problem in your code)</li> <li>The phone's speech feature is otherwise in use, e.g. when a phone call comes in</li> <li>The user or navigating away from the app canceled the operation</li> <li>The user declined the speech privacy policy</li> </ul> <p>The last point hints at the fact that the user has actively agree to using the speech recognition services. When you take a look at the above screenshot of the speech settings page again, you can see the corresponding check box at the bottom of the page there. If the user hasn't agreed to the policy and your app tries to use the feature, they are presented with an agreement screen first, and of course if they decline speech recognition will fail. Fortunately this has not to be done on an per-app basis, so if the user has accepted the policy any time before, your app won't run into this problem and your users won't be bothered with this again.</p> <p>If the built-in UI doesn't fit your needs, you can create a complete custom UI for your app. To this end, the "SpeechRecognizer" class mentioned above provides recognition features that do not involve any predefined UI at all:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var recognizer = <span class="kwrd">new</span> SpeechRecognizer();</pre> <!--CRLF--> <pre class="alteven">var speechRecognitionResult = await recognizer.RecognizeAsync();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven">ResultText.Text = speechRecognitionResult.Text;</pre> <!--CRLF--></div> </div> <p>When something goes wrong with the recognition in this case, exceptions are thrown. In addition, events exist on the recognizer that inform you e.g. about audio problems.</p> <p>Not matter whether you use the built-in UI or a custom implementation, it's a good idea to take a close look at the "SpeechRecognitionResult" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechrecognitionresult(v=vs.105).aspx">12</a>] which is directly returned by the speech recognizer and also available as property on the UI results returned by the speech recognizer UI. In particular, it indicates the confidence level by which the result could be determined. This includes a value of "Rejected" when the recognition service failed to guess any results. The confidence level is determined by an underlying floating point confidence score that you can also access here, if you really want to have more granularity. The result also allows you to access potential alternative results. For example, in some cases alternate interpretations of the analyzed audio may exist. The result then contains the most likely one, based on the confidence scores. If you want you can however access the other alternates too by using the "GetAlternates" method on the result.</p> <h3>Working with Grammars</h3> <p>Grammars are a way to tell the recognizer what kind of results you expect. By providing information about the expected structure and/or limiting the possible results to a pool of fixed values, you can improve the quality and accuracy of recognition significantly. Grammers are always used behind the scenes. Even if you do not specify any grammar explictly (like in all the examples above), Windows Phone uses a built-in default "dictation" grammar. The only other built-in grammar is "WebSearch" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechpredefinedgrammar(v=vs.105).aspx">13</a>].</p> <p>Grammars are maintained with the recognizer, and can be accessed by its "Grammars" collection property. This special collection type ("SpeechGrammarSet" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.speech.recognition.speechgrammarset(v=vs.105).aspx">14</a>]) has multiple custom methods to add grammars from local lists, the above mentioned pre-defined grammars as well as from URI locations. You can add multiple grammars to the recognizer at the same time and enable/disable them accordingly whenever you need them. The following example shows how to use local lists:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var recognizer = <span class="kwrd">new</span> SpeechRecognizer();</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// create a grammar from a local list</span></pre> <!--CRLF--> <pre class="alteven">var fruitPhrases = <span class="kwrd">new</span>[] { <span class="str">"apple"</span>, <span class="str">"banana"</span>, <span class="str">"gorilla"</span> };</pre> <!--CRLF--> <pre class="alt">recognizer.Grammars.AddGrammarFromList(<span class="str">"Fruits"</span>, fruitPhrases);</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// preload the grammar</span></pre> <!--CRLF--> <pre class="alteven"><span class="rem">// this is done automatically by calling RecognizeAsync, but this</span></pre> <!--CRLF--> <pre class="alt"><span class="rem">// gives you more explicity control over it, as it may cause a short delay</span></pre> <!--CRLF--> <pre class="alteven">await recognizer.PreloadGrammarsAsync();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="rem">// recognize using the grammar</span></pre> <!--CRLF--> <pre class="alt">var speechRecognitionResult = await recognizer.RecognizeAsync();</pre> <!--CRLF--></div> </div> <p>When you try this code, you will see that it very accurately recognizes the words listed in the grammar, however you would have a very hard time if you tried to make it recognize "mango", for example. So this is a simple way of making sure that you receive only results meaningful to your app, or nothing if recognition fails. More on working with grammars that way can be found on MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206964(v=vs.105).aspx">15</a>][<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206977(v=vs.105).aspx">16</a>].</p> <p>Of course limiting your app to a fixed set of values only works for simple cases. Grammars are a lot more powerful than that. Windows Phone supports SRGS – "Speech Recognition Grammar Specification" – which is another W3C standard [<a href="http://www.w3.org/TR/speech-grammar/">17</a>]. This allows you to specify rules about word ordering, combination of lists, filtering out unwanted "noise" and a lot more. MSDN has an introduction to this complex topic for Windows Phone 8, including additional links to more references and sample How-tos [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207051(v=vs.105).aspx">18</a>].</p> <h2>Testing Speech</h2> <p>A pleasant surprise with all the speech features is that you can easily test them in the emulator too. For text to speech this seems obvious. Because the emulator images contain a fully working Windows Phone system, there's really no reason why this shouldn't work there too. For speech recognition however more user interaction is required, in particular providing audio input using a microphone. To this end, a microphone connected to the development computer can be used to provide the necessary input for speech recognition without any further setup.</p> <p>For more complex scenarios, and especially for test cases that work reproducibly, this still may not be sufficient for you. At the moment, I am not aware of any built-in possibilities to provide e.g. pre-recorded audio files as input for testing, so you may need to build a custom solution for this (if you know a simpler way, let me know).</p> <h2>Conclusion</h2> <p>My personal perception was that on Windows Phone 7 speech features were a nice embellishment, but not many people actively used them on a daily basis. With Windows Phone 8, not only have the features improved and been extended dramatically, developers now also have great access to them through sophisticated APIs, so I expect to see a lot more use of speech in the future. Let's see how upcoming apps will surprise us.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Speech.aspx Tue, 19 Feb 2013 14:00:00 GMT Windows Phone 8: NFC (Near Field Communication) <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx" data-count="horizontal" data-text="Check out @Mister_Goodcat's article: '#WindowsPhone8 - NFC (Near Field Communication)!' #nfc #wpdev #wp8" data-url="http://slshow.net/12b3nan">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>In this third part about communication feature improvements in Windows Phone 8, I will focus on Near Field Communication, or NFC for short, which lately has found its way into many modern smart phones across different platforms like Android, Bada or BlackBerry. On Windows Phone, NFC support has only been added in version 8; there wasn't any support for it in Windows Phone 7 neither built-in nor available to third-party developers. The most prominent use case is for payment services like the "Wallet Hub" in Windows Phone [<a href="http://www.windowsphone.com/en-us/how-to/wp8/basics/wallet-faq">1</a>], however the range of uses is not limited to that, and with the available API developers can adapt the technology easily for their particular needs.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <h2>What NFC Is</h2> <p>Very much like Bluetooth, that we have learned about in the last part [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx">2</a>], Near Field Communication is a standard for short-range wireless connectivity. In contrast to Bluetooth which works in the range of up to tens of meters in optimal environments, NFC is limited to an extremely short range of just a few (typically no more than 3-5) centimeters.</p> <p>NFC can be used to transfer any kind of data, but it is not only designed for communication between devices. It also supports one-way applications where active devices like NFC-enabled smart phones interact with passive (unpowered) infrastructure like RFID or NFC tags, something that you might have heard about before. </p> <p>Near Field Communication requires low power and can establish connections very quickly (in less than 1/10th of a second), but its transfer speeds are slower than those of other wireless communication. An interesting use case hence is to use NFC as bootstrapping technology for other communication channels. For example, due to the low reception range unwanted communication between devices is unlikely; NFC-enabled devices therefore may allow to initiate typically more complex to set up connections like Bluetooth or Wi-Fi automatically, after a NFC connection between two peers has been established. The benefit is that the user does not need to perform multiple manual steps like enabling a connection and confirm security measurements. This is used e.g. on some Android devices to create ad-hoc Wi-Fi connections that you do not need to configure manually at all.</p> <h2>NFC Features in Windows Phone</h2> <p>In Windows Phone 8, both scenarios that I briefly outlined above are supported:</p> <ul> <li>Direct data exchange between devices using NFC connections, and</li> <li>Establishing a higher bandwidth connection like Wi-Fi or Bluetooth using NFC as initiator</li> </ul> <p>To use any NFC features, you need to set up your app accordingly first, as described in the following paragraph.</p> <h3>NFC Setup</h3> <p>No matter what you intend to do, to enable NFC use in your application you need to add the required capabilities to your application's manifest file, similar to what I've described in the article on Bluetooth (networking is only required if you plan on communicating over sockets):</p> <p><img style="margin-right: auto; margin-left: auto; float: none; display: block;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________________image_thumb.png" /></p> <p>You can of course also specify these directly in the WMAppManifest.xml:</p> <p><img style="margin-right: auto; margin-left: auto; float: none; display: block;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________________image_thumb_1.png" /></p> <p>If your app cannot function in a meaningful way without NFC support, you can also enforce this on the "Requirements" tab of the WMAppManifest.xml editor. Selecting this option will prevent devices without NFC support from installing your app completely:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________________image_thumb_1.png" width="264" height="177" /></a>This of course also will simply be translated into an entry in the Xml:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________________image_thumb_2.png" width="263" height="48" /></a></p> <p>Once you have configured your app for NFC use, the fundamental class involved in anything with NFC is "ProximityDevice" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.networking.proximity.proximitydevice.aspx">3</a>] in the Windows.Networking.Proximity namespace [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/br241250.aspx">4</a>]. It offers events that notify you about the presence of other devices as well as a rich set of methods to publish NFC messages and subscribe for their reception.</p> <p>The first step always should be to check whether NFC is actually supported on the device your app is currently running on. This is done by checking whether the default proximity device is null:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var proximityDevice = ProximityDevice.GetDefault();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="kwrd">if</span> (proximityDevice != <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="rem">// we can use NFC!</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> }</pre> <!--CRLF--></div> </div> <p>Now you can start using all the NFC features.</p> <h3>NFC Messages</h3> <p>Direct data exchange over NFC connections uses the above mentioned NFC messages. A message consists of both the message type and the actual payload to transmit. You can always define custom message types that are only meaningful to your own application, however Windows Phone also understands and supports a selection of predefined and standard message types. I'll talk a bit more about this later, after we've seen an example. To publish a message, you simply can use one of the available methods on the proximity device class. The available options include publishing string, binary and URI messages.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var publicationId = proximityDevice.PublishMessage(</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="str">"Windows.MyCustomMessageType"</span>, <span class="rem">// message type</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="str">"Hallo World!"</span>, <span class="rem">// message payload</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> MessageTransmittedHandler); <span class="rem">// callback</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> <span class="rem">// [...]</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> MessageTransmittedHandler(ProximityDevice sender, <span class="kwrd">long</span> messageId)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="rem">// the message has been transmitted</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> }</pre> <!--CRLF--></div> </div> <p>The snippet uses a custom message type of "Windows.MyCustomMessageType". The part before the dot is named "protocol" and needs to have a fixed value of "Windows" when you want to use custom messages. The latter part of course is up to you to define, as well as the payload data structure.</p> <p>It's important to know that only one message at a time can be published. This means that if you want to publish a different message, you need to explicitly stop publishing first, using the corresponding "StopPublishingMessage" method [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.networking.proximity.proximitydevice.stoppublishingmessage.aspx">5</a>]. This method takes the message/publication Id that is returned from the "PublishMessage" method call in the above sample. Another typical pattern also would be to stop publishing when a message has been transmitted, which is why the transmitted handler also takes the message Id argument.</p> <p>The consuming side works in a similar way: once you have obtained access to the default proximity device, you can subscribe for messages. This obviously requires that you provide the same message type that is used by the publishing code.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> proximityDevice.SubscribeForMessage(<span class="str">"Windows.MyCustomMessageType"</span>, MessageReceivedHandler);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="rem">// [...]</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> MessageReceivedHandler(ProximityDevice sender, ProximityMessage message)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> var receivedString = message.DataAsString;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> }</pre> <!--CRLF--></div> </div> <p>Of course the "ProximityMessage" class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.networking.proximity.proximitymessage.aspx">6</a>] also grants access to the binary content of the message instead of the convenient string access. If you want to unsubscribe from messages, the proximity device also offers a "StopSubscribingForMessage" method. </p> <p>As you can see, sending and receiving messages is pretty straight-forward and simple. </p> <h4>Supported Message Types</h4> <p>Apart from custom message types, Windows Phone also supports standard protocols and types that can be used for a greater variety of functionality, for example to transmit files or launch apps either by package id or by registered protocols (also see my article on that topic for more information [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx">7</a>]). The latter also allows you to launch built-in apps like the web browser and display a specific web site by publishing the corresponding NFC messages. In all these situations the user is always asked for consent due to security considerations.</p> <p>A more common use case for the standard protocols is to have phones react to passive tags or NFC chips. In a way, this can be compared to e.g. using Bing Vision to read a QR code which takes you to a web site – except that you'd tap smart posters or similar accessories that contain NFC tags instead. One of the supported messages types is to actually write to tags, so you can even create the content for these tags directly from the phone.</p> <p>An excellent and exhaustive article on NFC tag support in Windows Phone 8 can be found in the Nokia Developer Community Wiki [<a href="http://www.developer.nokia.com/Community/Wiki/Use_NFC_tags_with_Windows_Phone_8">8</a>]. It not only describes the possibilities (and limitations) of writing to tags with Windows Phone 8, but also contains a comprehensive list of supported protocols and sub types.</p> <p>In addition, projects are starting to show up to help you with working with the NFC features of both Windows Phone 8 and Windows 8 in a more comfortable way. For example, the NDEF Library on CodePlex [<a href="http://ndef.codeplex.com/">9</a>] gives you more control over the message details and lets you work easily with certain features like launching apps or settings pages on the phone.</p> <h3>Establishing Socket Connections Over NFC</h3> <p>As I mentioned in the beginning, another very interesting use case of NFC is to initiate higher bandwidth connections on more capable wireless connectivity technologies. Windows Phone supports exactly that by the use of the "PeerFinder" class that we've already seen in detail in my article on Bluetooth [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx">10</a>]. I won't go into the concepts of that class again here but rather show you how it is used to create an initial NFC connection between two devices that is then automatically "elevated" to a Bluetooth or Wi-Fi communication channel.</p> <p>One key part of this procedure is the "TriggeredConnectionStateChanged" event [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.networking.proximity.peerfinder.triggeredconnectionstatechanged.aspx">11</a>] that notifies you about the different stages an NFC-initiated connection goes through until it can be used in your code. This is useful to e.g. notify users of your app when a tap was successful and they can pull away their phones again. Consuming the event also is necessary to determine which device has initiated the tap, and to obtain a reference to the "StreamSocket" instance that is used for the actual communication. This socket will already use Bluetooth or Wi-Fi (TCP/IP) as transport, depending on how you configured the PeerFinder. Take a look at this snippet for an example:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> StartFindingPeer()</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="rem">// check if the device supports NFC</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="kwrd">if</span> ((PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Triggered) == PeerDiscoveryTypes.Triggered)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> PeerFinder.TriggeredConnectionStateChanged += TriggeredConnectionStateChanged;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="rem">// indicate we only want a Bluetooth connection, no Wi-Fi</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> PeerFinder.AllowBluetooth = <span class="kwrd">true</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> PeerFinder.AllowInfrastructure = <span class="kwrd">false</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> <span class="rem">// go!</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> PeerFinder.Start();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> }</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> TriggeredConnectionStateChanged(<span class="kwrd">object</span> sender, TriggeredConnectionStateChangedEventArgs args)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> <span class="kwrd">switch</span> (args.State)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum21"> 21:</span> <span class="kwrd">case</span> TriggeredConnectState.PeerFound:</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum22"> 22:</span> <span class="rem">// NFC tap was successful => phones can be pulled away now;</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum23"> 23:</span> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum24"> 24:</span> <span class="kwrd">case</span> TriggeredConnectState.Connecting:</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum25"> 25:</span> <span class="rem">// this is the initiating device</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum26"> 26:</span> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum27"> 27:</span> <span class="kwrd">case</span> TriggeredConnectState.Listening:</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum28"> 28:</span> <span class="rem">// the other device is the initiating device</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum29"> 29:</span> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum30"> 30:</span> <span class="kwrd">case</span> TriggeredConnectState.Completed:</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum31"> 31:</span> <span class="rem">// you can use the socket to communicate!</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum32"> 32:</span> var socket = args.Socket;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum33"> 33:</span> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum34"> 34:</span> <span class="kwrd">case</span> TriggeredConnectState.Failed:</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum35"> 35:</span> <span class="kwrd">case</span> TriggeredConnectState.Canceled:</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum36"> 36:</span> <span class="kwrd">break</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum37"> 37:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum38"> 38:</span> }</pre> <!--CRLF--></div> </div> <p>The code shows another way of determining whether the device supports NFC in its first if-statement. Eventually you will gain access to a StreamSocket instance that you can use for communication just like with any regularly established connection.</p> <p>One of the limitations on Windows Phone, again out of security considerations, is that it's not possible to automatically enable features on the phone that the user has turned off. This means that you cannot initiate a Bluetooth connection in the way shown above if Bluetooth is deactivated. Therefore, you would typically ask your users to turn on Bluetooth before tapping their phones. To make this most comfortable, you can navigate them to the corresponding settings page automatically. It's a small sacrifice of comfort in favor for more security, but requiring users to simply activate Bluetooth still is a lot better than have them pair devices and complete the normal Bluetooth setup manually.</p> <h2>Testing NFC</h2> <p>As with Bluetooth features, testing NFC is not exactly straight forward and often requires manual testing on real hardware. However, the situation is a bit better with NFC as people already have started developing tools that support testing with the built-in emulators. One of these tools is the Proximity Tapper hosted on CodePlex [<a href="http://proximitytapper.codeplex.com/">12</a>] that allows to inject NDEF messages into the emulator and also analyze the message traffic. It's not a full replacement for testing with a real phone and/or tags, but it's at least a start to make the development process a bit more efficient.</p> <h2>Conclusion</h2> <p>NFC communication is another piece in the puzzle of highly interactive and networked applications current software development is headed towards. Windows Phone's support for it is proof the platform has managed to successfully turn into an early adopter with unique characteristics, ahead of some competitors like iOS (which still has no NFC support [<a href="http://en.wikipedia.org/wiki/List_of_NFC-enabled_mobile_devices">13</a>]). I'm excited about what applications we will see that make use of these new opportunities.</p> http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-NFC-Near-Field-Communication.aspx Tue, 12 Feb 2013 03:03:00 GMT Windows Phone 8: Bluetooth <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx" data-count="horizontal" data-text="Check out @Mister_Goodcat's article: '#WindowsPhone8 - Bluetooth!' #wpdev #wp8" data-url="http://slshow.net/UUustQ">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>When we talk about Bluetooth support in Windows Phone, we really have to look at two different sides of the same medal: user experience and features as well as developer opportunities. Windows Phone 7 had basic support for Bluetooth from the beginning, however more advanced options were not available to the user. For developers, the situation was even worse, as there was no public available API to support Bluetooth features in your apps at all. Both situations have changed and improved dramatically in Windows Phone 8, however, as we will see in this article, the situation is still not perfect.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <h2>What Bluetooth Is</h2> <p>Bluetooth is a wireless communication standard that has been around since the late nineties and evolved over the last decade into one of the most important technologies for short-distance data exchange between both fixed and mobile devices. It allows, for example, to create ad-hoc networks between devices like your phone, and gadgets. Typical use cases you may know are:</p> <ul> <li>Use of hands-free kits to transport audio (speaker and microphone), data (e.g. caller information) as well as commands (e.g. for dialing)</li> <li>Remote game controllers (e.g. the Wii and PS3 controllers use it) and other input devices (e.g. wireless keyboards)</li> <li>Local communication sets (e.g. for motorcycle drivers etc.)</li> </ul> <p>Apart from these there are a lot more applications, both in the industry and consumer areas, like home automation or in the medical field.</p> <p>Bluetooth works with so-called profiles to add support for typical application-level features on top of the low-level technology infrastructure. For example, the possibility to exchange data does not guarantee that two devices really know how to talk to each other correctly. To solve the problem that each and every vendor potentially creates their own application-level protocols for basically identical features, profiles were created. These describe how certain functionality has to be implemented, so that e.g. devices across multiple vendors can talk to each other in a standardized way. Today, a great variety of profiles exist [<a href="http://en.wikipedia.org/wiki/Bluetooth_profile">1</a>], for example for audio, image and video exchange, remote control, hands-free features, input devices and even things like printing or data synchronization. This means that "Bluetooth support" alone is not a suitable term to describe a device's capabilities. You always have to be aware of what profiles are supported to understand what actual features a device really offers.</p> <h2>End User Bluetooth Features in Windows Phone</h2> <p>The first thing we need to do hence is look at what Bluetooth profiles are actually supported from the consumer's point of view. From the very beginning, Windows Phone 7 supported typical scenarios where you wanted to hook your phone to car audio systems or headsets. However, support for other important profiles like those used for data exchange or input devices were missing. Only some of these missing features have been added to Windows Phone 8. Let's take a look at the following table to understand what Windows Phone devices actually support:</p> <strong></strong><strong></strong><strong></strong> <table cellspacing="0" cellpadding="2" width="640" border="1"> <tbody> <tr> <td valign="top" style="width: 213px;"> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><strong>Windows Phone 7</strong></p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><strong>Windows Phone 8</strong></p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Advanced Audio Distribution Profile <br /> </strong>(audio streaming)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.2)</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.2)</p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Audio/Video Remote Control Profile <br /> </strong>(controlling A/V equipment)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.3)</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (<strong>1.4</strong>)</p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Hands Free Profile <br /> </strong>(e.g. car systems for hands-free calls)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.5)</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.5)</p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Headset Profile <br /> </strong>(basic headset features)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.1)</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><strong>No*</strong></p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Phone Book Access Profile <br /> </strong>(exchange of phone book data)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.1)</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">Yes (1.1)</p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Object Push Profile <br /> </strong>(pushing files, images etc. to others)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;">No</p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><strong>Yes (1.1)</strong></p> </td> </tr> <tr> <td valign="top" style="width: 213px;"><strong>Human Interface Device Profile <br /> </strong>(mice, joysticks, keyboards etc.)</td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><span style="color: #ff0000;">No</span></p> </td> <td valign="top" style="width: 213px;"> <p style="text-align: center;"><span style="color: #ff0000;">No</span></p> </td> </tr> </tbody> </table> <p><em><strong>*</strong>It's interesting that by the time of writing the official documentation [</em><a href="http://support.microsoft.com/kb/2770012"><em>2</em></a><em>] does not list the Headset Profile for Windows Phone 8 anymore (as it explicitly was in that for Windows Phone 7 [</em><a href="http://support.microsoft.com/kb/2449475"><em>3</em></a><em>]). Of course this does not mean that Windows Phone 8 doesn't support headsets anymore. Headsets are also part of the audio distribution profile and hands-free profile. I don't know whether the specific profile is just missing from the documentation or support for it has been explicitly dropped.</em></p> <p>I've highlighted the changes in Windows Phone 8 as well as other interesting details. The support for a newer version of the remote control profile should add more options to situations when you control A/V equipment with the phone. A lot more important however is the newly added support for the "Object Push Profile". This is something that was requested a lot, and it finally allows you to share data like contacts, photos, music and office documents between devices. Detailed instructions for end users can be found on the Windows Phone web site [<a href="http://www.windowsphone.com/en-us/how-to/wp8/basics/share-files-over-bluetooth">4</a>].</p> <p>Sadly, one of the most important profiles, namely the "Human Interface Device Profile", still is not supported on Windows Phone 8, just like it wasn't on version 7 of the platform. This profile is responsible for the support of external input devices, like game controllers and keyboards. It's not only relevant for end users to e.g. make gaming more enjoyable, but also a big issue for enterprise software development. For example, in one of my current projects it really would be nice for users of a enterprise software on Windows Phone 8 to be able to use an external keyboard, so input of large amounts of data when they are on the road becomes easier and more practicable. Support for this was expected by many, and consequently the corresponding User Voice feature has gained a lot of traction already [<a href="http://windowsphone.uservoice.com/forums/101801-feature-suggestions/suggestions/3587770-support-for-hid-human-interface-device-bluetooth">5</a>]. If you want to see support for things like these in Windows Phone, go and vote there!</p> <h2>Developer Bluetooth Features in Windows Phone</h2> <p>The options for developers regarding Bluetooth on Windows Phone 7 were, frankly, non-existent. No public APIs existed that third-party app developers could use to add Bluetooth features to their software. In Windows Phone 8, this situation was improved a lot, and the newly available APIs now support both custom device to device communication as well as interacting with any device the phone previously has paired with. It's noteworthy though that "device to device" mainly means communication between instances of your app running on multiple devices at the same time.</p> <h3>The Setup</h3> <p>The fundamental namespace involved with the peer communication features of Windows Phone 8, not only Bluetooth but e.g. also NFC, is Windows.Network.Proximity [<a href="http://msdn.microsoft.com/en-us/library/windows/apps/br241250.aspx">6</a>] which contains types that are available similarly on Windows Phone 8 and Windows 8. The idea here is to provide both a unified API for all the flavors of short distance communication as well as to keep those APIs consistent across both operating systems by making them part of the Windows Runtime APIs. This helps you creating portable code and spares you from learning multiple APIs depending on the platform you work with. The same is true for another part of the puzzle, the namespace Windows.Networking.Sockets [<a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.aspx">7</a>]. It provides types like the StreamSocket [<a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocket.aspx">8</a>] which is the common type used for the actual communication (connect, read and write data) in both Bluetooth scenarios. By the way, direct communication between Windows 8 and Windows Phone 8 versions of your app is an explicitly mentioned scenario that is supported through details like the "alternate identities" concept.  </p> <p>To make use of Bluetooth or NFC features, you need to specify the corresponding capability "ID_CAP_PROXIMITY" in your WMAppManifest.xml. For networking features, you additionally need to use the networking capability too. You can set those capabilities either through the visual editor:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________________image_2.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________________image_thumb.png" width="324" height="484" /></a>… or directly in XML:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________________image_thumb_1.png" width="373" height="125" /></a></p> <p> </p> <h3>Phone to Device</h3> <p>You cannot establish arbitrary connections to any Bluetooth devices within reach of the current phone. Instead, the user first has to pair with such devices using the phone's Bluetooth settings first. This obviously is a security precaution. For you as a developer this means that you can only iterate the paired Bluetooth devices and then pick one that you want to connect to. To do this, you have to make use of the alternate identities feature I already mentioned briefly above to indicate that you are interested only in peers that are paired through Bluetooth. Here is a complete sample snippet:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="rem">// set this to find all paired bluetooth devices</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> PeerFinder.AlternateIdentities[<span class="str">"Bluetooth:Paired"</span>] = <span class="str">""</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="rem">// do the actual discovery</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> var peers = await PeerFinder.FindAllPeersAsync();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> <span class="rem">// select one of the paired devices based on the</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="rem">// data provided by the returned peers</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> var peer = SelectPeer(peers);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="kwrd">if</span> (peer != <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> <span class="rem">// create and connect a socket</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="kwrd">using</span> (var socket = <span class="kwrd">new</span> StreamSocket())</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> await socket.ConnectAsync(peer.HostName, <span class="str">"[desired service]"</span>);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> <span class="rem">// write some data to the socket</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> var buffer = GenerateData();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> await socket.OutputStream.WriteAsync(buffer);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> }</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum21"> 21:</span> }</pre> <!--CRLF--></div> </div> <p>Once you have obtained the list of available peers, you typically select the one you want based on the information returned, for example the display or host names. Of course you can also give the user the opportunity to select the peer they want. The next step then is to create a socket that connects to the peer. For paired Bluetooth devices, the "ServiceName" property of the peer data is empty, so you need to know up-front what value to pass in to the "ConnectAsync" method of the socket. This shouldn't be a problem though, as this service name does not change and can safely be hard-coded for the devices you support.</p> <p>Once you are connected, you can use the "OutputStream" property of the socket to write data to the device, and of course the corresponding "InputStream" to read, if applicable. These streams work with "IBuffer" instances, something that you may not be familiar with if you haven't worked with Windows 8 and/or the Windows Runtime before. The following snippet gives you an idea how you can use the "DataWriter" helper class [<a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.storage.streams.datawriter.aspx">9</a>] to easily obtain an "IBuffer" suitable to use with these APIs.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> IBuffer GenerateData()</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="rem">// generate some sample data from the string "Hallo World!"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="kwrd">using</span> (var dataWriter = <span class="kwrd">new</span> DataWriter())</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> dataWriter.UnicodeEncoding = UnicodeEncoding.Utf8;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> dataWriter.WriteString(<span class="str">"Hallo World!"</span>);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="kwrd">return</span> dataWriter.DetachBuffer();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> }</pre> <!--CRLF--></div> </div> <p>Of course, the details about what data to send to the paired device depends on the situation and it's up to you to implement this correctly based on its specification.</p> <h3>Phone to Phone</h3> <p>For Bluetooth communication between phones, you can send data back and forth between instances of your app running on multiple devices. Even though these instances may look as equal partners in the communication, technically still the usual same client/server concept is used to bring them together. You as app developer hence are responsible for implementing both the server and client side in your app. </p> <p>The client side is almost identical to what we have seen above in the phone to device communication scenarios. The difference is that you are not enumerating the paired devices, but instead you will try to find a corresponding instance of your app running on another device directly. As mentioned above, by using the "alternate identities" approach you could also establish connections between apps that do not have the same identity, which typically will be the case if you're trying to e.g. connect to a Windows 8 version of your app from Windows Phone. More on this can be found in the above linked MSDN documentation.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="rem">// simply start the peer finder</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> PeerFinder.Start();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="rem">// do the actual discovery of our app running on another device</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> var peers = await PeerFinder.FindAllPeersAsync();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> <span class="rem">// select one of the available peers</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> var peer = SelectPeer(peers);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> <span class="kwrd">if</span> (peer != <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> <span class="rem">// create and connect a socket</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> <span class="kwrd">using</span> (var socket = <span class="kwrd">new</span> StreamSocket())</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> await socket.ConnectAsync(peer.HostName, <span class="str">"[desired service]"</span>);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> <span class="rem">// write some data to the socket</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> var buffer = GenerateData();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> await socket.OutputStream.WriteAsync(buffer);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> }</pre> <!--CRLF--></div> </div> <p>The server side is a bit more complex. You need to listen for incoming connections and then connect a corresponding socket that you can use to read whatever data the client has to send. If you are familiar with networking, this won't be new to you except for the involved types. </p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> StartBluetoothServer()</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="rem">// start and listen for connection requests</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> PeerFinder.Start();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> }</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="kwrd">private</span> async <span class="kwrd">void</span> PeerFinder_ConnectionRequested(<span class="kwrd">object</span> sender, ConnectionRequestedEventArgs args)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="rem">// retrieve the peer information</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> var peer = args.PeerInformation;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="rem">// ... and connect</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> <span class="kwrd">using</span> (var socket = await PeerFinder.ConnectAsync(peer))</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> <span class="rem">// required buffer</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> var buffer = <span class="kwrd">new</span> Windows.Storage.Streams.Buffer(1024);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> <span class="rem">// read back the data</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> var readBytes = socket.InputStream.ReadAsync(buffer, </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum21"> 21:</span> buffer.Capacity, </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum22"> 22:</span> InputStreamOptions.Partial);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum23"> 23:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum24"> 24:</span> <span class="rem">// process the data contained in "buffer"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum25"> 25:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum26"> 26:</span> }</pre> <!--CRLF--></div> </div> <p>Once again the details about what kind of data is transferred between both peers is up to you to define. Thinking about and specifying the involved structures is the challenging part when you build that kind of applications. You need to create a protocol for your app that is capable of transferring all the information you need but at the same time does not waste bandwidth and is robust enough to handle typical networking problems. Typically you would e.g. prefix the data that is sent with the amount that is to follow so the receiving side knows how many bytes to read from the stream. This however is a whole other topic and way beyond the scope of this article.</p> <h2>Testing Bluetooth</h2> <p>Bluetooth features in your app require lots of manual testing. The emulators that ship with the phone SDK do not have built-in support for Bluetooth, which means that using any APIs like the PeerFinder will immediately result in exceptions.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/wp8_bluetooth_small_2.png"><img title="wp8_bluetooth_small" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="wp8_bluetooth_small" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/wp8_bluetooth_small_thumb.png" width="480" height="292" /></a></p> <p>Unlike with NFC, where people already came up with solutions for this problem (more on this in the next part of this series), there's no way around this limitation for Bluetooth at the moment. So make sure that your Bluetooth features are encapsulated properly if you want to ensure aspects like good testability of your app. Also, plan ahead for the manual testing efforts.</p> <h2>Conclusion</h2> <p>From a consumer's point of view, Bluetooth improvements in Windows Phone 8 are a bit disappointing at first glance, in particular because of the still missing HID profile support. However, on the other hand third-party developers now have access to the involved APIs and can achieve things that simply weren't possible before. All in all, this will likely result in a greater variety of features and richer apps. And I'm sure that future versions of the platform also will bridge the remaining gaps in Bluetooth profile support. </p> http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Bluetooth.aspx Tue, 05 Feb 2013 14:14:00 GMT Windows Phone 8: Protocol and File Type Associations <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone8 - Protocol & File Type Associations! #wpdev #wp8" data-url="http://slshow.net/XRFltE">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>In Windows Phone 7 we had several options to communicate with the outside world, for example using Web Services, HTTP or low-level communication using sockets. This already enabled a large field of possibilities for interesting apps. For example, I built a remote controlling component named PAARC [<a href="http://paarc.codeplex.com/">1</a>] on top of this to virtually communicate with and control any .NET application from your phone. However, despite these options support for a lot of alternate technologies was missing: app developers could not use well-established things like Bluetooth, support for new technologies like NFC was missing completely on the phones, and direct app-to-app communication on a single device was impossible. Windows Phone 8 improves all of these situations, and over the next three articles I'll take a deeper look at some of the new possibilities that have been added. This time, I'll concentrate on what options we have to enable a greater interaction between apps on the local device.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <h3>The Fundamental Problem</h3> <p>Apart from the fact that no APIs existed for it, direct app-to-app communication on Windows Phone 7 was impossible because the technical specification of the platform indirectly prevented it: there is no multi-tasking for third-party apps on Windows Phone 7. So simply because no two apps can run simultaneously it's not possible to establish direct communication between them. Let's put it out straight right in the beginning: this particular situation has not changed in Windows Phone 8. Your apps still get tombstoned, and no general purpose multi-tasking has been introduced. Yes, we do have some scenarios where apps can continue to run in the background (for example location tracking or VoIP apps), but even those very specialized apps have no access to APIs for direct, bi-directional communication with other apps.</p> <h3>What We Can Do</h3> <p>So what new ways of doing this <em>do</em> we have? The answer is: protocols and file type associations. The idea is to enable apps to indirectly interact with other apps on the same device by passing around small bits of information in some style of one-way communication. The involved concept really is nothing new and has existed on desktop systems in a very similar flavor for decades, so let's look at two simple examples to make this abstract description more understandable quickly:</p> <h4>Protocols Explained</h4> <p>Let's assume you receive an email from a friend in your favorite email client, for example Outlook. Your friend sends you a link to a cool web site he discovered in that email. When you click that link, what happens? Your web browser opens and loads the corresponding web site that the link points to. How does this work? Well, the web browser has registered with the operating system for a certain protocol, in this case HTTP(S), in the past (this is what happens behind the scene when a browser asks you whether it should become your default browser!). So when you click a hyperlink in an email, Outlook says "I don't know what to do with this, let's hand it over to the operating system". The operating system looks up if there's an application registered for the protocol the hyperlink is using, and then simply passes on the information (the web site the hyperlink points to) to that registered application, in this case let's say Internet Explorer. The following diagram shows this in more detail:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________________image_thumb_1.png" width="640" height="315" /></a></p> <p>What is the benefit of such a setup?</p> <ul> <li>Outlook can communicate with Internet Explorer <em>indirectly</em>, passing on all the required information to it.</li> <li>Outlook doesn't need to know <em>how</em> to do this, it simply lets the operating system do the heavy lifting.</li> <li>This system is extremely flexible. In fact, Outlook doesn't even know about Internet Explorer. If it's e.g. Chrome that has registered the protocol, the operating system will pass on the information to Chrome.</li> </ul> <p>So, for developers it's extremely simple to pass on information to other applications, because it always works in the exact same way and there's no need to e.g. learn the <em>specific</em> API of a <em>specific</em> application. You only need to know about the kind of data to send. On the other hand, developers also can register their own applications for protocols easily and by that integrate deeply into the operating system logic with little effort. And above all we have the user who is able to decide extremely flexibly who should handle which protocol, and it will all continue to work when they switch between different applications. Other URI samples for protocols are "mailto://" to launch your mail client or "skype://" to initiate a, well, Skype call.</p> <h4>File Associations Explained</h4> <p>In the very same way protocols work, applications can register for file extensions with the operating system as well. Let's return to the previous sample and say your friend sent you an email that contains a ZIP file attachment. When you click on that attachment, Outlook now says "I don't know what to do with this file, so let's hand it over to the operating system". The operating system in turn looks up the registration for the file extension of the attachment and then decides that it should pass the file on to e.g. 7-zip, which then knows how to open and extract the archive.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_thumb_2.png" width="640" height="315" /></a></p> <p>As you can see, the concept is the same as with protocols, but now we're dealing with file information instead of URIs that are passed around. Other samples for file associations are viewers that register for .PDF files or video players that register for .MP4 file extensions.</p> <p>All in all, dozens and dozens of registered file type associations and protocols create a very complex and highly dynamic network of indirect application relationships that can indeed look differently for each and every computer and user. </p> <h3>How It Works on Windows Phone</h3> <p>The concept of all this is virtually the same on Windows Phone 8, however there are two significant differences: </p> <ol> <li>The involved technical details obviously are different from what you may know from desktop systems. For example, instead of registering with the registry, the application manifest is used, and to trigger the operating system to invoke other apps you use the well-known platform concept of launchers.</li> <li>Certain limitations and restrictions apply. For example, Microsoft wants to make sure that the core user experience of the system stays consistent, and of course also that malicious apps cannot take over that core functionality. This means that you e.g. cannot register protocols that the system has already registered, and the same is true for file type associations. The drawback of this is that e.g. you cannot create a custom sound player that handles MP3 files globally.</li> </ol> <p>Let's dive into some samples now.</p> <h4>Registering for Protocols and File Type Associations</h4> <p>If you want to configure your app to handle a certain file extension or protocol, all you have to do is add the corresponding entries to an "Extensions" section (directly below the "Tokens" element) in the WMAppManifest.xml file of your project, like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd"><</span><span class="html">Extensions</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="kwrd"><</span><span class="html">FileTypeAssociation</span> <span class="attr">Name</span><span class="kwrd">="My File Type"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="attr">NavUriFragment</span><span class="kwrd">="fileToken=%s"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="attr">TaskID</span><span class="kwrd">="_default"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> <span class="kwrd"><</span><span class="html">Logos</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> <span class="kwrd"><</span><span class="html">Logo</span> <span class="attr">Size</span><span class="kwrd">="small"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> <span class="attr">IsRelative</span><span class="kwrd">="true"</span><span class="kwrd">></span>Assets/myFileType_33x33.png<span class="kwrd"></</span><span class="html">Logo</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="kwrd"><</span><span class="html">Logo</span> <span class="attr">Size</span><span class="kwrd">="medium"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> <span class="attr">IsRelative</span><span class="kwrd">="true"</span><span class="kwrd">></span>Assets/myFileType_69x69.png<span class="kwrd"></</span><span class="html">Logo</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="kwrd"><</span><span class="html">Logo</span> <span class="attr">Size</span><span class="kwrd">="large"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> <span class="attr">IsRelative</span><span class="kwrd">="true"</span><span class="kwrd">></span>Assets/myFileType_176x176.png<span class="kwrd"></</span><span class="html">Logo</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> <span class="kwrd"></</span><span class="html">Logos</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="kwrd"><</span><span class="html">SupportedFileTypes</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> <span class="kwrd"><</span><span class="html">FileType</span><span class="kwrd">></span>.myFileType<span class="kwrd"></</span><span class="html">FileType</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> <span class="kwrd"></</span><span class="html">SupportedFileTypes</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> <span class="kwrd"></</span><span class="html">FileTypeAssociation</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> <span class="kwrd"><</span><span class="html">Protocol</span> <span class="attr">Name</span><span class="kwrd">="myprotocol"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> <span class="attr">NavUriFragment</span><span class="kwrd">="encodedLaunchUri=%s"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> <span class="attr">TaskID</span><span class="kwrd">="_default"</span> <span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> <span class="kwrd"></</span><span class="html">Extensions</span><span class="kwrd">></span></pre> <!--CRLF--></div> </div> <p>Registering a protocol is easy: really all you have to define is the "Name" part of the element. This determines what is used as the protocol part of URIs. In the above sample, the "Name" attribute is set to "myprotocol", so corresponding URIs that will be matched to your app will look like "myprotocol:[additional content that is sent to your app]". The format and details of the additional content is up to you to define. The other information ("NavUriFragment" and "TaskID") must have the exact values shown here.</p> <p>For file type associations you need to provide both a (descriptive) name as well as a list of supported file types that contains at least one entry (maximum is 20 by the way). Here you can specify which file extensions your application should be invoked for. Please note that the extension definition must include the dot. Optionally you can use the "Logos" element to provide icons that are used when files of your file type are displayed in other apps, for example in the web browser or email app. Again, most of the attribute values have to have the exact values shown here to work, like the "NavUriFragment" that needs to be set to "fileToken=%s". </p> <p>More information on setting up your application for protocols and file types can be found on MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987(v=vs.105).aspx">2</a>]. As mentioned above, you cannot register all protocols and file types at will; a lot of them are reserved by the operating system. A list of these can also be found on MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207065(v=vs.105).aspx">3</a>].</p> <h4>Receiving Data</h4> <p>Receiving data works similarly for both scenarios: the user taps on a link containing your registered protocol or a file with your registered file extension, and the operating system will launch your app, passing on the required data. To process that data, you need to set up a URI mapper in your app and handle what is passed on. Here is a sample snippet for this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">internal</span> <span class="kwrd">class</span> CustomUriMapper : UriMapperBase</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="kwrd">public</span> <span class="kwrd">override</span> Uri MapUri(Uri uri)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> var tempUri = HttpUtility.UrlDecode(uri.ToString());</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> <span class="kwrd">if</span> (tempUri.Contains(<span class="str">"myprotocol:"</span>))</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> <span class="rem">// app was launched using our protocol</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="rem">// extract additional information</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> var parameters = ExtractUriParameters(tempUri);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="rem">// pass data on to a page in the app</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> <span class="kwrd">return</span> <span class="kwrd">new</span> Uri(<span class="str">"/MainPage.xaml?Data="</span> + parameters, UriKind.Relative);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> <span class="kwrd">if</span> (tempUri.Contains(<span class="str">"FileTypeAssociation"</span>))</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> <span class="rem">// a file token has been passed on to the app</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> <span class="rem">// extract file id</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> var fileIdIndex = tempUri.IndexOf(<span class="str">"fileToken="</span>) + 10;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum21"> 21:</span> var fileId = tempUri.Substring(fileIdIndex);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum22"> 22:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum23"> 23:</span> <span class="rem">// open another page in the app</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum24"> 24:</span> <span class="kwrd">return</span> <span class="kwrd">new</span> Uri(<span class="str">"/HandleFile.xaml?FileToken="</span> + fileId);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum25"> 25:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum26"> 26:</span> <span class="kwrd">else</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum27"> 27:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum28"> 28:</span> <span class="rem">// normal app launch, simply pass through the uri</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum29"> 29:</span> <span class="kwrd">return</span> uri;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum30"> 30:</span> }</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum31"> 31:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum32"> 32:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum33"> 33:</span> <span class="rem">// additional methods</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum34"> 34:</span> }</pre> <!--CRLF--></div> </div> <p>As you can see, the sample distinguishes between three situations. First of all there's the trivial case of a normal app launch that simply passes on the received URI (typically this will point to your app's entry page). If however the app is launched using a link with the registered protocol, you need to extract the data from the URI and make something meaningful out of it. You can for example then decide what sub page you want to launch, depending on that information.</p> <p>When the application is launched as a result of a file type association, things become a bit more complex. The sample shows how to extract the file Id from the URI and pass it on to a separate page of the application. This Id can then be used in conjunction with the new SharedStorageAccessManager class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.storage.sharedaccess.sharedstorageaccessmanager(v=vs.105).aspx">3</a>] for further processing. It's important to realize that you are not able to directly modify files that have been passed on to your app this way. This means that your app can never get direct access to an attachment that resides in the email client, for example. Instead, to do something meaningful with that file, you need to copy it to your own app's storage first, using the said shared storage access manager [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.storage.sharedaccess.sharedstorageaccessmanager.copysharedfileasync(v=vs.105).aspx">4</a>].</p> <p>To actually use this URI mapper in your application you need to set the corresponding property on the root frame. For the default templates, a good place would be the "InitializePhoneApplication" method in App.xaml.cs:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________________image_2.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________________image_thumb.png" width="587" height="361" /></a></p> <p> </p> <h4>Launching Other Apps</h4> <p>To launch other apps and pass on custom data or files to them, you simply use the new Launcher class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/br241801.aspx">5</a>] that provides methods for both using a file or a URI. Here's a snippet for using a URI:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> async <span class="kwrd">void</span> LaunchApp(<span class="kwrd">string</span> data)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> var uri = <span class="kwrd">new</span> Uri(<span class="kwrd">string</span>.Format(<span class="str">"myprotocol:{0}"</span>, data));</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> var success = await Launcher.LaunchUriAsync(uri);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> }</pre> <!--CRLF--></div> </div> <p>Note that you can check the return value to see if launching the URI actually was successful or not. In the same way you can launch another app by file extension when you use the corresponding method. You obviously have to pass on a StorageFile instance for that:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> async <span class="kwrd">void</span> LaunchApp(StorageFile file)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> var success = await Launcher.LaunchFileAsync(file);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> }</pre> <!--CRLF--></div> </div> <p>Not only third-party apps use this mechanism. In my last article on the new live tile and lock screen features [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx">6</a>] I demonstrated how the Launcher class can be used to navigate the user to built-in screens of the operating system itself. I used a URI of "ms-settings-lock:" to open the settings app with the lock screen options.</p> <p>Of course, launching other apps does not only work programmatically. If for example the user taps a link or file on a web site, the email client or other areas of the phone, registered apps will be launched in a similar way, just as explained in the initial part of this article.</p> <h3>Additional Notes</h3> <p>There are some additional details worth mentioning. For example, when a user wants to open a file or launch an app using a protocol but does not have a suitable app for it installed, Windows Phone will go out to the store and retrieve a list of applications that can handle the request. The user then can choose whether they want to install any of the available apps. When you submit an app to the Windows Phone Store that registers for a protocol or file type, it will be automatically added as an option to that list. That's pretty comfortable for users and also convenient for developers.</p> <p>Another thing is that if the user has installed multiple apps that can handle the same protocol or file extension, they will be presented with a list of these installed apps and then can choose which one to use as target when they e.g. click on a corresponding link or file. So multiple applications acting as similar targets can co-exist on the same device. One drawback is that once multiple apps for the same file type are installed, your logos (see above) won't show up anymore (how should the operating system decide which logo to show?).</p> <h3>Conclusion</h3> <p>Registering for protocols and file types is not exactly highly sophisticated or even duplex app-to-app communication. However it enables a whole lot of new scenarios for app developers and finally provides the possibility to deeply integrate with the system and provide even more comfortable features to the user.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Protocol-and-File-Type-Associations.aspx Wed, 30 Jan 2013 13:12:00 GMT Windows Phone 8: Live Tiles and Lock Screen <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Live Tiles and Lock Screen! #wpdev #wp8" data-url="http://slshow.net/Tl36ii">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/WP8-Webinar-Part-2.aspx">Recording of webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>The most prominent change in Windows Phone 8 (and 7.8 for that matter), because it's immediately visible to everyone at first glance, is the redesigned start screen with the new sizes for live tiles. In Windows Phone 7, the only option we had were square-sized tiles. Yes, phones had large landscape tiles too (for example for the pictures app), however these were not accessible to third-party developers. With Windows Phone 8, we now have three available sizes for tiles at hand, and we also can choose between multiple templates to get different looks more easily. Best of all, as we will see in this article you can even make use of a lot of the new tile features even if your app does not target Windows Phone 8 or 7.8, but only 7.1. Another feature that is tightly related to tiles (even though it may not seem like that at first) is the new lock screen notification options that we will look at in the second half of this article.</p> <h3>New Tile Sizes</h3> <p>In addition to the tile size we are used to from Windows Phone 7 (which is now named the "medium" size), Windows Phone 8 comes with two additional sizes, small and wide:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_thumb_1.png" width="456" height="456" /></a></p> <p>When you create a new Windows Phone 8 app, you can choose the kind of support for tiles in your app comfortably by editing the WMAppManifest.xml (look for the tile options on the "Application UI" tab). Providing support for the small and medium size tiles is mandatory, but you can choose whether you want to support wide tiles or not explicitly:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_thumb_2.png" width="615" height="215" /></a></p> <p>Depending on your settings here, the user can then freely select the size of the tile when they pin your app to the start screen:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_8.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_thumb_3.png" width="480" height="488" /></a></p> <p>Apart from the title and background image, you can also work with other properties to change the appearance of your tile. This concept is not new; in Windows Phone 7 we already could create tiles that had a front and a back site, and we were able to set a counter value that showed as small overlay. In Windows Phone 8 however, we have a choice of multiple available templates that have distinct properties to create unique tile designs.</p> <h3>The New Tile Templates</h3> <p>The tile format we have in Windows Phone 8 that is closest to what we are used to from 7.1 is called "flip tile". It provides the same properties as before, but additionally now supports the small and wide sizes.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________image_12.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________image_thumb_5.png" width="584" height="506" /></a>One detail that you will realize with the new tile formats is that the involved physical sizes are significantly different from before. In Windows Phone 7 the tile size already was a somewhat unconventional 173x173 pixels. The corresponding medium tile size in Windows Phone 8 is 336x336 pixels. This is a side effect of the newly supported higher screen resolutions we have in Windows Phone 8, something you can read about in one of my articles here on SilverlightShow in detail [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx">1</a>]. For smaller resolutions like WVGA, the content of the tile is scaled down automatically. You as a developer always have to provide the largest theoretical size required. Please see below for a table that lists all content sizes, depending on the tile template.</p> <p>The second template available lets you cycle through up to 9 images from the local app installation. It's hence named "Cycle Template":</p> <p><img style="margin-right: auto; margin-left: auto; float: none; display: block;" alt="Windows Phone CycleTiles_ Tile template properties" src="http://i.msdn.microsoft.com/dynimg/IC601179.png" /></p> <p>Finally, there is the "Iconic Template" that makes it easier for you to style your tile for the plain and simple design language inherent to the phone platform:</p> <p><img style="margin-right: auto; margin-left: auto; float: none; display: block;" alt="Windows Phone Iconic Tile template properties" src="http://i.msdn.microsoft.com/dynimg/IC625725.png" /></p> <p style="text-align: center;">(Tile template images taken from MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202948(v=vs.105).aspx">2</a>])</p> <p>Due to the multiple tile sizes, you now also have to provide differently sized images for all the tiles your application supports. Since supporting small and medium sizes is mandatory, that would be at least two images. In detail:</p> <table cellspacing="0" cellpadding="2" width="400" border="1"> <tbody> <tr> <td valign="top" style="width: 133px;"> </td> <td valign="top" style="width: 133px;"><strong>Flip tile/Cycle tile</strong></td> <td valign="top" style="width: 133px;"><strong>Iconic tile</strong></td> </tr> <tr> <td valign="top" style="width: 133px;"><strong>Small*</strong></td> <td valign="top" style="width: 133px;">159x159</td> <td valign="top" style="width: 133px;">110x110</td> </tr> <tr> <td valign="top" style="width: 133px;"><strong>Medium*</strong></td> <td valign="top" style="width: 133px;">336x336</td> <td valign="top" style="width: 133px;">202x202</td> </tr> <tr> <td valign="top" style="width: 133px;"><strong>Wide</strong></td> <td valign="top" style="width: 133px;">691x336</td> <td valign="top" style="width: 133px;">no additional image</td> </tr> </tbody> </table> <p>*=mandatory</p> <h3>How to Use the New Tiles</h3> <p>In the introductory part we've already seen how you can statically define the tile images to use in the WMAppManifest.xml editor. This of course is the most comfortable way to do this, and the editor adapts automatically depending on what template you choose.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_10.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________________image_thumb.png" width="300" height="88" /></a></p> <p>For example, when you switch to the Cycle template, you are now free to select up to 9 images in the editor:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_14.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_thumb_4.png" width="484" height="411" /></a></p> <p>When you take a look at the generated XML, you can see how the tile data is declared behind the scenes:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_18.png"><img title="image" style="margin: 5px auto; float: none; display: block; background-image: none; border-width: 0px; border-style: solid;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______image_thumb_7.png" width="684" height="487" /></a></p> <p>Here you could change more of the available options if you wanted. However, a lot more interesting is the possibility to change tile properties in code dynamically. This is where the real power of tiles comes from, when you change the content and information that is shown on tiles depending on e.g. the data available in your application. And of course only manipulating tile data programmatically lets you work with multiple (secondary) tiles. A typical use case for these tiles is a weather app for example, that can show data specific to a certain location on a separate tile. It can also use the tile as a direct entry point to a specific part of the application for the user, without the need to navigate through the normal menu and application structure first. Again this concept is nothing new for Windows Phone developers, however the new tile types of course add new classes we have to work with to interact with them. For example, to set up a new flip tile, you can write code like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> PinToStartScreenButton_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> var navigationUri = <span class="kwrd">new</span> Uri(<span class="str">"/MainPage.xaml"</span>, UriKind.Relative);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> var flipTileData = <span class="kwrd">new</span> FlipTileData</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> BackgroundImage = <span class="kwrd">new</span> Uri(<span class="str">"/Assets/Tiles/FlipCycleTileMedium.png"</span>, UriKind.Relative),</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> SmallBackgroundImage = <span class="kwrd">new</span> Uri(<span class="str">"/Assets/Tiles/FlipCycleTileSmall.png"</span>, UriKind.Relative),</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> Title = <span class="str">"Demo Tile"</span>,</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> Count = 42</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> };</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="rem">// check if tile exists first</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> var tile = ShellTile.ActiveTiles</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> .Where(t => t.NavigationUri == navigationUri)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> .FirstOrDefault();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum17"> 17:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum18"> 18:</span> <span class="rem">// create or update tile</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum19"> 19:</span> <span class="kwrd">if</span> (tile == <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum20"> 20:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum21"> 21:</span> <span class="rem">// create a new tile</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum22"> 22:</span> ShellTile.Create(navigationUri, flipTileData, <span class="kwrd">true</span>);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum23"> 23:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum24"> 24:</span> <span class="kwrd">else</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum25"> 25:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum26"> 26:</span> tile.Update(flipTileData);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum27"> 27:</span> }</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum28"> 28:</span> }</pre> <!--CRLF--></div> </div> <p>The snippet also shows how to check for existing tiles, so you don't create multiple versions of the same tile over and over again. Instead, you can use the "Update" method of the "ShellTile" class to change the content of an existing tile. One thing that's really important is that you need to use the specific overload of the "Create" method that takes a third (boolean) argument [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207919(v=vs.105).aspx">3</a>] when you use one of the new tile data classes. That third argument indicates whether you support the new wide tile size or not. If you try to use the other, previously existing "Create" overload with one of the new tile data types, you'll receive an exception – it's only allowed to use the old Windows Phone 7 standard tile data class with it.</p> <p>In addition to the "FlipTileData" [<a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.shell.fliptiledata(v=vs.105).aspx">4</a>] shown above we of course also have the new types "CycleTileData" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.phone.shell.cycletiledata(v=vs.105).aspx">5</a>] and "IconicTileData" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.phone.shell.iconictiledata(v=vs.105).aspx">6</a>] now.</p> <h3>Using the New Tiles in Windows Phone 7.1 Apps</h3> <p>If your app does not target Windows Phone 8 exclusively but is designed to work on Windows Phone 7.1, you can use the power of reflection to still support the new tiles without breaking support for the older operating system version. This is a nice compromise for developers who only would like to use these new visual features but on the other hand don't want to lock out the existing user base of Windows Phone 7.1 (or maintain multiple app versions just for that). The very same concept of reflection is used to support the new live tiles on devices that run version 7.8 of Windows Phone. Following the logic shown below hence covers both use cases:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_26.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_thumb_11.png" width="442" height="646" /></a></p> <p>To make this work you also have to manually change the WMAppManifest.xml and add a separate element prior to the "App" element for this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd"><</span><span class="html">AppExtra</span> <span class="attr">xmlns</span><span class="kwrd">=""</span> <span class="attr">AppPlatformVersion</span><span class="kwrd">="8.0"</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="kwrd"><</span><span class="html">Extra</span> <span class="attr">Name</span><span class="kwrd">="Tiles"</span><span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="kwrd"></</span><span class="html">AppExtra</span><span class="kwrd">></span></pre> <!--CRLF--></div> </div> <p>Obviously working with reflection, dynamically creating types and invoking properties, is not that much fun, but it's also not as bad as it sounds. A separate page on the MSDN documentation has straight-forward sample code to get you started, and also talks at length about what limitations you have to consider when you work with the new tiles that way [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj720574(v=vs.105).aspx">7</a>].</p> <p>By the way, Microsoft has just released a Phone SDK update for version 7.8 [<a href="http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/22/now-available-windows-phone-sdk-update-for-7-8.aspx">8</a>] that adds additional emulators you can use to test how your 7.1 app tiles look like on 7.8 devices. The announcement of the SDK update was accompanied by an additional post that talks about this "light up" feature a bit more in detail [<a href="http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/22/windows-phone-7-8-and-windows-phone-8-live-tile-light-up-for-windows-phone-os-7-1-apps.aspx">9</a>]. And even if you don't feel comfortable with reflection at all, don't worry. First projects are already starting to show up to help you wrap the involved bits comfortably, like the Mangopollo project [<a href="http://mangopollo.codeplex.com/">10</a>].</p> <h3>The Lock Screen</h3> <p>The other very prominent visual change on Windows Phone 8 is the fact that applications now can tightly integrate with the lock screen functionality. Your app can act as a provider for lock screen background images, a custom text, as well as appear with a counter value there, to give the user a quick hint e.g. when new data is available in your app. These features were limited to the built-in apps (phone, texts, calendar, email etc.) before, now third party developers can offer the same features with their own apps.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___image_22.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_thumb_9.png" width="300" height="500" /></a></p> <p>To support these features, you have to specify them in your WMAppManifest.xml file. There are separate entries for each one of the available options, to be provided in an "Extensions" element below the "Tokens" element:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd"><</span><span class="html">Extensions</span><span class="kwrd">></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="rem"><!-- Use this entry to indicate background image provider support --></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> <span class="kwrd"><</span><span class="html">Extension</span> <span class="attr">ExtensionName</span><span class="kwrd">="LockScreen_Background"</span> </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> <span class="attr">ConsumerID</span><span class="kwrd">="{111DFF24-AA15-4A96-8006-2BFF8122084F}"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> <span class="attr">TaskID</span><span class="kwrd">="_default"</span> <span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> <span class="rem"><!-- Use this entry to indicate icon counter notification support --></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> <span class="kwrd"><</span><span class="html">Extension</span> <span class="attr">ExtensionName</span><span class="kwrd">="LockScreen_Notification_IconCount"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="attr">ConsumerID</span><span class="kwrd">="{111DFF24-AA15-4A96-8006-2BFF8122084F}"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> <span class="attr">TaskID</span><span class="kwrd">="_default"</span> <span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="rem"><!-- Use this entry to indicate text notification support --></span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> <span class="kwrd"><</span><span class="html">Extension</span> <span class="attr">ExtensionName</span><span class="kwrd">="LockScreen_Notification_TextField"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> <span class="attr">ConsumerID</span><span class="kwrd">="{111DFF24-AA15-4A96-8006-2BFF8122084F}"</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="attr">TaskID</span><span class="kwrd">="_default"</span> <span class="kwrd">/></span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> <span class="kwrd"></</span><span class="html">Extensions</span><span class="kwrd">></span></pre> <!--CRLF--></div> </div> <p>If you want to make use of the counter notifications, you additionally need to provide an icon that is shown together with the actual counter value. It can only contain white pixels on a transparent background and needs to be a 38x38 pixels PNG file that you have to specify in the "DeviceLockImageURI" element of your primary tile:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd"><</span><span class="html">DeviceLockImageURI</span> <span class="attr">IsRelative</span><span class="kwrd">="true"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="attr">IsResource</span><span class="kwrd">="false"</span><span class="kwrd">></span>Assets\LockImage.png<span class="kwrd"></</span><span class="html">DeviceLockImageURI</span><span class="kwrd">></span></pre> <!--CRLF--></div> </div> <p>The fact that you have to add this information to the <em>tile</em> data of your app already is a hint that the notification data on the lock screen really is only another view of the information on your (pinned) primary tile. The lock screen data is directly extracted from there. Hence, updating what the user sees on the lock screen comes down to simply updating the tile:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var primaryTile = ShellTile.ActiveTiles.FirstOrDefault();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> <span class="kwrd">if</span> (primaryTile != <span class="kwrd">null</span>)</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> var tileData = <span class="kwrd">new</span> FlipTileData</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> {</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> Count = 42, </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> BackContent = <span class="str">"Demo text"</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> };</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> primaryTile.Update(tileData);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> }</pre> <!--CRLF--></div> </div> <p>As you can see in the above screenshot, the "Count" value is used for the small icon indicator, the "BackContent" of your tile will be mapped to the custom text that is displayed.</p> <h4>User Consent</h4> <p>One important thing is that you cannot set your app as lock screen data provider programmatically. This follows the usual concept of the phone platform where certain actions can only be performed with user consent or even by the user manually. In the case of notifications, the user has to set your app as one of the data providers in the "lock screen" system settings:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_24.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_thumb_10.png" width="300" height="500" /></a></p> <p>What you can do however, is navigate the user to that screen programmatically, to make it easier for them to discover the corresponding options in the system settings. The code for this simply looks like:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="kwrd">private</span> async <span class="kwrd">void</span> NavigateToLockScreenSettingsButton_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> await Windows.System.Launcher.LaunchUriAsync(<span class="kwrd">new</span> Uri(<span class="str">"ms-settings-lock:"</span>));</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> }</pre> <!--CRLF--></div> </div> <p>If your application wants to act as a lock screen image provider, you have more options; in particular, you can use the "LockScreenManager" class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662989(v=vs.105).aspx">11</a>] to request the required user consent directly. There's a more sophisticated example available on MSDN that also shows how to use this class in conjunction with the "LockScreen" class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.system.userprofile.lockscreen(v=vs.105).aspx">12</a>] to actually manage the image handling from within your app [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206968(v=vs.105).aspx">13</a>].</p> <h3>Conclusion</h3> <p>Both the new lock screen and tile features proof that it's possible to open the phone platform to more customization options without giving up or sacrificing the consistent and unique user experience of Windows Phone. For you as a developer the new features make it possible to add functionality to your app that a lot of users have been waiting for, in particular integrating more deeply with the core notification elements of the system. Combined with existing concepts like push notifications this allows to build exciting apps and experiences.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Live-Tiles-and-Lock-Screen.aspx Wed, 23 Jan 2013 14:20:00 GMT Windows Phone 8: Contacts Integration <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Contacts Integration! #wpdev #wp8" data-url="http://slshow.net/W3bb7v">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/news/Free-SilverlightShow-Webinar-Deeper-Dive-into-the-Windows-Phone-8-SDK.aspx">Join today's webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>One of the cool features of Windows Phone from the start has been its tight and seamless integration of various sources into common and central places on the phone, like the people hub.</p> <p>To this end, multiple contact entries can be and often even are automatically linked together so information from different origin like Facebook, Twitter or Outlook is aggregated and merged into a single profile. However, this mechanism of deep integration was something that was managed by the operating system and first party apps. As developer, you had no chance of using similar features from within your own apps. With Windows Phone 8, Microsoft has improved this and added a way for us developers to integrate with a user's contacts list.</p> <h3>Contact Stores</h3> <p>In Windows Phone 7, what you could do was use the "SaveContactTask" class [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.phone.tasks.savecontacttask(v=vs.105).aspx">1</a>] located in the namespace Microsoft.Phone.Tasks to initiate the creation of a new contact. The entry could be pre-populated with data from your app, however just like with any other task or chooser the user is redirected to the corresponding default system dialog for the intended action, and only if they chose to save the contact was the data actually persisted:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var task = <span class="kwrd">new</span> SaveContactTask();</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> task.FirstName = <span class="str">"Ewald"</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> task.LastName = <span class="str">"Kratzkopp"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> task.Show();</pre> <!--CRLF--></div> </div> <p>With Windows Phone 8, Microsoft introduces a new concept of "custom contact stores" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207034(v=vs.105).aspx">2</a>]. In addition to the read-only access to the user's contact list and the above demonstrated way to use a separate task for creating new entries (both of which available in 7.x) we now are able to write our own data to the people hub silently and without user consent. However apps still cannot manipulate existing contacts that originate from somewhere else. In this sense, the data that belongs to an app is somewhat isolated from the rest. This concept is what is described as contact store – each app can have its own, writable part of the global contacts, but can only read from the rest. Which details of its own contacts can be consumed by other apps is decided by the app itself. However, the minimum setting is to allow reading the description and retrieving the associated display image, so you cannot completely hide your entries from the rest of the world.</p> <p>Getting access to a contact store is easy. First you need to specify the ID_CAP_CONTACTS capability in your app's manifest. If you fail to do so, the actions that follow will result in an InvalidAccessException.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________image_10.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_thumb_4.png" width="330" height="121" /></a></p> <p> </p> <p>Now you can use the corresponding class in the Windows.Phone.PersonalInformation namespace [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207747(v=vs.105).aspx">3</a>], in particular its static method to create a new contact store or open it if it already exists:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var contactStore = await ContactStore.CreateOrOpenAsync(</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> ContactStoreSystemAccessMode.ReadWrite, </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> ContactStoreApplicationAccessMode.LimitedReadOnly);</pre> <!--CRLF--></div> </div> <p>The two options that you can optionally pass in control how others can interact with your contacts: whether the system can only read or also write to your contacts and second, whether other apps will be able to read the full data from your contact entries or only the minimum set of information. Please note that the "system" rights directly affect whether the user is able to manipulate a contact through the phone's common UI in the people hub. If you specify "ReadOnly" here, the user won't be able to delete contacts you added, and they will not be able to edit existing data, only add additional information (which is achieved through another linked contact):</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_8.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_thumb_3.png" width="478" height="304" /></a></p> <p>Specifying "ReadWrite" on the other hand enables users not only to edit, but even to create completely new contacts in your contact store. In that case you should be careful not to assume any data always to be present and make sure everything is consistent with what you expect.</p> <p>Another important detail is that you cannot change the access rights of a contact store later on, or mix and match them as you wish, depending on the situation. When you have created a store once and e.g. set other applications' rights to "ReadOnly", then trying to downgrade the rights later by specifying "LimitedReadOnly" on successive opening will result in an ArgumentException. You can however use the "DeleteAsync" method on an existing store to remove it, and then start over with different access rights.</p> <p>With the contact store object, you can now create new and retrieve existing contacts easily.</p> <h3>Create New Contacts</h3> <p>Contact store entries are named (who would've thought that) stored contacts. The required class is located in the same namespace as the "ContactStore" class. To create a new contact, you have to pass in the store object the contact will be located in to the constructor of the "StoredContact" class. Optionally you can also use an existing "ContactInformation" instance to pre-populate the new entry, which also allows to e.g. import data from vCards [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.personalinformation.contactinformation.parsevcardasync(v=vs.105).aspx">4</a>]. However, it's possible to set all properties manually after creation, as shown in the following snippet:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="rem">// create the contact store</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> var contactStore = await ContactStore.CreateOrOpenAsync(</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> ContactStoreSystemAccessMode.ReadWrite, </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> ContactStoreApplicationAccessMode.LimitedReadOnly);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> <span class="rem">// create a new contact</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> var storedContact = <span class="kwrd">new</span> StoredContact(contactStore);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> storedContact.GivenName = <span class="str">"Ewald"</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> storedContact.FamilyName = <span class="str">"Kratzkopp"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> <span class="rem">// set additional properties</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> var properties = await storedContact.GetPropertiesAsync();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> properties[KnownContactProperties.Email] = <span class="str">"kratzewald@example.com"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum15"> 15:</span> <span class="rem">// save the new contact</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum16"> 16:</span> await storedContact.SaveAsync();</pre> <!--CRLF--></div> </div> <p>The code is pretty straight-forward. One noteworthy detail is that the properties on the contact object itself only provide direct access to a very limited set of data, like the name. To access and manipulate other common properties, you have to use the "GetPropertiesAsync" method to retrieve a dictionary. The "KnownContactProperties" class helps you using common keys in a type-safe manner, like "Email" above. There's also an "GetExtendedProperties" method that allows you to provide your own properties that are unrelated to the common data typically found on the phone.</p> <p>The nice thing about contacts that are added to your apps contact store is that the usual mechanism of the platform still apply. This means that e.g. entries you create are auto-linked to existing entries if applicable, or can be linked by the user manually if they decide to. From the above example, the email address I specified is merged with an existing contact I had created on the phone manually before:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________________image_2.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________________image_thumb.png" width="480" height="800" /></a></p> <p>This allows you to e.g. use the new and the existing read-only APIs in combination to create the illusion that you actually extend existing contacts, if you want.</p> <p>Please note that if your app creates and saves an entry repeatedly it will not magically be merged with existing ones (by name, for example), and this will also not result in errors. These multiple entries hence will appear as separate entities in the contacts list. Because the entries typically will be auto-linked this behavior might not be obvious at a quick glance, but becomes apparent on the detail page:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_thumb_2.png" width="448" height="597" /></a></p> <p>To solve this, you should search for existing contacts first and edit them, instead of blindly creating new entries.</p> <h3>Working with Existing Contacts</h3> <p>When you save a new contact, it will be assigned an Id that you can use to easily retrieve the contact later on:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> var existingContact = await contactStore.FindContactByIdAsync(<span class="str">"{8.30001.3}"</span>);</pre> <!--CRLF--></div> </div> <p>This requires you to retrieve and store the Id that the phone assigns though. You can also turn this mechanism upside down and provide your own Id when you create the contact, for example taken from your database or some other internal data structure. This Id needs to be stored in the "RemoteId" property, because the phone still generates its own Id. It's your responsibility to ensure that your Ids are unique; creating multiple entries with the same Id results in an exception. To lookup existing entries, you then use the corresponding "FindContactByRemoteIdAsync" method of the contact store.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="rem">// create a new contact</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> var storedContact = <span class="kwrd">new</span> StoredContact(contactStore);</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> storedContact.GivenName = <span class="str">"Ewald"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> storedContact.FamilyName = <span class="str">"Kratzkopp"</span>;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> storedContact.RemoteId = <span class="str">"MyId"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> await storedContact.SaveAsync();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> <span class="rem">// the Id property of storedContact now contains the auto-generated Id</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span>  </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span> <span class="rem">// later: re-load the contact by external Id</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> var existingContact = await contactStore.FindContactByRemoteIdAsync(<span class="str">"MyId"</span>);</pre> <!--CRLF--></div> </div> <p>Another way of accessing existing contacts is to use a contact query. This allows you to access all of your app's contacts and offers additional options like specifying the sort order and performing paging. Here is an example:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="lnum" id="lnum1"> 1:</span> <span class="rem">// set some query options</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum2"> 2:</span> var queryOptions = <span class="kwrd">new</span> ContactQueryOptions();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum3"> 3:</span> queryOptions.DesiredFields.Add(KnownContactProperties.Email);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum4"> 4:</span> queryOptions.OrderBy = ContactQueryResultOrdering.FamilyNameGivenName;</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum5"> 5:</span> </pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum6"> 6:</span> <span class="rem">// create and execute the query</span></pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum7"> 7:</span> var contactQuery = contactStore.CreateContactQuery(queryOptions);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum8"> 8:</span> var contactCount = await contactQuery.GetContactCountAsync();</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum9"> 9:</span> var contacts = await contactQuery.GetContactsAsync(0, contactCount);</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum10"> 10:</span>  </pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum11"> 11:</span> <span class="kwrd">foreach</span> (var contact <span class="kwrd">in</span> contacts)</pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum12"> 12:</span> {</pre> <!--CRLF--> <pre class="alt"><span class="lnum" id="lnum13"> 13:</span> <span class="rem">// do something</span></pre> <!--CRLF--> <pre class="alteven"><span class="lnum" id="lnum14"> 14:</span> }</pre> <!--CRLF--></div> </div> <p>The snippet also makes use of the "DesiredFields" property. This allows you to specify what properties of the contacts you are going to use after retrieving them. You still have to use the mechanism I've demonstrated above to access the values (using "GetPropertiesAsync"), however specifying the DesiredFields up front can result in a performance gain as no additional round-trips to the internal database might be needed later on.</p> <p>Once retrieved, you can manipulate its properties and save back the contact, or export them as vCard [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662986(v=vs.105).aspx">5</a>], for example.</p> <h3>Security Concerns</h3> <p>Let's talk a moment about security concerns that may arise from the new features. To a lot of people phrases like "write silently and without user consent", and "the user cannot delete contacts you create as read-only" sound alarmingly when we talk about a central store like the contacts, which are shared across the whole phone. What if an app decides to rampage and spam your phone with undesired entries? Well, of course the first frontier against things like these is Microsoft's validation process for apps in the Phone Store. But let's assume that a malicious app has made it through certification, and managed to flood your contact list with bogus entries.</p> <p>The good news is that unlike with the SaveContactTask that requires explicit user consent, entries that are generated using custom contact stores are automatically removed when the originating app is uninstalled. This means that as user you can easily get rid of everything an app has added to your global contacts list by removing the app in question, which I think is an acceptable and sufficient safety net to protect users.</p> <p>This behavior should also be a hint for you as a developer not to use contact stores as primary storage for important data. The data your app's contact entries are based on should always be stored e.g. in a back end like the cloud, to enable easy recovery and of course other scenarios like users migrating to other devices. To help you with this, custom contact stores support revisions and the retrieval of e.g. manual changes made by the user, so you can sync the local version with the one in your back end [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.personalinformation.contactstore.getchangesasync(v=vs.105).aspx">6</a>].</p> <h3>Conclusion</h3> <p>With the new concept of custom contact stores Microsoft managed to both open up new possibilities for developers as well as keep security and isolation of data on a high level. For the user, due to features like linked profiles, these security-related restrictions are almost invisible and do not come at a cost of comfort. Some apps (like Skype, for example) already actively make use of the new features, and I'm quite interested in what we'll see in this area in the coming months. Surprise us ;).</p> http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx Tue, 15 Jan 2013 15:06:00 GMT Windows Phone 8: Localization <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Localization! #wpdev #wp8" data-url="http://slshow.net/UCsXyx">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>With Windows Phone 8 the number of markets where users can get apps and games has been increased to a whopping 191 [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/help/jj215599(v=vs.105).aspx">1</a>]. And even with Windows Phone 7.8, by the time of writing 95 markets are available [<a href="http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/12/26/reflecting-on-2012-scale-and-opportunity.aspx">2</a>]. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/news/Free-SilverlightShow-Webinar-Deeper-Dive-into-the-Windows-Phone-8-SDK.aspx">Join the upcoming webinar: Deep Dive in Windows Phone 8 SDK</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> These are quite impressive numbers compared to the opportunities we had when Windows Phone was released initially. Naturally now topics like localization become more and more interesting even for smaller apps, to stimulate customers' interest outside the English-speaking world. Windows Phone supported this from the beginning, however the tooling was somewhat inferior to what we were used to from other Microsoft platforms. In Windows Phone 8, Microsoft has improved the developer experience for localization and made it significantly more comfortable to translate your applications to different languages. <h3>Globalization vs. Localization</h3> <p>Before we start with a hands-on walkthrough of how to localize your app, let's get some clearance on terms that are often mixed or not well understood by a lot of developers: globalization and localization. Here is what the MSDN documentation says on globalization [<a href="http://msdn.microsoft.com/en-us/library/aa292081(v=vs.71).aspx">3</a>]:</p> <blockquote> <p><em>"Globalization is the process of designing and developing a software product that functions in multiple cultures/locales."</em></p> </blockquote> <p>In other words: globalization ensures that your app will work in different languages and geographic areas with respect to the set of rules that are in place for the respective locale. These rules affect things like: date, time and number formatting, currencies, weight/measurement and other conventions as well as sorting rules. An example would be to display a number like "1.234" as "1,234" in a German environment, because in Germany the decimal separator is a comma, not a point. If you want to learn more on globalization, best practices on Windows Phone and the differences between 8.0 and 7.x, take a look at the MSDN documentation [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff637522(v=vs.105).aspx#BKMK_GlobalizingYourApplication">4</a>].</p> <p>Localization on the other hand is described as [<a href="http://msdn.microsoft.com/en-us/library/aa292137(v=vs.71).aspx">5</a>]:</p> <blockquote> <p><em>"The process of adapting a globalized application […] to a particular culture/locale. […] The localization process refers to translating the application user interface (UI) or adapting graphics for a specific culture/locale."</em></p> </blockquote> <p>In contrast to globalization where you ensure that your application adapts to the specific locale gracefully without the need for further action, localization is the step when you actually take your content and create specific versions of it for different locales. Typically this will involve the translation of strings and texts, but of course it's not limited to that. Localization also covers swapping icons and graphics or even sounds and other audio for particular cultures. </p> <p>Using hard-coded, constant strings or similar constructs prevents you from localizing your app efficiently. To enable your application for localization, you hence need to prepare it properly, for example by separating code and data in a nice way. In the following steps we will see how this can be done with a Windows Phone 8 app.</p> <h3>Getting Started</h3> <p>As I mentioned, one of the nice things about Windows Phone 8 is that the tooling around localization has improved a lot. No more editing of your project files in a text editor or similar manual steps, at least for the main tasks. In fact, when you create a new empty project, you already will be presented with a project structure set up for localization. Just remember to choose "Windows Phone OS 8.0" as target platform – the structure is not created with the 7.1 template, and it's also not added when you later decide to upgrade a 7.1 project to version 8.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_thumb_1.png" width="235" height="189" /></a></p> <p>The whole setup basically consists of three parts:</p> <ol> <li>For each supported culture, a resource file is located in the "Resources" folder (as seen in the screenshot above).</li> <li>A class named "LocalizedStrings" (again as seen in the screenshot) is created and used as a XAML binding helper construct.</li> <li>In the Application class' resources (in App.xaml) an instance of the "LocalizedStrings" helper class is created and provided globally so localized resources can be bound in XAML everywhere in your app:<a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_thumb_2.png" width="613" height="68" /></a></li> </ol> <p>Some hints to get you quickly started with localization based on these parts are located in the MainPage.xaml as a block of comments:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_8.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_thumb_3.png" width="657" height="246" /></a></p> <p>So basically, with the new template everything already is set up for you so you can start translating your app right away. Let's see how this is done.</p> <h3>First Steps</h3> <p>First of all, let's actually replace the currently hard-coded application title on the main page with the binding that is described in the above comment section. In the following screenshot, I've left the original version in XAML as a comment for comparison:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________image_10.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________image_thumb_4.png" width="640" height="96" /></a></p> <p>As you can see in the second binding I'm setting up, we have nice IntelliSense support for the available resources, and the tooltip even provides me with a preview of what the result will look like ("… similar to Hallo World!"). The "Hallo World!" part is taken from the "AppResources.resx" file where I have added the "MainPageTitle" entry like this:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______image_12.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________image_thumb_5.png" width="307" height="177" /></a>Two things are worth noting here: first of all there are some special entries listed here: "ResourceLanguage" and "ResourceFlowDirection". These two are used in "App.xaml.cs" in code to set the language and flow direction property of the top-level element in your UI:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_14.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_thumb_6.png" width="695" height="301" /></a></p> <p>Usually you don't need to change that code or worry about it. All you need to know is that all your resource files need to have these two entries as sort of a self-description so the UI bits can be set up automatically. We'll see how this works for additional languages in a moment.</p> <p>The second important thing to remember is that the "AppResources.resx" which has been created automatically is a special resource file that denotes the neutral language. The entries you make here are used whenever no resource for the current culture is found. That means that if someone e.g. uses German with their phone, but you haven't provided German resources, the entries from this file will be used as fallback. All additional resource files that you create will be specific to a certain culture and also technically a bit different (see below). The actual language that is used as neutral language can be set in the "Assembly Information" dialog in the project properties (tab "Application"):</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_18.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_thumb_8.png" width="406" height="388" /></a></p> <p>With everything above in place, you will see that the app indeed resolves the two bindings to what we have entered in the resource file when you run it:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_16.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_thumb_7.png" width="424" height="139" /></a></p> <h3>Adding A New Supported Culture</h3> <p>The interesting part of course starts when you add additional supported cultures. With the new tooling, this is easier than ever. Just open the project properties of your Windows Phone app and navigate to the "Application" tab. There you will find a "Supported Cultures" section at the bottom. Let's add German to the list of cultures that the app supports:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_20.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___image_thumb_9.png" width="373" height="273" /></a>As soon as you hit the save button for your project, you will see that a new resource file has been created automatically for you. The technical difference is that no code-behind (.Designer.cs) file has been created for it. This is the usual localization mechanism that is no different from other .NET platforms.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_22.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___image_thumb_10.png" width="237" height="222" /></a>Behind the scenes, the "SupportedCultures" node of the project file is edited also, something that you had to do manually in previous versions of the Windows Phone tooling. </p> <p>The new resource file contains copies of all the entires of the neutral language resource file, but the language and flow direction values have been adjusted automatically to fit your selection. Now you can change the values of the remaining entries to appropriate translations:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_26.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_thumb_12.png" width="276" height="177" /></a>To test the new culture, you can switch your phone or the emulator to a different language in the "Settings" area (which requires a restart). Once switched to German, the app indeed presents a translated UI:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_28.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_thumb_13.png" width="368" height="140" /></a>Of course you can still override the auto-detected culture by setting it in code, like:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">Thread.CurrentThread.CurrentUICulture = <span class="kwrd">new</span> CultureInfo(<span class="str">"en-US"</span>);</pre> <!--CRLF--></div> </div> <p>This enables you to allow the user to choose a different language from their phone settings. Naturally you would store such a preference in some user-specific configuration data instead of hard-coding it.</p> <h4>Additional Improvements</h4> <p>One thing to note is that culture settings are thread specific. Until now you had to set up your desired culture data for each thread you were using manually. With Windows Phone 8, two new static properties have been added to the CultureInfo class: DefaultThreadCurrentCulture [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.globalization.cultureinfo.defaultthreadcurrentculture(v=vs.105).aspx">6</a>] and DefaultThreadCurrentUICulture [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.globalization.cultureinfo.defaultthreadcurrentuiculture(v=vs.105).aspx">7</a>]. This lets you set the default cultures used on an AppDomain level so you don't have to worry anymore about situations where subtle culture-related errors may arise from multi-threading scenarios.</p> <h3>… And The Ugly</h3> <p>Despite the comfortable improvements with Windows Phone 8 and Visual Studio 2012, there are still some areas where localization of  Windows Phone apps is a bit more complex than you might expect. Especially those details that integrate more deeply with the underlying (native) system are not exactly obvious to set up. Two of these you inevitably will run into when you localize your app:</p> <h4>The Application Bar</h4> <p>Just like in Windows Phone 7, the application bar elements like the ApplicationBarIconButton and the ApplicationBarMenuItem do not support data binding of their fundamental properties like "Text". This means that you need to create and set up these elements in code manually to support localized content, like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// Set the page's ApplicationBar to a new instance of ApplicationBar.</span></pre> <!--CRLF--> <pre class="alteven">ApplicationBar = <span class="kwrd">new</span> ApplicationBar();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="rem">// Create a new button and set the text value to the localized string from AppResources.</span></pre> <!--CRLF--> <pre class="alt">var appBarButton = <span class="kwrd">new</span> ApplicationBarIconButton(</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">new</span> Uri(<span class="str">"/Assets/AppBar/appbar.add.rest.png"</span>, UriKind.Relative)</pre> <!--CRLF--> <pre class="alt"> );</pre> <!--CRLF--> <pre class="alteven">appBarButton.Text = AppResources.AppBarButtonText;</pre> <!--CRLF--> <pre class="alt">ApplicationBar.Buttons.Add(appBarButton);</pre> <!--CRLF--></div> </div> <p>This snippet is taken from the commented hints that are created by the default project template in your project's MainPage.xaml.cs.</p> <p>One way to elegantly work around this issue and avoid code is to make use of the available frameworks that support bindable application bar elements in XAML. If you are using MVVM as design pattern for your app you probably already have decided for a supporting MVVM framework – take a look at its documentation, most of them come with bindable application bar replacements out of the box.</p> <h4>The App Title</h4> <p>The application title that is used in the application list on the phone (including the texts used for the live tiles) is another example of a rather tedious process that is involved when you want to apply localization. You need to create separate C++ resource-only Win32 dlls to achieve this. Luckily, the whole process is described in elaborate detail on MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff967550(v=vs.105).aspx">8</a>]. Yet still, as you can see there, this quickly gets time-consuming when you want to support a lot of cultures. A nicer solution is to use one of the available tools that generate these dlls automatically for you. Patrick Getzmann for example has created a separate software to help you with this [<a href="http://patrickgetzmann.wordpress.com/wp8-localize/">9</a>] (he also still offers the Windows Phone 7 version [<a href="http://patrickgetzmann.wordpress.com/wp7-localize/">10</a>]).</p> <h3>Conclusion</h3> <p>Localization always takes a bit more effort than single culture apps, as you have to plan ahead and separate code and data thoroughly. This typically involves additional code in the form of bindings and helper classes. However, Windows Phone 8 and Visual Studio 2012 make this significantly easier than previous versions of Windows Phone. We still have some areas that can be improved in the future, but luckily third party developers already came up with various solutions, frameworks and tools that you can use comfortably to work around the current limitations that are still in place.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Localization.aspx Mon, 07 Jan 2013 09:55:00 GMT Windows Phone 8: Enterprise Development <p>Windows Mobile, the discontinued predecessor of today's Windows Phone, had a strong position in the field of enterprise development. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/New-WP8-SDK-Webinar.aspx">Recording of the webinar: Overview of the Windows Phone 8 SDK</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p> Not only were companies able to manage devices comfortably, it also had all sorts of valuable additional business features available. Development options were rich, ranging from native development in C++ to managed code using the .NET Compact Framework, to various other development environments provided by third parties. With Windows Phone, Microsoft took a bold move into the direction of consumer satisfaction and focused a lot on end-user features. Although great for average users, it implicated a lot of simplifications and dropped features for the enterprise world, for which it hence was considered a step backwards by a lot of people with focus on business software. In fact, a lot of companies dogded Windows Phone 7 and kept using Windows Mobile as their preferred platform for internal applications. With Windows Phone 8, Microsoft now has put a lot of effort into offering sufficient choices and features for that target audience too. In this article, we'll cover the most important ones of these. <br />  </p> <h3>What is Enterprise Development?</h3> <p>To understand why Windows Phone 7 was a bit of a problem for businesses, we first have to understand what enterprise applications actually are and how they are different from the Average Joe app that you can buy or download for free from the Phone Store. </p> <p>Enterprises often have a demand for software that is custom tailored to their specific needs and processes, to support their organization's inner workings. There are several standard software packages out there that also can be customized, but it's quite common to still have a custom application developed for very particular needs, to improve productivity and efficiency even more, or simply because for very special use cases no suitable standard software exists. Typical scenarios are business functions like order processing, production management or customer relationship management. But there are hundreds of additional topics that range from very technical aspects, like handling particular machines and devices, to support topics like ticket management systems, to things like fleet tracking or custom messaging systems. So the first obvious difference is that instead of trying to attract as much people as possible by targeting popular topics, enterprise software has a very limited target audience – usually only the own staff.</p> <p>This in turn has additional implications. Typically, security is more a concern than with other software. Not only do companies want to protect their <em>data</em> by applying the usual authentication and authorization strategies, they are also interested in keeping the software itself private – after all, the code reflects their processes and whole business mechanics, something they don't want to expose to potential attack vectors like reverse engineering. And of course, a lot of money is invested into custom software that is not accessible to the open market off the shelf. Protecting intellectual property hence also is quite an issue.</p> <p>With mobile devices, additional points of interest arise. Compared with stationary computers, those devices are lost or stolen more easily, so additional security features like remote data purging become relevant. Also, management of these devices is important especially when employees are allowed to bring their own devices and use them for work ("BYOD" – bring your own device). </p> <p>All of these requirements were somewhat problematic when Windows Phone 7 came around, because it was not possible…</p> <ul> <li>to manage devices in a centralized way</li> <li>to publish apps to a private set of users only</li> <li>to have full control over how and when apps are deployed to users</li> <li>to protect your data and intellectual property appropriately</li> <li>to access hardware or system details in a way that may be required for the business</li> <li>to easily bring over legacy code to the new platform</li> </ul> <p>Some of these issues were addressed in small areas in later updates of version 7, but the real deal for enterprises is Windows Phone 8 which has solutions to all of these points. The possibility to reuse existing, native code was already covered in a previous article [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx">1</a>], and the increased options for developers to access hardware and system details will be part of future articles of this series. But let's see what new features you have at your disposal for the other points, and what you need to do to benefit from them.</p> <h3>What You Need To Do First…</h3> <p>To prepare your developer account to use the new enterprise targeted features, you have to follow a few steps first. To begin with, you need to have a "Company" account registered with Microsoft. Individuals (like personal or student accounts) do not qualify for any of what is to follow. You can check the status of your account in the developer center [<a href="https://dev.windowsphone.com/en-us/account">2</a>].</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_thumb_1.png" width="320" height="324" /></a></p> <p>You will notice that your account also contains a so-called "Symantec Id". This id is needed to obtain a code signing certificate from Symantec [<a href="http://go.microsoft.com/fwlink/?LinkId=268441">3</a>], who is Microsoft's partner for the company validation process (you may have gotten messages from them upon registering your company account already). By the time of writing, the cost for this certificate is 299 US-$ per year. This certificate is later used for two things:</p> <ul> <li>Signing company apps</li> <li>Generating an Application Enrollment Token (AET)</li> </ul> <p>If you are a bit familar with the involved concepts, the first part should be clear: signing an app makes sure that it indeed originates from your company, and also that it hasn't been tampered with upon delivery, for example. The second part listed above may not be as clear: an Application Enrollment Token makes it possible to enroll specific phones in your company's account. Only phones that are enrolled will be able to install and run your applications. So this is the part that makes sure nobody outside your company is able to use software should they get access to it. The process of creating the enrollment token is described in Microsoft's documentation [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj735576(v=vs.105).aspx">4</a>].</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/Company_process_2.png"><img title="Company_process" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="Company_process" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/Company_process_thumb.png" width="494" height="480" /></a></p> <p>The critical part is delivering the resulting token file (.aetx) to your users. Typically, this will be done using a secure website or through other secured channels (can be e-mail, for example). For the user, the enrollment is very simple: they simply tap on the .aetx file and by that enroll the phone in your company account. Alternate enrollment options involve special management software and make the process even simpler for the user (see below).</p> <p>From that moment on, users are able to install and use applications signed by your Symantec certificate. The token is used on a regular basis (periodically and during certain actions) to make sure the company account is still valid. More information and details on the process and concepts can be found in the MSDN documentation [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206943(v=vs.105).aspx">5</a>].</p> <h3>… And What You Can Do Then</h3> <p>After you have established the eco system for your company and enrolled devices in your account, you can start using all the new goodies designed around enterprise requirements. One of the main features from a software development point of view is that you are not bound to Microsoft's deployment mechanism for your own apps anymore. This means that your enterprise apps do not have to go through the Store certification process and can be deployed directly to your users (side-loading). To do this, you have to:</p> <ul> <li>Precompile the code to MDIL using a tool named MDILXAPCompile from the SDK. If you want to learn more about MDIL and precompilation, you can read my detailed article on it here on SilverlightShow [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx">6</a>].</li> <li>Sign the XAP file with the XapSignTool from the SDK. For this you need the corresponding PFX file obtained from the above mentioned enterprise certificate.</li> </ul> <p>This process also is covered in detail on MSDN [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681686(v=vs.105).aspx">7</a>]. Particularly useful is a TechNet link that describes how you can export the required PSX file [<a href="http://go.microsoft.com/fwlink/?LinkId=186422">8</a>], something that's probably not obvious to most developers.</p> <h4>Company Hubs</h4> <p>To make it easier for users to discover all apps of your company, as well as launch and maintain them from a central place, Microsoft introduces the concept of Company Hubs. Technically, a Company Hub is nothing else but a normal Windows Phone app that uses some special APIs to maintain and launch other apps. In addition, you can of course place any other logic and content into such an app that you like, for example company news. Microsoft gives an idea of a Company Hub using their typical "Contoso" sample on the Windows Phone web site [<a href="http://www.windowsphone.com/en-US/business/custom-hub">9</a>]:</p> <p><img style="margin-right: auto; margin-left: auto; float: none; display: block;" alt="Custom Company Hubs" src="http://cmsresources.windowsphone.com/windowsphone/en-us/how-to/wp8/site/business-site-apps-hub-896x240.png" width="640" height="171" /></p> <p>As you can see, Microsoft's vision is to have a one-place stop for all company related info, not only the company apps, but also with news, alerts, maybe an embedded ticket system and management possibilities for your company account profile or other social features.</p> <p>The Company Hub app is usually distributed together with the Application Enrollment Token mentioned above. The intended workflow is for the user to obtain both the .aetx file and the XAP file for the Company Hub simultaneously, and then use that Company Hub as the central tool to manage all the other company apps.</p> <p>For us developers, two important new classes for this have been added to the Windows Phone Runtime: InstallationManager [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207245(v=vs.105).aspx">10</a>] and Package [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/br224667.aspx">11</a>]. When you take a look at the first one, you will see that it not only allows you to get information on currently installed packages for the current publisher, but also the option to add new packages by url. This allows you to host the apps e.g. on some internal network and give users some custom, comfortable UI options for the installation process, including progress reporting. The Package class on the other hand allows you to launch the corresponding app directly, and to obtain basic information like the thumbnail image so you can display it nicely integrated in your Company Hub.</p> <h4>The IT Side of Things</h4> <p>Administrators will be pleased to learn that with Windows Phone 8, it's now possible to use similar options like we had with Windows Mobile, and more. To give you a more detailed view on what was missing from Windows Phone 7 compared to e.g. Windows Mobile 6.5, you can take a look at this very informative Wiki page [<a href="http://social.technet.microsoft.com/wiki/contents/articles/1150.exchange-activesync-client-comparison-table.aspx">12</a>] on TechNet that lists all the Exchange ActiveSync supported (and unsupported) features on both platforms. This makes it more understandable why some administrators were a bit shocked and perceived version 7 of the platform as a huge step backwards. The Wiki page does not yet list Windows Phone 8, but a paper has been published with details on the supported ActiveSync features for the new version [<a href="http://go.microsoft.com/fwlink/?LinkId=270085">13</a>]. You will find that not all of the old options have been added back in (more on that below), but some very important ones for companies are now supported, for example drive encryption. </p> <p>Management tools that are compatible with Windows Phone include both System Center 2012 as well as the cloud-based management features of Windows Intune. These tools make it significantly easier to handle enrollments and distributions of apps. Once set up, the user can then for example comfortably add a certain company account using the phone's "Company Apps" settings dialog that is part of the system itself:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/Company%20Account_2.png"><img title="Company Account" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="Company Account" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/Company%20Account_thumb.png" width="288" height="480" /></a></p> <p>The download and installation of the Company Hub app that you defined in Intune is then initiated automatically (with user consent of course), so there's no need to manually direct them to secured web sites or use similar manual distribution methods. All the phone management details are accessible from a dedicated web site [<a href="http://www.windowsphone.com/en-US/business/phone-management">14</a>] for those interested. If you are looking for more information on the new security features, including how device encryption and the details on protecting intellectual property work, you can find a white paper on these topics on another web site [<a href="http://www.windowsphone.com/en-US/business/security">15</a>].</p> <h3>A Word on Privacy and Control Over Devices</h3> <p>When users read about how companies are able to manage devices, remotely wipe content and apply policies, they get easily concerned especially when they are using their private phones for work (nobody wants to give their company full control over their private data, do they?). To allay those fears Microsoft emphasizes the involved concepts a lot whenever possible: there are very few "global" switches, one of them being device encryption. Instead, Microsoft is trying to find a balance between company data protection and end user control. This means that for example consumer and company data is being kept separated, and remote company data wipe is different from the user-initiated remote wipe that we previously had already on Windows Phone 7. You also do not have to fear that e.g. you won't be able to install custom apps from the Store anymore – companies are only able to maintain and restrict their own apps, for example to tightly control who is able to actually use them. Also, while silent updates of company apps can be performed, the user has to confirm new installs explicitly.</p> <p>These details are not only in place to somewhat protect the user and their data, it also enables other scenarios. For example, by this you are able to enroll your device in multiple company accounts without having policies conflict or contradict each other. This is something that's interesting e.g. for consultants or free lancers who have to work with multiple companies at the same time, including their own of course.</p> <h3>Conclusion</h3> <p>I think the new enterprise features of Windows Phone 8 will quickly lead to an increased adoption of the new platform in the business world, especially since it's starting to become harder and harder for companies to get replacements for e.g. broken Windows Mobile devices from carriers. I'm already in the process of developing enterprise apps on Windows Phone 8, something that our customers were quite reluctant with before. With the good balance between management features, developer options and user data protection and separation, all sides can benefit and acceptance for Windows Phone should be much better among all involved parties in typical enterprise scenarios.</p> http://www.silverlightshow.net/items/Windows-Phone-8-Enterprise-Development.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Enterprise-Development.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Enterprise-Development.aspx Wed, 26 Dec 2012 11:08:00 GMT Windows Phone 8: Developer Tools <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Developer Tools! #wpdev #wp8" data-url="http://slshow.net/VublCZ">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>In the last part of the series [<a href="http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx">1</a>], we talked about the new screen resolutions that have been introduced with Windows Phone 8. This is one of the features not only exciting for end users, but also important to learn about for developers. However, one thing we didn't see was how the development eco system enables you to actually test your apps with these different device features. Time to get our hands on the improved developer tools.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/news/Free-SilverlightShow-Webinar-An-Overview-of-the-Windows-Phone-8-SDK.aspx">Join the Upcoming Webinar on Dec 18th: Overview of the Windows Phone 8 SDK</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <h3>What's in the SDK</h3> <p>When you download the SDK from the Windows Phone Dev Center [<a href="https://dev.windowsphone.com/en-us/downloadsdk">2</a>], you get a whole set of tools. The core of the SDK itself integrates nicely with existing installations of Visual Studio 2012 (Professional, Premium, Ultimate) and provides application templates as well as the required libraries. It also will install a separate Express edition of Visual Studio if you don't have an existing version on your computer – all in all, nothing new there.</p> <p>However, in addition to that the SDK will also provide you with different emulators, test kits, the phone profiler and a new tool named the simulation dashboard, all of which we will take a look at now.</p> <h3>Emulators</h3> <p>In Windows Phone 7, we first only had one single emulator that ran your apps on a simulated WVGA 512MB device. At some point, Microsoft introduced support for lower end devices with only 256MB of RAM, for example the Nokia Lumia 610. The corresponding update of the SDK to version 7.1.1 consequently added a second emulator image that allows you to test your applications against these lower specs [<a href="http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/03/26/wpsdk-711-now-available.aspx">3</a>]. With the Windows Phone 8 SDK we now have four emulators at hand:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________________image_2.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________________image_thumb.png" width="222" height="141" /></a>As you can see, we still have WVGA versions, but this time in 1024MB and 512MB flavors (for Windows Phone 8, no 256MB devices will be available). In addition to that we also have the ability to test on the new high-resolution devices now: WXGA (1280x768) and HD 720p (1280x720). You can leave multiple emulators running in parallel, however Visual Studio can only connect to one of them at the same time. One important detail is that you can only use these emulators when the following requirements are fulfilled:</p> <ul> <li>Operating System: Windows 8 Pro or better</li> <li>CPU: Must support SLAT (Second Level Address Translation)</li> </ul> <p>The latter one is a bit irritating to most people, as usually you don't have to deal with such technical details. If you want to learn more about it, a starting point is the corresponding Wikipedia article [<a href="http://en.wikipedia.org/wiki/Second_Level_Address_Translation">4</a>], and in particular the additional link provided there that provides information on how to find out whether your CPU supports it or not [<a href="http://www.softwaretipspalace.com/how-to/260-check-slat-support-on-intel-amd-processors-cpu.html">5</a>]. You can also look up your CPU on Intel's [<a href="http://ark.intel.com/Products/VirtualizationTechnology">6</a>] and AMD's [<a href="http://support.amd.com/us/kbarticles/Pages/GPU120AMDRVICPUsHyperVWin8.aspx">7</a>] support lists. If your system does not meet the requirements for the emulator, you can still install the SDK, but the emulators will not run, and you cannot test your app other than on real hardware then.</p> <p>With the emulators, you can now run and test code like the following (which is based on the information from the last article) without the need to actually own these devices. Even more important is the possibility to test your application's visual layout under these various circumstances.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> DeviceHelper</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">public</span> <span class="kwrd">static</span> PhysicalResolution PhysicalResolution</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> get</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">return</span> (PhysicalResolution)Application.Current.Host.Content.ScaleFactor;</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">public</span> <span class="kwrd">enum</span> PhysicalResolution</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> WVGA = 100,</pre> <!--CRLF--> <pre class="alt"> HD720P = 150,</pre> <!--CRLF--> <pre class="alteven"> WXGA = 160,</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>This code translates the "ScaleFactor" property into more type safe data on the physical display resolution.</p> <h4>Targeting Windows Phone 7</h4> <p>One thing to note is that the available emulators depend on the version of Windows Phone you target with your project. For example, it's still possible to develop for Windows Phone 7, e.g. when you create a new project:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_18.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_thumb_8.png" width="517" height="239" /></a></p> <p>This will add the old emulators (WVGA with 512MB and 256MB) running on Windows Phone 7 to the list of available devices:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_20.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_thumb_9.png" width="222" height="185" /></a></p> <p>You can now test your 7.1 app on both the previously available emulators as well as how it behaves on the new operating system version and the corresponding devices.</p> <h4>Emulator Features</h4> <p>Just like in the Windows Phone 7 SDKs, the emulators have some additional tools that allow you to:</p> <ul> <li>Simulate accelerometer input</li> <li>Simulate location data</li> <li>Take and save screenshots</li> </ul> <p>These options haven't really changed, expect for one minor detail: previously, when you had the display size of the emulator scaled down to something below 100%, you received a warning when you took screenshots:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_16.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_thumb_7.png" width="644" height="43" /></a>Consequently, those screenshots were blurry and not usuable e.g. for the Marketplace. With the new version of the SDK and emulators, this is not a problem anymore. Even when you set the emulator to really small zoom levels, the screenshot is always taken in the native resolution and with highest quality.</p> <p>By the way, one of the cool new features of Windows Phone 8 is that you can now take screenshots on the devices too. To do this, press and hold the power button and then hit the start button. A screenshot image will be saved to your image library.</p> <h3>The Windows Phone Profiler</h3> <p>No matter how hard you try, you might always reach a point where your app runs into certain problems like unexpected CPU or memory consumption. On the phone platform these problems always are a sensible topic, but they are getting even more important now, as Microsoft has announced that the memory constraints which existed but were sort of lax on Windows Phone 7 will be fully enforced on Windows Phone 8 [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681682(v=vs.105).aspx">8</a>]. To analyze your app's behavior with respect to these details, you can use the profiler that is provided by the SDK. The most parts of this tool haven't changed since Windows Phone 7, however a whole new option named "Monitoring" has been added:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_thumb_2.png" width="611" height="432" /></a>The other two features still perform deep analysis, however the new option allows you to get a quick overview of the behavior of your app. The result will look something like this:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_8.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_thumb_3.png" width="640" height="467" /></a></p> <p>For those of you who know the former "Marketplace Test Kit" some of these numbers will look familiar. Things like the startup time and max memory usage have been moved here. This quick monitoring test grants access to the world of profiling for those developers who have no experience in using such a tool. Of course, once you have identified issues using this method, you might still need to refer to the more detailed options of the profiler to resolve them.</p> <h3>Store Test Kit</h3> <p>With the rebranding of the Marketplace to "Windows Phone Store" to align it its Windows 8 counterpart, the corresponding test kit for developers also has been renamed to "Store Test Kit". Here you can find (almost) all the options that we had in the previous "Marketplace Test Kit", with the exception of the monitored tests that are now part of the profiler (see above). Of course the test kit has been extended for new device features also, for example to support application screenshots for the different available display resolutions. You now have to provide at least one screenshot for each resolution your app supports, or you will receive validation failures:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________image_10.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________image_thumb_4.png" width="579" height="180" /></a>The long list of manual tests still is a bit exhausting to go through, but it helps you identify typical problems with apps and potentially saves you from going through another submission process if you look at them carefully before uploading your app.</p> <h3>Simulation Dashboard</h3> <p>On of the gems in the Windows Phone 8 SDK is the new simulation dashboard that you can access through the Tools menu:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_12.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______image_thumb_5.png" width="371" height="192" /></a>This tool allows you to simulate some of the most crucial things which are hard to reproduce for testing in a lab environment:</p> <ul> <li>Network speeds and reliability</li> <li>The phone's lock screen kicking in, or being removed by the user</li> <li>An unexpected reminder that covers (obscures) your app</li> </ul> <p>You can control and trigger all of these aspects from the new dashboard, on the fly as your app is running in the emulator:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_14.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____image_thumb_6.png" width="403" height="629" /></a>This should be a tremendous help to test how your app behaves in real-world situations, for example when suddenly the network connection is dropped, or when the user receives an incoming phone call. More information on the simulation dashboard's details can be found in the MSDN documentation [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206953(v=vs.105).aspx">9</a>].</p> <h3>Conclusion</h3> <p>Just like other parts of the platform, the developer tools also mature more and more with this release of Windows Phone. Not only do we have emulators for all device configurations, we can also make use of the new simulation dashboard and profiler features to make our applications more robust and ready for real-world situations. With this equipment, it's about time to start coding, don't you think? ;)</p> http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Developer-Tools.aspx Mon, 10 Dec 2012 10:11:00 GMT Windows Phone 8: Multiple Screen Resolutions <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Multiple Screen Resolutions! #wpdev #wp8" data-url="http://slshow.net/Uk8sWy">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>Microsoft has always been quite strict on hardware specifications for Windows Phone devices. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li><!-- Begin Ban Man Pro Text Link Code --> <a href="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Click&SiteID=1&RandomNumber=482522" target="_Blank">Join the latest SilverlightShow challenge!</a><img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Get&Mode=TEXT&SiteID=1&RandomNumber=482522" width="1" height="1" style="border-width: 0px; border-style: solid;" /> <!-- End Ban Man Pro Text Link Code --></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw <br /> Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook</a>:</li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> This has both advantages as well as some drawbacks. For example, to developers this means that they don't have to worry as much about what features are available on devices and which ones aren't, something that is a lot more annoying to deal with on other platforms like Android. On the other hand, strict specifications also limit the possibilities of hardware vendors to divert and the options of customers to choose between e.g. high-end and low-end devices. <p>One of the details of these specifications is screen resolutions. All Windows Phone 7.x devices on the market have the same resolution of WVGA, which is 480 by 800 pixels. Initially there was a planned additional resolution of 320 by 480 (HVGA) [<a href="http://blogs.msdn.com/b/shawnhar/archive/2010/03/10/xna-game-studio-on-windows-phone.aspx">1</a>] to support lower end devices, but no such devices or even platform updates with support for this ever showed up. Practically, we faced a very homogenious environment in that context, with a single resolution to target. In Windows Phone 8 however, the supported screen resolutions are extended to some additional high-end options. In this part of the series, we will take a look at this in detail and see how it will affect developers.</p> <h3>New Screen Resolutions</h3> <p>In addition to the existing resolution of 480 by 800, two new options are added in Windows Phone 8, totaling in three available display resolutions that are listed below:</p> <strong></strong><strong></strong> <table cellspacing="0" cellpadding="2" width="600" border="1"> <tbody> <tr> <td valign="top" style="width: 150px;"> </td> <td valign="top" style="width: 150px;"><strong>WVGA</strong></td> <td valign="top" style="width: 150px;"><strong>HD</strong></td> <td valign="top" style="width: 150px;"><strong>WXGA</strong></td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>Resolution</strong></td> <td valign="top" style="width: 150px;">480x800</td> <td valign="top" style="width: 150px;">720x1280</td> <td valign="top" style="width: 150px;">768x1280</td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>Aspect Ratio (1:1)</strong></td> <td valign="top" style="width: 150px;">15:9</td> <td valign="top" style="width: 150px;">16:9</td> <td valign="top" style="width: 150px;">15:9</td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>Supported by</strong></td> <td valign="top" style="width: 150px;">Windows Phone 7.x/8.0</td> <td valign="top" style="width: 150px;">Windows Phone 8.0</td> <td valign="top" style="width: 150px;">Windows Phone 8.0</td> </tr> </tbody> </table> <p>To get a better feeling of what we are talking about we can take a look at true to scale visual representations of these:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/wp8_screen_resolutions_2.png"><span style="text-decoration: underline;"></span><img title="wp8_screen_resolutions" style="border-width: 0px; margin: 0px auto; float: none; display: block; background-image: none; border-style: solid;" alt="wp8_screen_resolutions" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/wp8_screen_resolutions_thumb.png" width="640" height="412" /></a></p> <p>Isn't that impressive? Personally, I was aware of these values before and I had read them multiple times in dozens of places, but it was only until I've seen those scaled images that my reaction simply was "wow, that's a lot of additional pixels". </p> <p>Now, one of the important details to realize is something that people usually have a natural understanding of, but that needs to be discussed a bit more: these values obviously don't translate into physical dimensions of devices. Let's take a look at another visual comparison, this time of the screen size of a Nokia Lumia 900 (Windows Phone 7.x) and a Nokia Lumia 920 (Windows Phone 8.0):</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/lumia_dimensions_4.png"><img title="lumia_dimensions" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="lumia_dimensions" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/lumia_dimensions_thumb_1.png" width="600" height="506" /></a></p> <p>As you can see, despite the fact that the 920's resolution is much higher, the physical screen size is almost identical to the Lumia 900. By the rules of logic, if the physical size is about the same but the number of pixels is much higher, then the density of the pixels must be increased (they need to be packed together more tightly). This is exactly what is expressed by the last number in the images, which denotes the "pixels per inch" (ppi) [<a href="http://en.wikipedia.org/wiki/Pixel_density">2</a>]. The Lumia 900 has ~217 ppi, whereas the Lumia 920 has 332 ppi according to Nokia's data sheets (if you calculate it manually, the result is 335 or 336, depending on whether you use the width or height).</p> <p>An interesting fact is that, depending on the viewing distance and the visual acuity [<a href="http://en.wikipedia.org/wiki/Visual_acuity">3</a>] of course, the average human eye cannot differentiate individual pixels beyonds ~300 ppi. This means that displays with a ppi that high don't need to resort to techniques like anti-aliasing to smooth text and images anymore, and they have the potential to compete with printed content with regards to visual quality. This is a very important thing to keep in mind, because it heavily influences how we as developers are supposed to work:</p> <blockquote> <p><em>The benefit of these higher resolutions is that we can improve the visual quality of whatever is displayed. <br /> We do NOT want to cram more stuff into that additional screen real estate.</em></p> </blockquote> <p>Creating mulitple versions of a user interface (or a single one that nicely supports multiple resolutions) often can be a time-consuming task that requires different layouts or heavy view logic to reflow the elements on the screen. The above strong postulate hence makes things much easier for us developers, as we really don't need to create those different layouts or care too much about those different resolutions. In fact, Windows Phone handles most of this for us nicely out of the box. </p> <h3>Develop for Multiple Resolutions</h3> <p>The first indication of how you are supposed to work with the new resolutions becomes apparent when you try to access the width and height values of the available phone content area, using code like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var resolution = <span class="kwrd">string</span>.Format(<span class="str">"{0}x{1}"</span>,</pre> <!--CRLF--> <pre class="alteven"> Application.Current.Host.Content.ActualWidth,</pre> <!--CRLF--> <pre class="alt"> Application.Current.Host.Content.ActualHeight);</pre> <!--CRLF--></div> </div> <p>For a WVGA device, this results in the expected value of "480x800". Surprisingly however, when you run the same code on a WXGA device, the returned value still is "480x800". With an HD device, we have a slight change, but the result still is highly unexpected: "480x853". Huh? When you take a look at the documentation of these properties [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.interop.content.actualwidth(v=vs.105).aspx">4</a>][<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.interop.content.actualheight(v=vs.105).aspx">5</a>] you can see that it talks about "logical pixels":</p> <blockquote> <p><em>"The height, in logical pixels, of the Windows Phone application content area."</em></p> </blockquote> <p>So as a developer, you always work with the same WVGA "logical" resolution to layout your application. The small difference with the HD resolution is a result of the different aspect ratio (16:9 as opposed to 15:9 for the other formats) and we'll return to that in a minute. To get an idea of the real physical resolution your application runs on, you have to take a look at the third interesting property on the "Content" class: "ScaleFactor" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.interop.content.scalefactor(v=vs.105).aspx">6</a>] which is a property new to Windows Phone 8.0:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var resolution = <span class="kwrd">string</span>.Format(<span class="str">"{0}x{1} (Scale factor: {2}%)"</span>,</pre> <!--CRLF--> <pre class="alteven"> Application.Current.Host.Content.ActualWidth,</pre> <!--CRLF--> <pre class="alt"> Application.Current.Host.Content.ActualHeight,</pre> <!--CRLF--> <pre class="alteven"> Application.Current.Host.Content.ScaleFactor);</pre> <!--CRLF--></div> </div> <p>When you run the code, you can see that this scale factor returns different values depending on the physical resolution of the device. The following is an overview of the current characteristics of all these properties:</p> <strong></strong><strong></strong> <table cellspacing="0" cellpadding="2" width="600" border="1"> <tbody> <tr> <td valign="top" style="width: 150px;"> </td> <td valign="top" style="width: 150px;"><strong>WVGA</strong></td> <td valign="top" style="width: 150px;"><strong>HD</strong></td> <td valign="top" style="width: 150px;"><strong>WXGA</strong></td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>ActualWidth</strong></td> <td valign="top" style="width: 150px;">480</td> <td valign="top" style="width: 150px;">480</td> <td valign="top" style="width: 150px;">480</td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>ActualHeight</strong></td> <td valign="top" style="width: 150px;">800</td> <td valign="top" style="width: 150px;"><span style="color: #ff0000;">853</span></td> <td valign="top" style="width: 150px;">800</td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>ScaleFactor (%)</strong></td> <td valign="top" style="width: 150px;">100</td> <td valign="top" style="width: 150px;">150</td> <td valign="top" style="width: 150px;">160</td> </tr> <tr> <td valign="top" style="width: 150px;"><strong>Resulting Size (Width/Height x Scale)</strong></td> <td valign="top" style="width: 150px;">480x800</td> <td valign="top" style="width: 150px;">720x1280</td> <td valign="top" style="width: 150px;">768x1280</td> </tr> </tbody> </table> <p>What happens behind the scenes is that the content you as developer created for the logical resolution is scaled up to the real physical size of the device screen at runtime. The fact that the XAML layout system is based on vector graphics makes it possible to do this for text and other content without any loss in quality (limitations see below). The result is that users with those high-end devices immediately benefit of the much better visual quality.</p> <p>The only potential problems are caused by the different logical height of the HD resolution. As long as you stick to relative sizing (for example using grids with star and auto sizing) there shouldn't be a lot of problems. However, when you start working with pixel-perfect layouts (or bitmaps, for that matter), things might be a little off on these devices. For example, when you place a fixed sized element of 480x800 as background of your app it works equally well on both WVGA and WXGA devices but it is padded by 80 pixels when it runs on an HD device – depending on the value of the VerticalAlignment for this element this can be padding at both the top and bottom or either side.</p> <p>It's possible to indicate the supported resolutions in the WMAppManifest.xml for your application. If your app really is not capable of handling the HD resolution very well, you can remove it there:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_2.png"><img title="image" style="margin: 0px auto 10px; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________________image_thumb.png" width="391" height="103" /></a>However, this of course should be an exception or a temporary setting until you fix the issues. Your primary goal always should be to ensure your application works well on all of the available devices so you don't block out potential users (for example, the upcoming Samsung Ativ S has an HD screen).</p> <h4>How to Handle Bitmaps</h4> <p>The above mentioned upscaling works well for all kinds of vector graphics. However, in some cases you will use bitmap assets in your applications, for example as background images or icons and similar things. These images cannot be scaled very well by their nature, and something that looks great at a resolution of 480x800 might be distorted or not optimal at 720x1280 or 768x1280. There are some solutions to this problem.</p> <p>One idea would be to create individual versions of your bitmap resources for each one of the potential resolutions. That means that you would package an image in three different sizes with your application, and then choose the most suitable based on the above described ScaleFactor property. The drawback is that this will increase your application package size significantly if you have a lot of images, and it requires you to distinguish between different resources in all places of your app. </p> <p>Another solution uses a simpler approach: scaling <em>down</em> bitmaps works a lot better than scaling them up, because reducing existing information is a much simpler task than creating missing information out of nowhere. So instead of working with bitmaps that are designed to be used with a physical resolution of 480x800, you can create and package your bitmaps to target a physical resolution of 768x1280. If your app runs on a WVGA device the images will be scaled down, which results in a better experience than the other way round. The drawback is that this does not eliminate the problem completely. While this is a nice solution for things like sprites, icons and thumbnails, you still would have to provide different versions in those situations that depend on the screen aspect ratio, for example for background images.</p> <h3>Other Things to Know</h3> <p>There are some other interesting details that I list as a small Q&A section here:</p> <ul> <li><strong>Is it possible to work with the actual, physical pixels directly?</strong> No. Whenever you layout elements on the screen e.g. in your XAML, you are always working with the logical pixels, never with the physical dimensions.</li> <li><strong>The automated scaling sounds great, but I'm worried how well this works for small sizes (rounding issues)?</strong> The scaling logic usually rounds up values that are small. However, it also has some optimized code paths to handle certain situations in a specific way to avoid weird results. Testing your applications with different resolutions (also possible in the emulator) should be reassuring :).</li> <li><strong>Isn't using high-res resolution assets on WVGA devices a waste of memory?</strong> It's true that images that are high-res and simply scaled down for display still take up the same amount of memory as when they're displayed in full size. However, you can make use of the new DecodePixelWidth and DecodePixelHeight features [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.media.imaging.bitmapimage.decodepixelwidth(v=vs.105).aspx">7</a>] to get more control over this and have images only occupy as much memory as required to display them, for example:</li> </ul> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var bmp = <span class="kwrd">new</span> BitmapImage();</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// no matter the actual size, </span></pre> <!--CRLF--> <pre class="alteven"><span class="rem">// this bitmap is decoded to 480 pixels width (aspect ratio preserved)</span></pre> <!--CRLF--> <pre class="alt"><span class="rem">// and only takes up the memory needed for this size</span></pre> <!--CRLF--> <pre class="alteven">bmp.DecodePixelWidth = 480;</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven">bmp.UriSource = <span class="kwrd">new</span> Uri(<span class="str">@"Assets\Demo.png"</span>, UriKind.Relative);</pre> <!--CRLF--> <pre class="alt">ImageControl.Source = bmp;</pre> <!--CRLF--></div> </div> <p>If you want to learn more on the topic, a nice start is the talk "XAML Application Development" by Shawn Oster from Build 2012 [<a href="http://channel9.msdn.com/Events/Build/2012/2-021">8</a>] (the details on screen resolutions start around 8 minutes into the video).</p> <h3>Conclusion</h3> <p>The new screen resolutions that are available in Windows Phone 8 try to improve the user experience significantly without putting too much burden on the developer. You don't have to re-think your application completely or even create completely different versions of it, yet still the user can benefit from much improved visual quality immediately. Only for certain content like bitmaps do you need to take those new options into consideration, and you have to be a bit careful to handle the different aspect ratio of HD devices nicely. Other than that, multiple screen resolutions support is another one of these "for free" features that we see in Windows Phone 8. </p> http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Multiple-Screen-Resolutions.aspx Mon, 03 Dec 2012 11:03:00 GMT Windows Phone 8: Native Code Support <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Native Code Support! #wpdev #wp8" data-url="http://slshow.net/10Nv4U8">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <div style="border: 1px solid #dddddd; background-color: #f3f3f3; margin-top: 5px; margin-left: 150px; padding-left: 10px; padding-top: 10px; width: 400px; text-align: center;"><strong><a href="http://www.silverlightshow.net/Storage/Sources/WP8_MandelbrotSample.zip">Download the source code for this article</a></strong> <ul> </ul> </div> <p>Developing software for Windows Phone always meant developing managed code. Whether it was traditional development in Silverlight to create your apps or if you decided to build games in XNA, you never left the cozy world of a managed runtime environment. While usually this is something that gives you much more benefits than drawbacks, there are situations where having the possibility to use unmanaged code would be very desirable. Unfortunately, until now using managed code was not a conscious decision you could make as the developer, but rather a limitation of the platform that was imposed on you, and a choice that you didn't have.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li><!-- Begin Ban Man Pro Text Link Code --> <a href="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Click&SiteID=1&RandomNumber=482522" target="_Blank">Join the latest challenge in SilverlightShow challenge channel!</a><img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Get&Mode=TEXT&SiteID=1&RandomNumber=482522" width="1" height="1" style="border-width: 0px; border-style: solid;" /> <!-- End Ban Man Pro Text Link Code --></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>With version 8 of Windows Phone, Microsoft opens up the platform to unmanaged third party code and allows you to develop in C++. I have hinted at this <a href="http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx">in the first part of the series</a> already when I presented you the simplified overview of the new platform infrastructure:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_thumb3_2.png"><img title="image_thumb3" style="border: 0px solid currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" alt="image_thumb3" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_thumb3_thumb.png" width="410" height="267" /></a></p> <p>As you can see, traditional developing in .NET (or, as it was called back then, Silverlight :)) is only one of the available options. We now have a whole set of native APIs at hand that we can also use, and we are free to choose whatever programming model matches our situation and requirements best.</p> <h3>Making the Decision</h3> <p>When I ask people in my workshops and trainings about what they think should be driving reasons behind using native code as opposed to managed code, 90% of the time the first answer that is mentioned is "performance". Up to this day, developers still think of performance as the primary motivation why someone should choose native development over let's say writing the same in C#. The interesting part for me is that apparently the background of a developer doesn't seem to influence that very much. Not only people you'd expect to come up with these arguments (with a background in C++ development for example) think that, but also junior developers who never ever had to write or use native code in a real project. Of course it's true that managed code takes a performance penalty, and there <em>are</em> scenarios where this actually is the decisive argument. However, the truth is that developers very often overestimate the performance benefit they receive from using native code. I often do code reviews and analyses of applications, and usually bad performance is the result of things that are not tied to managed code or the underlying runtime, but rather flaws of the involved architecture and software design. Rethinking your software's structure is in almost all cases what you need to do, and only switching to a different programming model wouldn't result in any measurable improvements. So if you think that support for native code in Windows Phone means you now should rewrite your existing C# projects in C++ to get an enormous boost in performance, please think again – that is definitely not what you're supposed to do, and it definitely will result in a huge disappointment.</p> <p>With this out of the way, you may ask yourself what valid reasons to go native actually are? Well, here is my personal list of considerations, ordered by descending priority. Yours of course may differ, but in the end it more or less always comes down to variations of these.</p> <ul> <li><strong>Reusability:</strong> You have some legacy code around that you really don't want to rewrite but still use in your app.</li> <li><strong>Portability:</strong> You want to use the code you're about to write on multiple platforms.</li> <li><strong>Personal Preference:</strong> You are a developer who really favors C++ over e.g. C# or you have significantly better skills in C++.</li> <li><strong>Performance:</strong> You really are in need for these last bits of performance benefits and know what you're doing.</li> </ul> <p>Now that we have talked about the whys, it's about time to get into the details of how you use native code.</p> <h3>A Closer Look at What's Available</h3> <p>First of all, let's take take a look at the options we have in Visual Studio. When you inspect the available templates for Windows Phone and C++, you can see that the ones that create new applications are very much focused on Direct3D:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_2.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________________image_thumb.png" width="640" height="442" /></a></p> <p>Surprisingly, creating a "Direct3D with XAML" C++ application actually creates a C# main project and a separate Windows Runtime Component in C++. The basic idea here is very similar to how you mixed XNA and Silverlight in Windows Phone 7: Silverlight did take the leading role there and allowed you to embed XNA on individual pages. With the mentioned template in Windows Phone 8, the main application is based on .NET for Windows Phone and makes use of specific controls in XAML (in particular the DrawingSurfaceBackgroundGrid) to embed Direct3D in a similar way. The actual rendering in the sample then is handed off to the native component. This mixture of technologies probably is the typical use case: it allows you to benefit from both the flexibility and comfort of XAML with managed code (for example for menus and other details) as well as the power of native code at the same time.</p> <p>If you want to create an app that really has no connection to C# and managed code anymore, you can select the second template that already has the "native only" reference in its name, which then results in a pure unmanaged application. The other available C++ templates are there to create libraries, either native ones that are dynamically or statically linked, or single Windows Phone Runtime Components which we now will take a closer look at.</p> <h3>It's All About Communication</h3> <p>For interop and communication between the managed and unmanaged world, just like in Windows 8, the Windows Runtime is the magic glue that allows you to let different technologies interact with each other in a very natural way. Particularly, we can integrate unmanaged C++ implementations into managed apps by creating simple Windows Runtime wrappers. They can easily be consumed from C# and feel very ".NET-like". </p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_12.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______image_thumb_5.png" width="313" height="366" /></a></p> <p>It's really not obvious you're not using normal .NET classes and objects when you interact with WinRT components, because you don't have to resort to traditional ways of interop or COM communication for that. </p> <h3>A Practical Sample</h3> <p>I want to show you an example of how you can easily integrate an existing C++ code base in your managed C# app by making use of such a Windows Runtime Component. First of all, since the C++ app templates very much focus on Direct3D, I create a new C# XAML application instead.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_6.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_thumb_2.png" width="640" height="442" /></a></p> <p>Then, in a second step, I simply add another project to my solution, but this time I choose the C++ "Windows Phone Runtime Component" template. After the project is created, I add a reference to it to the main project.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_8.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_thumb_3.png" width="640" height="442" /></a></p> <p>As you can tell from the names in the screenshots, I'm going to re-use an existing Mandelbrot algorithm that is written in C++. The motivation behind this could be any of the above mentioned reasons: in my case I found some existing code and I'm simply reusing it for demonstration. But it could very well be a particularly fast algorithm I want to integrate, or some code that I want to share between multiple platforms.</p> <p>The code of the Windows Phone Runtime Component is explained easily:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/winrt_component_2.png"><img title="winrt_component" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="winrt_component" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/winrt_component_thumb.png" width="655" height="206" /></a></p> <p>In line 3, I include the header file for the existing native implementation that I want to use. In line 13, I declare a member for that legacy type that I can then use later on. These two things could be part of any other C++ code and are not particularly interesting.</p> <p>The details that are special to Windows Runtime Components however are highlighted in line 7 and line 11. First, the class needs to be decorated with the "ref" keyword as well as be a sealed class. The first one tells the compiler that this is a WinRT class that needs to be treated in a special way, the latter one simply is a technical restriction for these kinds of components. In line 11 you can see a wrapper method that I introduced and that will do nothing else but invoke the legacy implementation contained in the "Mandelbrot" class (see below). However, the argument types need some comments. As you can see, I'm using a "WriteOnlyArray", which is a special type that determines that the native code will be able to write to the array. The type is followed by a hat symbol (^) that may remind you of managed C++ (which this isn't!). This is the notation for WinRT types that are automatically reference counted.</p> <p>Obviously, when I pass on the call to the original native implementation, I cannot use the WinRT types, because that old code knows nothing about those. Instead, I use the "Data" member to access the underlying type that my legacy code expects and understands (here: double*):</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___image_14.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___image_thumb_6.png" width="600" height="105" /></a></p> <p>That's basically all you have to do:</p> <ul> <li>Create wrapper methods for all the functionality you want to expose</li> <li>Make sure you only use compatible WinRT types in the public API of your component</li> </ul> <p>For the latter one, you should take a look at the available documentation for proper type mapping [<a href="http://msdn.microsoft.com/en-us/library/windows/apps/br230301.aspx">1</a>], and of course the compiler will also hint you at errors in your code.</p> <h4>Consuming WinRT Components From C#</h4> <p>As mentioned before, the consuming end of this feels very natural to managed developers. You simply have to add a reference to the project containing your Windows Runtime Component and then can start using your component right away:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/csharp_invocation_2.png"><img title="csharp_invocation" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="csharp_invocation" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/csharp_invocation_thumb.png" width="452" height="120" /></a></p> <p>The first highlighted line (1.) creates a new instance of the Windows Runtime component, the second marked line (2.) invokes the wrapper method which internally in turn invokes the original native implementation. As you can see, there's virtually no difference to how you would use normal .NET types – this is the magic of WinRT's projection layers that translate everything into natural .NET types behind the scenes for you.</p> <p>In the sample, I continue to convert the result of the native call to a WriteableBitmap which then is displayed on the XAML page. Et voilà, we have a Mandelbrot set in our managed application, coming straight out of a ten year old piece of native C++ code:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/mandelbrot_2.png"><img title="mandelbrot" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="mandelbrot" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/mandelbrot_thumb.png" width="480" height="800" /></a></p> <h3>Limitations And Opportunities</h3> <p>One thing to note is that obviously you cannot use native code which has dependencies on particular, incompatible features that are not available on Windows Phone. This somewhat limits the possibilities to reuse existing legacy code especially if it is not designed very well. However, the ability to use native code now also opens a lot of new opportunities that simply weren't possible before. For example, it's now much easier to bring interesting projects like the Unity 3D engine over to the platform [<a href="http://www.marketwire.com/press-release/unite-2012-unity-technologies-announces-support-for-windows-8-and-windows-phone-8-1693366.htm">2</a>], which in turn will make it more attractive for developers too.</p> <p>I hope you enjoyed this quick detour to native development and how you can benefit from it on Windows Phone 8. The sample code may be downloaded at the top of this article.</p> <p>Have fun!</p> http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Native-Code-Support.aspx Tue, 27 Nov 2012 10:10:00 GMT Windows Phone 8: Compile in the Cloud <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Compile in the Cloud! #wpdev #wp8" data-url="http://slshow.net/TZEFCk">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p><a href="http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx" target="_self">In the first part of this series</a>, I have introduced you to some of the fundamental changes in Windows Phone 8 on the operating system level. A lot of the improvements however go far beyond that and affect not only the local situation on devices, but the surrounding infrastructure and phone ecosystem as a whole. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't Miss</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li><!-- Begin Ban Man Pro Text Link Code --> <a href="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Click&SiteID=1&RandomNumber=482522" target="_Blank">Join the latest challenge in SilverlightShow challenge channel!</a><img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=0&BannerID=117&AdvertiserID=10&CampaignID=97&Task=Get&Mode=TEXT&SiteID=1&RandomNumber=482522" width="1" height="1" style="border-width: 0px; border-style: solid;" /> <!-- End Ban Man Pro Text Link Code --></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> With this, I not necessarily mean the great improvements that have been introduced for the Windows Phone Store [<a href="http://blogs.windows.com/windows_phone/b/windowsphone/archive/2012/11/07/what-s-new-in-the-windows-phone-store.aspx">1</a>] or in the field of business opportunities – there's also a lot in the box on a very technical level that's not obvious to a quick passing view. One of these things is what I want to talk about today: Compile in the Cloud. <h3>A Quick Look Back</h3> <p>To understand what has been changed and accomplished by that new feature, we first have to take a look back at how things are done on Windows Phone 7, or for that matter, on all other .NET platforms. When you use Visual Studio to build e.g. your C# code, the compiler does not produce a binary that contains machine code. Instead, your source code is translated into something called Intermediate Language (IL). Only when your code is about to be executed will a so-called just-in-time (JIT) compiler do the final step and translate the IL code into something that can be understood by and executed on the target machine architecture. This alone is a pretty fascinating detail, as the JIT compiler is invoked on a per-method basis as soon as the method in question is invoked. For subsequent calls to the method, the previous results are cached and reused, but only until the application is shut down! Then, all the compiled code is simply thrown away and the whole process starts over the next time the application is launched (we like to refer to this as the "Groundhog Day" effect :)). </p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_4.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_thumb_1.png" width="584" height="492" /></a></p> <p>Now the first question that pops into ones mind is: why would you want to do something like that? It seems like a lot of unnecessary extra work at first, does it? The truth is that this has quite some advantages in a lot of situations. First of all, Intermediate Language is a CPU-independent instruction set. This means that you can pass around the IL code as is, and as long as there's a JIT compiler that knows how to translate it to machine code, it'll work on all platforms without modification. Second, the fact that compilation happens every time the application is executed also means that it is built against the current version of installed dependencies (namely the .NET runtime itself) from scratch on each run – meaning that changes to that runtime will not break the application as long as the public API stays compatible. There's also some inherent optimization to the concept of just-in-time compilation: code that is not needed during execution also will never be compiled. And finally there's some other features that IL and the included metadata enable, for example enforcing code security and code validation. If you're interested in it, you can easily take a look at what the IL version of your code looks like using tools like ILdasm.exe [<a href="http://msdn.microsoft.com/en-us/library/f7dy01k1.aspx">2</a>]:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_2.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_________________image_thumb.png" width="600" height="397" /></a></p> <p>If you're scared by what you see, don't worry. If you never learned assembly language it's quite natural that it looks all gibberish.</p> <p>One of the drawbacks of JIT compilation is that it adds some overhead at execution time. As you can imagine, things like parsing metadata, enforcing code validation, setting up dummy methods during load time (stubs) and compiling them into real code on the fly all come at a price. On desktop computers, this price usually is easy to pay, as the computational power is sufficient to do all these things in a blink of an eye. However, with limited resource like – let's say – on a mobile device, these penalties suddenly become very relevant, and no matter how optimized the mechanism is in terms of performance, we're suddenly talking about seconds instead of milliseconds. Additionally, we are even facing some kind of vicious circle here: on a smart phone, the JIT compiler should perform as fast as possible. However, fast usually means producing less optimized code, which on the other hand would result in additional benefits for applications. All in all, the clever concept of IL and JIT compilation is one of the reasons on Windows Phone 7 why we see relatively long start times of applications, sometimes in the range of several seconds. Something had to be done here, and Microsoft did :).</p> <h3>A Solution?</h3> <p>A seemingly obvious solution to the problem is to skip the IL and JIT part altogether and simply produce machine code, like it was and still is done in other languages today. That would eliminate issues like long start times of apps immediately, and even result in a performance boost at runtime too, because no code would have to be compiled on the fly. The idea of this is nothing new to the .NET world. In fact, a tool named NGEN has been around since the very early days of .NET [<a href="http://msdn.microsoft.com/en-us/library/6t9t5wcf.aspx">3</a>]. NGEN generates platform-specific machine code from your IL assemblies that then can be used without the need for a tool like the JIT compiler at all.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_6.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_thumb_2.png" width="577" height="601" /></a>There are however some problems with this. One is that generating those native images is slow even on powerful machines. A prominent example of software that actively makes use of NGEN is the free image processing software Paint.NET [<a href="http://www.getpaint.net/">4</a>] which incorporates an optimization step with NGEN as part of its installation. In some situations it's possible that this optimization takes several minutes to complete. Can you imagine the time it would take to do the same on a phone?</p> <p>A more subtle, yet even more important detail can be found in the above linked page with the NGEN documentation:</p> <blockquote> <p><em>"Images need to be regenerated when the original assembly or one of its dependencies is serviced."</em></p> </blockquote> <p>The first part is somewhat obvious; when I update the original application, the optimized image needs to be recreated. However, the crucial part is the second one: when a dependency (read: .NET runtime components) are changed, the image needs to be recreated also. As a consequence, if we compiled apps to native code, updates to the runtime on the phone inevitably would require to recompile all installed apps on that device too. If optimizing <em>one</em> app potentially could take dozens of minutes, then recompiling your collection of a hundred apps would probably make you go berserk…</p> <h3>A Better Solution!</h3> <p>After this somewhat lengthy introduction on the topic I think you have already guessed that the real solution to all this must be the "Compile in the Cloud" feature that is mentioned so prominently in the headline already. However, simply moving the compilation of IL to native images (NGEN) to the cloud would be a weak solution that introduced all sorts of new problems. For example, even if we used the power of the cloud to do the heavy lifting, we still would need to download that newly compiled image to our phones. Re-downloading a hundred apps after a platform update? I don't think so. So, if you were a clever Microsoft employee and faced all these problems:</p> <ul> <li>JIT is too slow, we can't (continue to) do that</li> <li>Compiling to native images locally is way too slow, people would hate us</li> <li>Re-downloading pre-compiled native images all the time also is impracticable, no chance!</li> </ul> <p>Then what would you do? The correct answer is: simply create yet another language that we can compile to and that solves all these problems :). Ladies and gentlemen, please welcome MDIL – Machine Dependent Intermediate Language. Here is the process for this new concept:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_8.png"><img title="image" style="margin: 5px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_thumb_3.png" width="578" height="677" /></a>To understand why the solution here was to develop a new language, we first have to fully understand the reason why native images need to be regenerated their dependencies are changed. In the process of creating these images all kind of information about the physical layout of references is baked into the result, in particular address offsets. That data potentially becomes stale when those dependencies are changed, for example when new members are added to them. So despite the fact that an API may stay very similar and fully compatible to its previous version, the physical layout of that code can change and cause all sorts of problems up to very severe data inconsistencies and even corruption. This is when MDIL comes into play. It is a format that somewhat resembles the final machine code, but it has placeholder tokens in all the places that usually would contain the hard-coded literals that potentially cause problems. This concept allows to have an "almost done" native image that can be finished in a final, very lean step directly on the phone. Once any dependencies change, that final step can easily be repeated in little time. The actual creation of the MDIL file (which is the heavy lifting in this process) can be performed in the cloud. When a client installs an app from the Phone Store, he already receives that prepared MDIL image from Microsoft's servers.</p> <h3>How You Can Benefit From This</h3> <p>What do you as a developer have to do for your app to support this? Literally nothing. That is one of the beautiful details of this feature: the initial compilation to MDIL is performed the moment when you upload the application to the Store. You don't have to do anything to make this work, it happens automatically behind the scenes for you. Also, you don't have to worry about problems with users who still run Windows Phone 7.x. Supposed your app supports these platforms of course, those users receive an unaltered version of your app package that is JIT compiled on the device just like before. Only users of Windows Phone 8 are provided with the optimized, pre-compiled MDIL version of your app.</p> <p>The result of this new feature can immediately be seen when you run an app on a Windows Phone 8 device and compare in particular the startup time to its behavior on Windows Phone 7 devices – improvements of 50% and more are absolutely possible. </p> <h4>More Details</h4> <p>If you want to test your app as an optimized native image <em>before</em> submitting it to the Windows Phone Store, you can do that by following some simple steps. It requires a physical device though and cannot be performed in the emulator. Details on this can be found in the Windows Phone 8 SDK documentation "How to test the retail version of your app for Windows Phone 8" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj585401(v=vs.105).aspx">5</a>].</p> <p>A lot more information on the topic can be found in both the Build session "Deep Dive into the Kernel of .NET on Windows Phone 8" [<a href="http://channel9.msdn.com/Events/Build/2012/3-005">6</a>] as well as the Channel 9 Going Deep show "Inside Compiler in the Cloud and MDIL" [<a href="http://channel9.msdn.com/Shows/Going+Deep/Mani-Ramaswamy-and-Peter-Sollich-Inside-Compiler-in-the-Cloud-and-MDIL">7</a>]. The latter one features Peter Sollich, who also is listed as the inventor of MDIL in Microsoft's patent application for it [<a href="http://www.freepatentsonline.com/20110258616.pdf">8</a> (PDF)].</p> <h3>Summary</h3> <p>Compile in the Cloud is one of these hidden gems in the set of new features of Windows Phone 8 that most likely won't be noticed and talked about a lot outside of a rather small, interested community. I'm pretty sure that a lot of developers even will never learn about this and frankly, they don't need to – which is why it is such an elegant solution. To the marketing people, it's probably simply "hey we've improved startup times so much it'll drop your jaw". To me, exploring the details of the technology once again was one of these magic moments that make me realize how much effort and thinking goes into pushing forward the platform and evolving the concepts that have been around for ten years now. Fascinating, isn't it?</p> http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Compile-in-the-Cloud.aspx Thu, 22 Nov 2012 10:40:00 GMT Windows Phone 8: Introduction to the Platform <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: #WindowsPhone 8 - Introduction to the Platform! #wpdev" data-url="http://slshow.net/SJ0AvK">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>After a sneek peak at Windows Phone 8 back in June, followed by a private developer preview program in September, this year's BUILD conference was accompanied by the long awaited public access to the SDK for Windows Phone 8, just a few weeks ago. Since that time, first devices from Nokia and HTC also have started to show up in the wild and are available in stock on several markets now. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>More resources...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> About time to get your teeth into the details if you're a developer who is interested in the new platform! In the upcoming series of articles on Windows Phone 8, I'll try to cover most of the changes and new features in detail to prepare you for all the potential projects you plan on taking on in the future. We'll take extensive looks both at the concepts of the platform, programming models and APIs as well as deep dive into individual features. In this first part, I give you an introduction to the platform itself and the significant changes that have been performed under the hood compared to version 7.x of Windows Phone. <h3>The New Old Platform</h3> <p>When we talk about Windows Phone 8 and people ask what has changed, the true albeit confusing answer should be something like: "everything and nothing". Why is that? Well obviously we can read everywhere about all the shiny features those new devices have to offer that we didn't have in Windows Phone 7. But the sheer endless list doesn't stop at hardware gimmicks. Also, the newly offered possibilities for us developers are countless, and if you dig deeper to inspect the technical foundation and details – which we absolutely will – you can see that there have been additional, tremendous changes under the hood too. So why would anybody say nothing has changed? Because despite all of those really fundamental changes of the platform itself that were introduced, Microsoft has taken an enormous amount of effort to ensure that for the almost 120,000 applications in the Marketplace, everything continues to work as expected without compatibility issues, and without the need for developers to change their applications for the new system – until they want to make use of the new features of course. To understand how amazing this accomplishment actually is, we first have to dive into the platform details of Windows Phone a bit.</p> <p>Windows Phone 7 is based on the Windows CE kernel, a technology that has been around for 15 years now, and that has been the basis for predecessor platforms like Windows Mobile too. If that makes it sound bad, please stand corrected. A great variety of devices and corresponding software is build on top of this platform, many of which you wouldn't even recognize from the outside, like various cable/IPTV receivers. Over the years I've done quite some work with the platform in other areas like robotics and device controlling too. Officially Windows Phone 7 was based on the then up to date version 6 of Windows CE, albeit with significant features and new functionality added to the system to support the requirements of the new phone platform, and which allegedly have been adopted back into the next iteration of Windows CE [<a href="http://www.engadget.com/2010/05/04/windows-phone-7-based-on-a-hybrid-windows-ce-6-compact-7-kerne/">1</a>]. This technical foundation most likely is one of the reasons Windows Phone 7 hardware was limited to a certain degree and couldn't adopt modern or even expected features of devices running on top of other platforms. For example, multi-core support was only officially added to Windows CE in 2011. </p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_5.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_thumb_1.png" width="410" height="328" /></a></p> <p>What has changed in Windows Phone 8 regarding this operating system platform? With the release of Windows 8 Microsoft has already created one single operating system that is supposed to serve a great variety of hardware scenarios and platforms: from stationary desktop computers to very lean tablets that run on limited resources. It's only a logical desire to integrate even more platforms and in particular try to unify Windows Phone and tablet/desktop development also. This not only helps to limit the number of seperate systems to support on Microsoft's end; it supposedly also makes it easier for you as a developer to exchange code between those platforms as well. Therefore, Windows Phone 8 will be powered by the same underlying operating system kernel as all the other platforms: the NT kernel, which is the technology that powers all current operating systems by Microsoft, like Windows 7/8 and their server operating systems counterparts. Take a look at the revised (and simplified) chart for Windows Phone 8 below:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_9.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_thumb_3.png" width="410" height="267" /></a></p> <p>Let's focus on the lower part first: as you can see, the whole foundation of the system has been swapped and is now based on the Windows 8 kernel. We can also see in the upper parts that the number of exposed APIs and available programming models have been increased. In addition to native code a version of the Windows Runtime (WinRT) also has found its way onto the phone. </p> <p>Does this mean we are running Windows 8 (for example Windows RT) on the phone now? No [<a href="http://www.pocket-lint.com/news/46334/windows-phone-8-windows-rt-separate-for-now">2</a>]. It means that the core technology like the low level operating system functions, driver models and so on are now shared between the Windows Phone and Windows systems, and that we have a shared amount of APIs that are similar on both systems. But it's not an interchangeable setup or even the completely same operating system. For example, Windows Phone 8 offers only a subset of APIs taken from the full Windows Runtime, and it also extends these APIs by additional features unique to the phone. A schematic diagram looks like this [also see <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff626516(v=vs.105).aspx">3</a>]:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_13.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____image_thumb_5.png" width="325" height="449" /></a>Of the original 11,000 members of the Windows Runtime on Windows 8, a shared subset of approximately 2,800 members has been defined that is also available on the phone. In addition, about 600 members have been added to the phone version of the Windows Runtime that are not available on Windows 8, for example to support speech recognition.</p> <p>A quick start poster is available in PDF format [<a href="http://go.microsoft.com/fwlink/?LinkId=272110">4</a>] that gives you an overview of the available APIs on the phone, be it managed, native or Windows Runtime. It denotes all the overlaps with Windows 8 to give you an idea what features are shared between both platforms.</p> <h4>Backward Compatibility</h4> <p>One of the strengths of Microsoft always has been that introductions of new systems mostly were evolutionary. That means, instead of creating a completely new system that is incapable of running old applications, there's always a huge amount of consideration that goes into maintaining backward compatibility. For example, Stuart Miles proudly emphasized in the above quoted interview [<a href="http://www.pocket-lint.com/news/46334/windows-phone-8-windows-rt-separate-for-now">2</a>] that Visicalc 1.0 (an application from 1981) still runs on Windows 8 (Pro) tablets. For a platform like Windows Phone which – despite the fact that it has been publically around since 2010 – still is considered a newcomer on the market, backward compatibility is more important than ever. You don't want to alienate all of your early adopters and loyal customer by presenting an update to your "just" released new mobile platform that breaks all existing applications (that people also potentially spent a lot of money on), do you?</p> <p>So a lot of thinking and testing went into ensuring that all of the 120,000 apps in the Marketplace today continue to work on the new system and devices just like before. To this end, a "quirks mode" has been introduced that handles existing 7.x apps on the new devices. If you're familiar with web development you know that the term "quirks mode" there refers to a browser's capability of running web sites that are not standards compliant in a backward compatibility code path that ensures they still work as expected even if they are considered broken by modern measures. On Windows Phone 8, a similar concept is used to emulate a version 7 environment for applications which expect it. This means that either the original code of Windows Phone 7 is executed (so it's still present in the current code base in addition to newer code paths), or that the new code behaves in a way to mimic the old behavior of Windows Phone 7 even when the implementation of a particular detail has changed in Windows Phone 8.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_21.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_thumb_9.png" width="433" height="299" /></a></p> <p>If you want to get some more first-hand information on that topic and the testing that was done to make this work, one source is the talk Stefan Wick gave at this year's Build conference where he also covers Windows Phone 8's quirks mode [<a href="http://channel9.msdn.com/Events/Build/2012/3-045">5</a>]. As a result of this mechanism, the vast majority of apps available today should run and behave the same on new Windows Phone 8 devices, even with those dramatic changes under the hood, and without the requirement that developers recompile and resubmit their apps for the new platform. So for a Windows Phone 7.x app, the new version of the system seemingly really hasn't changed at all ;).</p> <p>Of course no matter how hard you try, when you swap such a huge part of the runtime environment and code base for something completely different, there <em>are going to be </em>glitches and incompatibilities that you cannot handle even by the thoroughest considerations, or they simply would take an amount of effort to implement that's not justified, for example because there's only a theoretical chance existing apps are actually affected by a change. Therefore it's of course a great idea to test your existing 7.x app on Windows Phone 8 devices for compatibility, and to take a look at the documentation "App platform compatibility for Windows Phone" [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206947(v=vs.105).aspx">6</a>] that has been released a few days ago. It contains a rather long list of breaking changes, but if you read through that list you'll find that a lot of them are only of theoretical nature, for example when limits have been eased or existing behavior has been made more robust – those should never affect existing apps in practice as it would mean that the code in question would fail on 7.x devices too. However, some of the details described there are indeed things to consider and to check against your own apps. For example, multi-threaded apps inherently still only ran on one single physical core on Windows Phone 7, which made typical threading errors much less likely to surface in practice. On Windows Phone 8, not only do we have real multi-core CPUs but the compiler also does more optimization and may produce different results in this area, for example when accessing instance fields. Therefore, having correct and robust multi-threading code becomes more important for 7.x apps when they execute on Windows Phone 8.</p> <h3>Retarget to Windows Phone 8</h3> <p>The above mentioned quirks mode is nothing you are able to configure for your app. It's a decision that the runtime makes for you automatically. As soon as you take your existing 7.x code base and retarget for Windows Phone 8, quirks mode no longer is applied. The technical process of doing this retargeting is simple and even offered as a separate option when you right-click on a Windows Phone 7 project in Visual Studio 2012 (it can also be accessed on the project properties page where you naturally would expect it):</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_23.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__image_thumb_10.png" width="322" height="309" /></a></p> <p>The implications of this however are that your application now executes on the normal runtime, which potentially introduces changed behavior of existing APIs that also may affect your application. You may even experience bugs with your newly compiled app even if it did run correctly on 8.0 devices when it still was built as 7.x app (again: no quirks mode anymore after recompile). Therefore, you should plan additional time for thorough testing of your app after you retarget it for Windows Phone 8. One thing to note is the behavior of referenced assemblies in your application, something that is also mentioned when you execute the above shown upgrade menu item:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/image_25.png"><img title="image" style="margin: 0px auto; border: 0px solid currentcolor; float: none; display: block; background-image: none;" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_image_thumb_11.png" width="492" height="227" /></a></p> <p>So, referenced projects are not upgraded automatically. This hints at the fact that you can indeed create an app that targets Windows Phone 8 and still references and consumes assembies that target the old version of 7.x. More information can be found on the site linked to in the dialog [<a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202996(v=vs.105).aspx">7</a>].</p> <h3>Summary</h3> <p>As you can see, the fact that Windows Phone is updated to a new major version with this release isn't merely a marketing gag or solely driven by the great amount of new features that are visible to the consumer. The underlying changes of the platform itself are most extensive and also very much affect how we developers are able to work with and use the platform features – something that we of course will see in the upcoming parts of the series in more detail. I hope you enjoyed this first part, and as always I encourage you to provide feedback either in the comments below or by contacting me directly. </p> http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-8-Introduction-to-the-Platform.aspx Mon, 19 Nov 2012 07:56:05 GMT SilverlightShow Interview with Scott Golightly - Presenter at 2 Windows Phone sessions at Visual Studio Live!Redmond 5-day Conference <p><strong>In this SilverlightShow interview, we talk with Scott Golightly - presenter at 2 Windows Phone sessions at </strong><a href="http://ads.silverlightshow.net/a.aspx?ZoneID=55&Task=Click&Mode=HTML&SiteID=1&PageID=6591" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=55&Task=Get&Mode=HTML&SiteID=1&PageID=6591" width="0" height="0" style="border-width: 0px; border-style: solid;" /><strong>Visual Stuido Live! Redmond conference</strong></a><strong> (August 6-10, 2012, Microsoft HQs in Redmond). The topics of the sessions are: </strong><a href="http://ads.silverlightshow.net/a.aspx?ZoneID=83&Task=Click&Mode=HTML&SiteID=1&PageID=21659" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=83&Task=Get&Mode=HTML&SiteID=1&PageID=21659" width="0" height="0" style="border-width: 0px; border-style: solid;" /><strong>Getting Started with Windows Phone 7</strong></a><strong>, </strong><a href="http://ads.silverlightshow.net/a.aspx?ZoneID=84&Task=Click&Mode=HTML&SiteID=1&PageID=39717" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=84&Task=Get&Mode=HTML&SiteID=1&PageID=39717" width="0" height="0" style="border-width: 0px; border-style: solid;" /><strong>Making Money with Windows Phone</strong></a><strong> <br /> As with all earlier Visual Studio Live events this year,SilverlightShow is again the </strong><a href="http://vslive.com/events/redmond-2012/information/sponsors.aspx"><strong>Social Media Premiere Partner</strong></a><strong> for this conference and we are </strong><a href="http://www.silverlightshow.net/community/contest_vslive_redmond.aspx"><strong>sending one SilverlightShow member to this conference for free</strong></a><strong>.</strong></p> <p><strong><em></em></strong></p> <p><strong><em>About Scott:</em></strong><em> </em><em>Scott Golightly is a Senior Software Developer with Experlogix. Scott is also a Microsoft Regional Director. He has over 15 years experience helping clients to create solutions to business problems with various technologies. Scott is an experienced speaker and trainer. He has taught classes around the globe on various technical and business related topics. Scott has presented at numerous code camps, Tech Ed break out sessions, and Tech Ready. Scott has held many certifications including Certified PowerBuilder Developer, Certified Sybase Instructor, MCP, MCSD, and MCT. When he is not working with computers Scott enjoys spending time with his family and being in the outdoors.</em></p> <p><em></em></p> <p><strong>SilverlightShow: </strong>Hi Scott! Nice to meet you online! You are presenting 2 sessions on Windows Phone at VS Live! Redmond event, the <a href="http://ads.silverlightshow.net/a.aspx?ZoneID=83&Task=Click&Mode=HTML&SiteID=1&PageID=21659" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=83&Task=Get&Mode=HTML&SiteID=1&PageID=21659" width="0" height="0" style="border-width: 0px; border-style: solid;" />first</a> being a beginners intro to developing for Windows Phone. Since there are quite a lot of online resources on Win Phone development, how will your session differ from what’s online, why should people who never developed anything for the phone join it?</p> <p><a href="http://ads.silverlightshow.net/a.aspx?ZoneID=62&Task=Click&Mode=HTML&SiteID=1&PageID=42655" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=62&Task=Get&Mode=HTML&SiteID=1&PageID=42655" style="float: right; margin-left: 10px; border-width: 0px; border-style: solid;" /></a><strong>SG:</strong> As with any “getting started” topic today there will be many resources (blogs, videos, and the SDK documentation to name a few) that there will be some overlap. The live session can provide a few advantages including an organization to the content, and the ability to ask questions to figure out how everything fits together.</p> <p><strong>SilverlightShow</strong> : Monetization of Windows Phone apps is undoubtedly something extremely important for phone developers. The Windows phone marketplace has so many paid apps, but few of them are truly profiting ones. Why do you think that is? And is it possible for a developer to become a marketer for his own apps, or should he seek assistance with marketing efforts?</p> <p><strong>SG:</strong> Marketing is one of those things that seem to be more of an art than a science. I don’t know if I have all the answers but I will cover some of the things that make applications successful in the marketplace as well as helping the attendees to understand the process of publishing an application in the marketplace.</p> <p>If a developer is serious about making a career out of selling applications in the marketplace they will need to come up with a really good idea, write a compelling application, and then make sure that it is seen. Because there are now so many applications in the marketplace if you want to truly distinguish your application you should look at getting some help to market your application to the target market. For most hobbyist developers they may not need to hire a professional marketing firm but that will need to be a business decision made by each developer weighing the potential market and gains against the cost of a marketing firm.</p> <p><strong>SilverlightShow</strong> : What would you recommend as the most effective marketing tool to spread the word about a paid app you’ve developed?</p> <p><strong>SG:</strong> There are several factors that make for successful applications. The first and best is to have an idea that your target market wants or needs. </p> <p>After the idea you need to have a compelling application. Two of the criteria that people use to judge applications is the ratings for your application and the performance. By having a good application that meets the needs of the users and is easy to use you will get good ratings. One of the things I see often is that users will start an application and flick quickly to see how it responds. If there are pauses then that application may be removed immediately. </p> <p>If your application is featured in the marketplace it will help to get a lot of downloads and buzz. If you are not that lucky then you will have to market it through your social circles, in magazines and web sites that your target audience will visit, and word of mouth.</p> <p>Finally being responsive to customer issues and having frequent meaningful updates is important to make sure that users are reminded that your application is on their phone and that they downloaded it for a purpose. As they use it more and more it will become integrated into the way they work and this will help to spread the word about your application.</p> <p><strong>SilverlightShow</strong> : And, given that an app has gained a lot of popularity following intensive marketing efforts, what’s the key to having people upgrade to the paid version after trying it, what is the most important factor that persuades people the app deserves their money?</p> <p><strong>SG: </strong>While the reasons that a person will decide to purchase your application are as individual as the people who purchase there are generally several reasons that people decide to purchase the application. I see those reasons as 1) There is additional functionality in the paid version 2) the paid version has fewer advertisements or doesn’t “nag” them to upgrade 3) they like the application so much that they want to upgrade after a trial period 4) their friends are using the application and they purchase it without really considering the cost.</p> <p>You can’t really rely on the last reason but you can be strategic and plan your application so it becomes a must have application that people are willing to pay a small amount of money for in order to continue using the application.</p> <p>Of course there is another strategy and that is to create a free application that is wildly popular and make money off of the advertisements included in the application. This strategy has worked for some applications.</p> <p style="text-align: center;"><a href="http://ads.silverlightshow.net/a.aspx?ZoneID=57&Task=Click&Mode=HTML&SiteID=1&PageID=31606" target="_blank"> <img alt="" src="http://ads.silverlightshow.net/a.aspx?ZoneID=57&Task=Get&Mode=HTML&SiteID=1&PageID=31606" width="468" height="60" style="border-width: 0px; border-style: solid;" /></a></p> <p><strong>SilverlightShow</strong> : Earlier this week Microsoft announced the features to be expected in Windows Phone 8. How do you think Win phone 8 will affect the development of mobile apps, and the ability to substantially monetize the apps?</p> <p><strong>SG:</strong> This is an exciting time for Windows Phone developers. Since applications written for Windows Phone 7 will run on Windows Phone 8 developers can continue to create great applications using Silverlight that will run in both Windows Phone 7 and Windows Phone 8.</p> <p>As more details come out about the features available in Windows Phone 8 developers can start to weigh the new features against the potential market and determine when to move to a Windows Phone 8 only solution.</p> <p><strong>SilverlightShow</strong> : What do you think does Windows Phone technology still lack, to be more widely adopted for LOB apps? </p> <p><strong>SG:</strong> There are several features that will help with business adoption. One of the requests I hear often is for a private marketplace where an administrator can ensure that only members of that organization get access to the application as well as a way to remove the application when a user leaves the enterprise.</p> <p>Windows phone already has great management capabilities and with Windows Phone 8 I expect that there will be even more capabilities that will appeal to enterprises.</p> <p><strong>SilverlightShow: </strong>How and where may conference attendees meet you during the conference?</p> <p><strong>SG: </strong>I generally like to attend other sessions so I will be in the hallways and in sessions. I am more than happy to talk to anyone about Microsoft in general and development and Windows Phone in particular. The best part of conferences is the chance to talk and learn from other’s perspectives that might be different than your own.</p> <p><strong></strong></p> <p><strong>Thanks Scott for this interview! Wish you, as well as our free pass winner a great conference event!</strong></p> http://www.silverlightshow.net/items/SilverlightShow-Interview-with-Scott-Golightly-Presenter-at-2-Windows-Phone-sessions-at-Visual-Studio-Live-Redmond-5-day-Conference.aspx editorial@silverlightshow.net (Silverlight Show ) http://www.silverlightshow.net/items/SilverlightShow-Interview-with-Scott-Golightly-Presenter-at-2-Windows-Phone-sessions-at-Visual-Studio-Live-Redmond-5-day-Conference.aspx#comments http://www.silverlightshow.net/items/SilverlightShow-Interview-with-Scott-Golightly-Presenter-at-2-Windows-Phone-sessions-at-Visual-Studio-Live-Redmond-5-day-Conference.aspx Thu, 28 Jun 2012 13:47:00 GMT Creating the SilverlightShow Windows Phone App: part 4 <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: Creating the SilverlightShow #WindowsPhone App: part 4 #wpdev" data-url="http://slshow.net/L0CR5J">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>When you create an app like the SilverlightShow app, that accesses remote data frequently, thinking about a suitable strategy for local storage and caching is vital to provide a great user experience. In the previous parts of this series, we have already seen how <a href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx">several optimizations are used</a> to improve the networking performance of the app. Overall, the costs to pull data from the portal could be reduced to far less than 1/10th of the original traffic by applying some relatively simple changes. However, this is only half the story. What we also wanted to achieve is that content that has been retrieved once should not be fetched again – we needed a solution for storing those items locally.</p> <h2>Local Storage Options</h2> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>More resources...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>When you think about persisting and restoring data locally on the phone, you have a variety of features at your disposal. With the first versions of Windows Phone, you could either use the <a href="http://msdn.microsoft.com/en-us/library/Cc672312(v=vs.95).aspx">ApplicationSettings</a> for trivial situations, or you had to pretty much do all the work manually, as in writing to and reading from Isolated Storage files. </p> <p>With the platform maturing more and more, additional options are established. In particular, Microsoft added local database support in Windows Phone 7.1, built on SQL Server of course. This gives you the comfort of working with relational data and the well known features of LinqToSql for queries. If you want to learn more about local database support, take a look at <a href="http://www.silverlightshow.net/items/Windows-Phone-7.1-Local-SQL-Database.aspx">Andrea Boschin's article</a> about it.</p> <p>The option we decided to use is a community project originally designed and developed by Jeremy Likness: <a href="http://sterling.codeplex.com/">The Sterling Database</a>. The project has been around for two years, is now maintained and contributed to by various community members, and has proven its power in several apps on the Marketplace that are using it today.</p> <h2>What Sterling is</h2> <p>Let me quote from the Sterling project page on CodePlex to give you a basic understanding of its nature:</p> <blockquote> <p><em>"Sterling is a lightweight NoSQL object-oriented database for .Net 4.0, Silverlight 4 and 5, and Windows Phone 7 that works with your existing class structures. Sterling supports full LINQ to Object queries over keys and indexes for fast retrieval of information from large data sets."</em></p> </blockquote> <p>What exactly does this mean? For starters, instead of mapping your classes to a relational database model, you can simply use your existing data structures right away. In situations like ours, where a data structure has already been established or is determined by some external factors, this can result in less work. It may also give you a more natural and easier way of working with your data, as you don't have to deal with that extra layer and conversion logic between your application objects and data storage. </p> <p>Although Sterling is a very lightweight project (the core assembly is only ~80 kilobytes big), it still is very flexible. For example, in addition to well-known features like triggers you can also register so-called interceptors that let you change the way Sterling works on a low level, which enables interesting options for example regarding transparent data encryption or optimization (more on that later).</p> <p>Behind the scenes, Sterling of course also uses Isolated Storage for persistence, but it uses binary serialization, which results in very compact file sizes compared to the built-in serialization options:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto;" alt="sizeondisk.png" src="http://i3.codeplex.com/Download?ProjectName=sterling&DownloadId=211262" /></p> <p style="text-align: center;"><span style="font-size: 10px;">(Image taken from </span><a href="http://sterling.codeplex.com/"><span style="font-size: 10px;">the Sterling project page</span></a><span style="font-size: 10px;">)</span></p> <p>The way Sterling performs queries on its keys and indexes (explained below) gives a massive performance benefit, as shown by the following comparison:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto;" alt="sterlingspeed.png" src="http://i3.codeplex.com/Download?ProjectName=sterling&DownloadId=211263" /></p> <p style="text-align: center;"><span style="font-size: 10px;">(Image taken from </span><a href="http://sterling.codeplex.com/"><span style="font-size: 10px;">the Sterling project page</span></a><span style="font-size: 10px;">)</span></p> <h1><span style="font-size: 10px;"></span></h1> <p>So in certain situations, for example when disk memory consumption or query speeds are crucial and your data is suitable to be stored and handled by Sterling, using that database can be a huge improvement over alternative methods, and/or save you a considerable amount of time compared to custom implementations.</p> <h2>Setup</h2> <p>Setting up a Sterling database is easy to do. After pulling in the required references (you can use the available <a href="http://www.nuget.org/packages/SterlingPhone">NuGet package</a> for that) simply derive from the built-in database instance base class. You can then provide so-called table definitions that determine what types you want to store in your database, and what indexes should be created for them. For example, the following piece of code creates a table definition for "Article" items, uses the "Guid" property as key, and adds an index for the "PublishDate" property:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> SterlingDatabase : BaseDatabaseInstance</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">protected</span> <span class="kwrd">override</span> List<ITableDefinition> RegisterTables()</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">return</span> <span class="kwrd">new</span> List<ITableDefinition></pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> CreateTableDefinition<Article, <span class="kwrd">string</span>>(article => article.Guid)</pre> <!--CRLF--> <pre class="alteven"> .WithIndex<Article, DateTime, <span class="kwrd">string</span>>(<span class="str">"ArticleDateIndex"</span>, article => article.PublishDate)</pre> <!--CRLF--> <pre class="alt"> };</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>All that's left to do is initialize the database. A good pattern is to do that when your application starts or gets activated, and to execute the corresponding clean-up when the user leaves your application. The following shows the required code that can then be called in the respective lifetime events of the PhoneApplicationService:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">private</span> SterlingEngine _engine;</pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">private</span> ISterlingDatabaseInstance _sterlingDatabaseInstance;</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">private</span> <span class="kwrd">void</span> ActivateSterling()</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> _engine = <span class="kwrd">new</span> SterlingEngine();</pre> <!--CRLF--> <pre class="alt"> _engine.Activate();</pre> <!--CRLF--> <pre class="alteven"> _sterlingDatabaseInstance = _engine.SterlingDatabase.RegisterDatabase<SterlingDatabase>(<span class="kwrd">new</span> IsolatedStorageDriver());</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="kwrd">private</span> <span class="kwrd">void</span> DeactivateSterling()</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> _sterlingDatabaseInstance.Flush();</pre> <!--CRLF--> <pre class="alteven"> _engine.Dispose();</pre> <!--CRLF--> <pre class="alt"> _sterlingDatabaseInstance = <span class="kwrd">null</span>;</pre> <!--CRLF--> <pre class="alteven"> _engine = <span class="kwrd">null</span>;</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>Do not forget to clean-up in the "Deactivated" event too, as there is no guarantee that the user will return to your app, resulting in tombstoning and silent removal of your app, with the potential to leave your database corrupted.</p> <h2>Basic Operations</h2> <p>From the moment of activation on, you can use the database instance to save and load items very easily:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// save an article</span></pre> <!--CRLF--> <pre class="alteven">_sterlingDatabaseInstance.Save(article);</pre> <!--CRLF--> <pre class="alt">_sterlingDatabaseInstance.Flush();</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// load back</span></pre> <!--CRLF--> <pre class="alteven">var loadedArticle = Load<Article>(article.Guid);</pre> <!--CRLF--></div> </div> <p>As you can see, the snippet uses both "Save" as well as an additional "Flush" method to save the object. Since Sterling is optimized for performance, it keeps its current keys and indexes in-memory only, until you call "Flush" explicitly. This allows you to do multiple successive "Save" operations without the performance hit of persisting keys and indexes between each of these operations. The drawback is that for single operations, you have to call "Flush" explicitly to keep the database consistent on disk.</p> <p>One important thing that often causes confusion with inexperienced users, is that the "Load" operation does not cache items in memory. This means that every time you use the "Load" operation, a new instance is returned, i.e. two successive invokes of "Load" with the same "article.Guid" value will return two different objects (for the same article though). To benefit from caching, you have to use queries (see below).</p> <p>Loading and saving an object will treat the whole object graph connected to that object through properties. Depending on how you set up your database the behavior will be slightly different. To learn more about the details of loading and saving, I recommend reading the excellent documentation of Sterling: <a href="https://sites.google.com/site/sterlingdatabase/sterling-user-guide/4-databases/c-saving-instances">Saving Instances</a> and <a href="https://sites.google.com/site/sterlingdatabase/sterling-user-guide/4-databases/d-loading-instances">Loading Instances</a></p> <p>Deletion of objects is performed using either the object itself, or by passing in the key for that object (which eliminates the need to explicitly load an object just for deletion):</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// delete by reference</span></pre> <!--CRLF--> <pre class="alteven">var article = _sterlingDatabaseInstance.Load<Article>(guid);</pre> <!--CRLF--> <pre class="alt">_sterlingDatabaseInstance.Delete(article);</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// or delete by key</span></pre> <!--CRLF--> <pre class="alteven">_sterlingDatabaseInstance.Delete(<span class="kwrd">typeof</span>(Article), key);</pre> <!--CRLF--></div> </div> <p>Sterling of course also supports deleting all objects of a certain type (truncating a table) and even purging the whole database. You can learn more about this <a href="https://sites.google.com/site/sterlingdatabase/sterling-user-guide/4-databases/f-delete-truncate-and-purge">here</a>.</p> <h2>Queries</h2> <p>The power of Sterling comes with queries. In the above sample, we had added an index for the publish date of articles. This allows us to access stored article instances by their publish dates extremely fast because Sterling holds that data in memory. It uses a lazy load mechanism that only needs to access the disk once you actually need to retrieve the object content. Let me give you an example:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> DateTime DetermineNewestArticle()</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> var result = _sterlingDatabaseInstance.Query<Article, DateTime, <span class="kwrd">string</span>>(<span class="str">"ArticleDateIndex"</span>)</pre> <!--CRLF--> <pre class="alteven"> .OrderByDescending(o => o.Index)</pre> <!--CRLF--> <pre class="alt"> .Select(o => o.Index)</pre> <!--CRLF--> <pre class="alteven"> .FirstOrDefault();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">return</span> result;</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>This retrieves the date of the newest available article using the respective index, <em>without loading the actual article from disk</em>. Because the index is available in memory, this is a Linq to Objects operation that is really fast. You can have multiple indexes for each type, to enable different of these query scenarios at the same time.</p> <p>If you need to actually access the content of the newest article, then the code could look like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> Article GetNewestArticle()</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> var result = _sterlingDatabaseInstance.Query<Article, DateTime, <span class="kwrd">string</span>>(<span class="str">"ArticleDateIndex"</span>)</pre> <!--CRLF--> <pre class="alteven"> .OrderByDescending(o => o.Index)</pre> <!--CRLF--> <pre class="alt"> .Select(o => o.LazyValue.Value)</pre> <!--CRLF--> <pre class="alteven"> .FirstOrDefault();</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">return</span> result;</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>Only when you access the "LazyValue.Value" property does Sterling load the data from Isolated Storage. Queries of course are much more powerful than simply loading single objects. You can also combine them and make use of joins, projections and all the other available features. To learn more about complex queries, <a href="https://sites.google.com/site/sterlingdatabase/sterling-user-guide/4-databases/e-queries-and-filters">the documentation</a> is a good starting point.</p> <h3>Caching</h3> <p>As mentioned above, as soon as you use queries the retrieved values are cached. This means that only the first access of a certain (lazy) value in the key or an index collection results in an actual load operation. Successive queries return the previously loaded object and hence will execute much faster. Don't worry: as soon as you change the object and save it back to Sterling, the cache is cleared for that object, and the next query operation will reload your changed values from disk again (with the result being cached again). Sterling keeps track of save operations internally.</p> <p>While caching can improve performance of your app tremendously, it also can have some unexpected side effects when you use the same data in different parts of your app at the same time. To learn more about these edge cases, take a look at the docs <a href="https://sites.google.com/site/sterlingdatabase/sterling-user-guide/4-databases/e-queries-and-filters">here</a>.</p> <h2>Interceptors</h2> <p>The data of the SilverlightShow app is easily compressible, because it's mostly text. One of the nice hooks Sterling allows you to use therefore came in handy, to apply a general compression to all the data that is written and read – without the need to explicitly take care of this manually during each and every save and load operation. The way this works is to add a custom interceptor implementation during the initialization phase of the database:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> <span class="kwrd">void</span> ActivateSterling()</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> _engine = <span class="kwrd">new</span> SterlingEngine();</pre> <!--CRLF--> <pre class="alteven"> _engine.Activate();</pre> <!--CRLF--> <pre class="alt"> _sterlingDatabaseInstance = _engine.SterlingDatabase.RegisterDatabase<SterlingDatabase>(<span class="kwrd">new</span> IsolatedStorageDriver());</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="rem">// register a custom interceptor</span></pre> <!--CRLF--> <pre class="alteven"> _sterlingDatabaseInstance.RegisterInterceptor<CompressionInterceptor>();</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>To create such an interceptor, you can conveniently derive from the existing "BaseSterlingByteInterceptor" base class and override the required methods:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> CompressionInterceptor : BaseSterlingByteInterceptor</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">override</span> <span class="kwrd">public</span> <span class="kwrd">byte</span>[] Save(<span class="kwrd">byte</span>[] sourceStream)</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> <span class="rem">// do anything you want with the incoming bytes</span></pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">override</span> <span class="kwrd">public</span> <span class="kwrd">byte</span>[] Load(<span class="kwrd">byte</span>[] sourceStream)</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// reverse whatever you did to the bytes in the Save method here</span></pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--></div> </div> <p>Your interceptor is used behind the scenes in all the operations, you don't have to change anything in the way you work with Sterling. So this is the perfect place to apply things like on-the-fly compression or encryption.</p> <h2>Conclusion</h2> <p>Sterling is an interesting alternative for local storage of data in Windows Phone apps. We were able to reuse our existing data structures without the need to introduce any storage-related changes to them, and the way Sterling handles key and indexes is perfect for our requirements of searching and sorting available items without the need to deserialize their (heavy) content from disk. The possibility to implement a generic data compression easily was the icing on the cake that helped create a great user experience.</p> http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx#comments http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-4.aspx Mon, 14 May 2012 18:30:00 GMT Creating the SilverlightShow Windows Phone App: part 3 <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: Creating the SilverlightShow #WindowsPhone App: part 3 #wpdev" data-url="http://slshow.net/IE4Ege">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>In the first parts of the series about developing <a href="http://windowsphone.com/s?appid=aa47a1d4-3418-496d-862f-36eb1ec78f43">the SilverlightShow Windows Phone app</a> I explained the general development process and the technical details of accessing and optimizing the RSS feeds of the site. Now that we are able to access all of the content from the phone, the next step is to take a look at what was necessary to display what we have to the user while preserving a native look and feel. If you haven't seen the app in action, <a href="http://www.silverlightshow.net/video/SilverlightShow-WP7-App-Intro.aspx">here</a> is a short video about it.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>More resources...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>When you recall the details of the previous part or simply take a quick look at the RSS feeds of the SilverlightShow site again (<a href="http://www.silverlightshow.net/FeedGenerator.ashx?type=Article">sample</a>), you will see that the content of each category (news, articles, events) is stored as fully formatted HTML already. All of it is produced by authors in WYSIWYG tools like Windows Live Writer and directly uploaded to the site's content management system. Even though we receive a slightly optimized and cleaned version of that rich content on the phone, it's still HTML. The fundamental decision to make hence was whether we would take that content as-is or transform it into something more native to the phone platform.</p> <h2>HTML or not HTML, that is the question</h2> <p>I have talked about the problems of parsing real-world HTML in the last part already, and how malformed tags and content can easily break a strict approach. We could have used a specialized parser like the <a href="http://htmlagilitypack.codeplex.com/">Html Agility Pack</a> I've suggested before, to ease some of these problems. However, these tools can only help with certain technical details, to fix low-level issues. SilverlightShow is a platform that is open for anyone to contribute and be an author for their respective area, and that variety is also reflected in the technical structure of the content. An analysis of the existing data revealed that sometimes articles are structured with div elements, sometimes people use paragraph tags; some like to present tabular information, others make heavy use of images, diagrams and screenshots. In addition, we have code snippets for different languages, bulleted lists, and of course the normal styling features you have in HTML for highlighting and font formatting.</p> <p>All of this quickly lead to the conclusion that any attempt to transform the existing content into something native to Windows Phone (=XAML) would result in various problems:</p> <ul> <li>Either we would have to spend a large amount of time to support an insane amount of formatting features, or</li> <li>We needed to make sure that all (future) content is only using a limited subset of the available options (which would require a very sophisticated technical review process before publishing any new item), or</li> <li>We would only support a small subset of the available features in HTML and simply strip the rest, which would result in a more or less significantly worse experience for phone users compared to the normal desktop experience.</li> </ul> <p>In any case, we were sure that none of the above solutions could be implemented in a way that is safe and robust enough for all future content. No matter how thorough you test and create an app like this, since you highly depend on external factors that are completely out of your hands it's almost inevitably that something is going to break at some point in the future.</p> <p>The logical consequence was to use the content as is, and present it within the app using the web browser control. Obviously the team at Microsoft has much more resources and knowledge, and put more effort into creating a full featured HTML parser and rendering engine than we ever could – why not make use of that and provide the best presentation possible by using this built-in option? This seemed like the perfect compromise to us: creating a nice application to give users the best look and feel as well as a native, integrated experience, and embed the existing content in a way that provides the same nice presentation as accessing the site.</p> <h2>What's in a color?</h2> <p>Using the web browser control in a satisfactory way turned out to be much harder than expected. Along the way we hit quite some obstacles that were hard to overcome. And I'm not talking about advanced or obscure things but pretty basic features. For example, setting the background color of the control can become a challenge if you want it to be perfect. The web browser control is only a shallow wrapper around a native component and in turn makes use of the built-in rendering capabilities of Internet Explorer to display its content. The way the control works unfortunately does not allow to e.g. work with advanced features like transparency for the background.</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto;" alt="visual_tree" src="http://www.pitorque.de/MisterGoodcat/image.axd?picture=visual_tree.png" /></p> <p>This analysis of the visual tree of the web browser control I did a while back shows the native Internet Explorer component named "TileHost" as last element. So, with the background color solely determined by the content that is displayed, the natural next step is to simply adjust that data in the HTML content itself. The items we download from the RSS feeds are only HTML fragments and need to be extended to a full and valid HTML page anyway (which means adding html, head and body tags etc.). During that step, we inject some custom styling data, for example for the pre tags of code snippets, and also for the background color:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var styleElement = ownerDoc.CreateElement(<span class="str">"style"</span>);</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// [...]</span></pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="kwrd">const</span> <span class="kwrd">string</span> <span class="kwrd">value</span> = <span class="str">"body { font-size: 10pt; background-color: #000000; color: #ffffff; }"</span>;</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt">var valueNode = ownerDoc.CreateTextNode(<span class="kwrd">value</span>);</pre> <!--CRLF--> <pre class="alteven">styleElement.ChildNodes.Add(valueNode);</pre> <!--CRLF--> <pre class="alt">headElement.ChildNodes.Add(styleElement);</pre> <!--CRLF--></div> </div> <p>The problem with this approach is that before any content is rendered, the web browser control's background color is white by default. This means that when you set it to a black background like we do with the above code, you will see some flickering, because it takes a short amount of time for the content to be loaded and rendered. The background will rapidly switch between the default white and your desired background color every time you change the content. </p> <p>This annoying behavior cannot be suppressed by any of the built-in features easily. The simplest solution I found on the web was a suggestion by Colin Eberhardt to create an overlay (another UI element, like a rectangle) with the desired background color, and then fade out that overlay once the content in the web browser control has finished rendering. He has used a similar technique in his PhoneGap experiments to overcome the same issue there (you can find his blog post on this <a href="http://www.scottlogic.co.uk/blog/colin/2011/12/a-simple-multi-page-windows-phone-7-phonegap-example/">here</a>). This workaround is not yet added to the SilverlightShow app – if you play with the app you will therefore see the said flickering when you e.g. navigate back and forth between the content items.</p> <p>If you think that this is quite some work for something as simple as setting a background color, then you haven't thought about theming yet.</p> <h3>I Want Change</h3> <p>In the above paragraphs, I showed the code used to produce a constant background of black for the web browser control. However, Windows Phone supports both a dark and a light theme, and naturally we wanted to give users of our app the same choice. If a user has set their phone to the light theme, we wanted to invert the presentation scheme of the content items to display black text on white background. Due to the same problems mentioned above, this cannot be achieved by simply setting some properties on the control. Also, we couldn't simply inject the style in the way shown above when we download the content, because obviously the user can switch themes at any time in between uses of the app. So what we had to do instead is find a way to dynamically set the new colors within the HTML content of the control. JavaScript to the rescue!</p> <p>The idea is to inject some JavaScript into the content that is to displayed, in the same way that we inject the style data above, so we can let that JavaScript code perform the required changes for us whenever it is required. To this end, the web browser control provides a method named <a href="http://msdn.microsoft.com/en-us/library/cc491132(v=vs.95).aspx">InvokeScript</a>, which lets you execute a JavaScript function defined in the current content dynamically. The injected code can be something simple like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">function</span> changeBackgroundToWhite() { </pre> <!--CRLF--> <pre class="alteven"> document.body.style.background = <span class="str">'white'</span>; </pre> <!--CRLF--> <pre class="alt"> document.body.style.color = <span class="str">'black'</span>; </pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--></div> </div> <p>Injecting this works the same way as before with the styles:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// create script element and attributes</span></pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">var</span> scriptElement = ownerDoc.CreateElement(<span class="str">"script"</span>);</pre> <!--CRLF--> <pre class="alt"><span class="kwrd">var</span> scriptTypeAttribute = ownerDoc.CreateAttribute(<span class="str">"type"</span>, <span class="str">"text/javascript"</span>);</pre> <!--CRLF--> <pre class="alteven">scriptElement.Attributes.Add(scriptTypeAttribute);</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="rem">// create script content</span></pre> <!--CRLF--> <pre class="alt"><span class="kwrd">string</span> script = <span class="str">"[...]"</span>;</pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">var</span> scriptContent = ownerDoc.CreateTextNode(script);</pre> <!--CRLF--> <pre class="alt">scriptElement.ChildNodes.Add(scriptContent);</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="rem">// add everything to the head tag</span></pre> <!--CRLF--> <pre class="alteven">headElement.ChildNodes.Add(scriptElement);</pre> <!--CRLF--></div> </div> <p>Now we are able to switch the color scheme when the device currently is set to use the light scheme:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">var</span> lightThemeVisibility = (Visibility)Application.Current.Resources[<span class="str">"PhoneLightThemeVisibility"</span>];</pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">if</span> (lightThemeVisibility == Visibility.Visible)</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> ContentWebBrowser.InvokeScript(<span class="str">"changeBackgroundToWhite"</span>);</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p><em>Note: Due to an issue with detecting theme changes after you return from tombstoning in the current release of the phone OS switching to the light theme that way (and not having a way to switch back) is actually sufficient in our case.</em></p> <h2>Where am I?</h2> <p>One of the most annoying problems with the web browser control is that it does not display a scroll bar to give the user an indication of what part of the page they are currently looking at, or how much more content there is during scrolling. I have written a detailed analysis of the problem a while ago in my blog; if you're interested in learning more on the technical details, you can read that post <a href="http://www.pitorque.de/MisterGoodcat/post/Somethings-Missing-from-the-WebBrowser-Control.aspx">here</a>. The following is a screenshot taken from that post to demonstrate the issue:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto;" alt="ie9_webbrowser_control_comparison" src="http://www.pitorque.de/MisterGoodcat/image.axd?picture=ie9_webbrowser_control_comparison.png" /></p> <p>In my post I also explain a workaround that tries to emulate the behavior of the built-in browser experience. To achieve that I'm once again injecting some custom JavaScript into the content, but this time I communicate with the outer application from that very JavaScript, using the well-known "external.notify" mechanism. The corresponding JavaScript looks like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">function</span> initialize() { </pre> <!--CRLF--> <pre class="alteven"> window.external.notify(<span class="str">"scrollHeight="</span> + document.body.scrollHeight.toString()); </pre> <!--CRLF--> <pre class="alt"> window.external.notify(<span class="str">"clientHeight="</span> + document.body.clientHeight.toString()); </pre> <!--CRLF--> <pre class="alteven"> window.onscroll = onScroll; </pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"><span class="kwrd">function</span> onScroll(e) { </pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">var</span> scrollPosition = document.body.scrollTop; </pre> <!--CRLF--> <pre class="alt"> window.external.notify(<span class="str">"scrollTop="</span> + scrollPosition.toString()); </pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven">window.onload = initialize;</pre> <!--CRLF--></div> </div> <p>On the Silverlight side of things, you are able to capture these calls and process the information accordingly; in the case of the SilverlightShow app, I'm using it to update a fake scrollbar overlay I've added to the web browser control.</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// e.g. in the constructor, or in XAML</span></pre> <!--CRLF--> <pre class="alteven">ContentWebBrowser.ScriptNotify += ContentWebBrowser_ScriptNotify;</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">private</span> <span class="kwrd">void</span> ContentWebBrowser_ScriptNotify(<span class="kwrd">object</span> sender, NotifyEventArgs e)</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// parse e.Value and use it to update a fake ScrollBar element</span></pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>Unfortunately, the way the web browser works on the phone (and I think the web browsers on other mobile platforms and brands work in a similar way) is that they make heavy use of GPU features and deferred rendering to optimize performance. Only by using these tricks can they provide a smooth scrolling and zooming experience. The side effect of this is that the respective scrolling properties and events are not invoked until the panning has come to an end, which in turn means a limitation of this visualization workaround is that it's only updated once the user has finished scrolling.</p> <h2>And Some Fine-Tuning</h2> <p>As the name already says, one of the core features of HTML is its hyperlinked nature. The content available from SilverlightShow is no different in that. Articles and news contain links to external sources and other web sites all the time. Since we have even less control over that external content in a technical sense, and also out of legal reasons and other considerations, we decided that users of the SilverlightShow app should not be able to navigate to that external content within the web browser control, and within the context of the phone app itself. Instead, the idea is to intercept those navigational events and relay them to the built-in web browser of the Windows Phone operating system. This not only makes sure that the target page is displayed correctly and in the best way possible on the phone, but it also makes it as clear as possible to the user that they're leaving the content provided by SilverlightShow. At the same time, features like fast app switching and tombstoning allow a quick and seamless transition back to the app with no drawbacks for the user.</p> <p>To make this work, you can simply handle <a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.webbrowser.navigating(v=vs.92).aspx">the "Navigating" event</a> of the web browser controls, cancel the navigation that is about to happen, and simply hand off that task to the platform's built-in web browser:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">private</span> <span class="kwrd">void</span> WebBrowser_Navigating(<span class="kwrd">object</span> sender, NavigatingEventArgs e)</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="rem">// we cancel all internal navigation...</span></pre> <!--CRLF--> <pre class="alteven"> var uri = e.Uri;</pre> <!--CRLF--> <pre class="alt"> e.Cancel = <span class="kwrd">true</span>;</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">try</span></pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> <span class="rem">// ... and instead launch an external web browser for this</span></pre> <!--CRLF--> <pre class="alteven"> WebBrowserTask task = <span class="kwrd">new</span> WebBrowserTask();</pre> <!--CRLF--> <pre class="alt"> task.Uri = uri;</pre> <!--CRLF--> <pre class="alteven"> task.Show();</pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">catch</span> (Exception ex)</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// do some error handling</span></pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven">}</pre> <!--CRLF--></div> </div> <p><em>Note: You may need to add some additional code to prevent that logic from kicking in when you set or refresh your own internal content.</em></p> <h2>Conclusion</h2> <p>The web browser control that is built into the framework is a powerful tool to display HTML content within your application. Unfortunately, it comes with some limitations that require unconventional and creative workarounds and solutions to provide a good user experience. Some issues like the missing scroll bars even cannot be fully resolved with the current given possibilities. If you can live with these limitations and the additional effort to achieve seemingly simply things, the control still provides a great way to present rich content, especially if it's already available as HTML.</p> http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx#comments http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-3.aspx Thu, 12 Apr 2012 10:44:00 GMT Creating the SilverlightShow Windows Phone App: part 2 <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: Creating the SilverlightShow #WindowsPhone App: part 2 #wpdev" data-url="http://slshow.net/HxccRV">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>In the <a href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx">first part</a> of this mini series I was mostly talking about the process of developing the SilverlightShow Windows Phone application, and didn't discuss any of the technical specifics. Today I want to dive into some of the details around downloading and optimizing RSS feeds. I not only want to give you insight into the particular problems we were facing, but also some hopefully useful advice and guidelines should you ever want to develop a similar feature for your own application. If you haven't used or seen the app yet, you can watch a quick intro video <a href="http://www.silverlightshow.net/video/SilverlightShow-WP7-App-Intro.aspx">here</a> and find it on the Marketplace <a href="http://windowsphone.com/s?appid=aa47a1d4-3418-496d-862f-36eb1ec78f43">here</a>.</p> <h2>It's all about content</h2> <p>As described before, the SilverlightShow portal has already established a nice infrastructure for creating, maintaining and accessing its rich content, and that includes multiple RSS feeds which seamlessly cover all the data we need in the mobile app. </p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>More resources...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> So the first step was to prototype an app that could download and display the content provided by these feeds, to evaluate whether going down that road is feasible. <p>When you search for samples and tutorials on RSS feed reading on Windows Phone, you inevitably will find articles that recommend using the Syndication assembly that comes with Silverlight, which indeed is safe to use on the phone too. I won't post any links here, because I strongly vote against doing this. If you still want to try it out yourself, you will realize that the parser included with this library is really strict, and unfortunately that means it's fighting severe problems with real world RSS feeds. A single unexpected space character somewhere in the data of feed items <a href="https://connect.microsoft.com/VisualStudio/feedback/details/325421/syndicationfeed-load-fails-to-parse-datetime-against-a-real-world-feeds-ie7-can-read">can result in an exception</a> and the inability to parse the feed at all. As you can see in the old Connect bug I've just linked to, people continue complaining about this and other issues with the Syndication framework even though the bug entry itself is "closed as fixed".  </p> <h2>Don't use System.ServiceModel.Syndication.dll</h2> <p>In an environment where you have full control over the very detail of the feeds you may be able to work around this problem, but most of the time you are not. For example here at SilverlightShow, we weren't able to fix some of the glitches that let the Syndication framework fail, because the feeds are not created manually, but handled by a third-party framework for generating RSS feeds from existing data. So what's the alternative? Fortunately, parsing RSS feeds manually isn't such a big deal, because in the end it all comes down to walking an XML tree and extracting the data you want from its elements. When you do that, you are able to handle the specific problems of the feed you're dealing with yourself, or can create a parse algorithm for e.g. date values (these often are problematic) that is more forgiving and flexible than the built-in parser of the Syndication framework. </p> <p>If you're looking for a full example, I'm pleased to announce that the official RSS starter kit for Windows Phone switched to a more robust way of parsing the feeds just a few days ago, and can now be recommended as a great starting point for these kinds of applications. It used to use the Syndication framework but Chris Koenig decided to change the implementation to manual processing recently. You can find its web site <a href="http://aka.ms/wpskrss">here</a>, and its GitHub page <a href="https://github.com/ChrisKoenig/Windows-Phone-Starter-Kit-for-RSS">here</a>. The code for downloading and parsing essentially looks like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="rem">// retrieve the feed and it's items from the internet</span></pre> <!--CRLF--> <pre class="alteven">var request = HttpWebRequest.CreateHttp(SelectedFeed.RssUrl) <span class="kwrd">as</span> HttpWebRequest;</pre> <!--CRLF--> <pre class="alt">request.BeginGetResponse((token) =></pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="rem">// process the response</span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">using</span> (var response = request.EndGetResponse(token) <span class="kwrd">as</span> HttpWebResponse)</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">using</span> (var stream = response.GetResponseStream())</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">using</span> (var reader = XmlReader.Create(stream))</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> var doc = XDocument.Load(reader);</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alt"> feed.Description = doc.Root.GetSafeElementString(<span class="str">"summary"</span>);</pre> <!--CRLF--> <pre class="alteven"> </pre> <!--CRLF--> <pre class="alt"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> doc.Root.Elements(doc.Root.GetDefaultNamespace() + <span class="str">"entry"</span>))</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> var newItem = <span class="kwrd">new</span> RssItem()</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> Title = item.GetSafeElementString(<span class="str">"title"</span>),</pre> <!--CRLF--> <pre class="alt"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>In the SilverlightShow app, we're using a slightly different approach to squeeze out the last bit of performance :). Instead of working with Linq to Xml, the code uses the XmlReader object directly to sequentially extract all the required information from the feed. Like:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">private</span> <span class="kwrd">void</span> ReadFeed(XmlReader xmlReader, FeedData result)</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">try</span></pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> xmlReader.ReadStartElement(<span class="str">"rss"</span>);</pre> <!--CRLF--> <pre class="alteven"> xmlReader.ReadStartElement(<span class="str">"channel"</span>);</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">while</span> (xmlReader.IsStartElement())</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> <span class="kwrd">if</span> (xmlReader.IsStartElement(<span class="str">"title"</span>))</pre> <!--CRLF--> <pre class="alteven"> {</pre> <!--CRLF--> <pre class="alt"> result.Title = xmlReader.ReadElementContentAsString();</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alt"> } </pre> <!--CRLF--> <pre class="alteven"> } </pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>Working this way, you are flexible enough to e.g. apply a more relaxed date parsing, or process the content in any way you want. You'll also be able to do your own custom error handling, for example to only skip a single item if you're unable to parse it, instead of throwing away the whole feed content when you run into a small error.</p> <h2>Optimizations, optimizations, optimizations</h2> <p>Now that we were able to correctly load the content in question onto the phone, it was important to evaluate whether doing this was a practical solution. One of the invaluable helpers in the tool box of every developer to analyze these scenarios is a network monitoring tool. I generally start with Fiddler because it's so simple and convenient to use, and only switch to more advanced tools when Fiddler isn't able to capture the traffic or provide the information I need. For developing with the Windows Phone emulator, Fiddler is perfectly fine as long as you remember to first start Fiddler and then launch the emulator afterwards (or you won't be able to capture any of the emulator's traffic). You can find more information and download Fiddler for free <a href="http://www.fiddler2.com/">here</a>. </p> <p>In the case of analyzing the RSS feeds of SilverlightShow you don't even have to go through the Windows Phone emulator, but can access the feed directly in your browser and watch the traffic in Fiddler that way. One of the particular feeds we are interested in is the one that retrieves article content from the site:</p> <p><a href="http://www.silverlightshow.net/FeedGenerator.ashx?type=Article">http://www.silverlightshow.net/FeedGenerator.ashx?type=Article</a></p> <p>At the time of writing this article, the size of the returned 25 items in this feed is a whopping 1.5 MiB:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_2.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________________image_thumb.png" width="175" height="26" /></a></p> <p>Obviously that amount of data is unsuitable to be transferred to a mobile device frequently, where people often are using slow connections or even worse, have to pay for the transferred data byte-by-byte. It was clear that we needed to introduce a whole lot of optimization and improvements to make this work. Fortunately, we had already reckoned this situation and collected a bunch of ideas during the design phase.</p> <h3>Squashing the Content</h3> <p>One of the particular details we quickly identified for optimization are the code snippets that are included with most of the articles on SilverlightShow. Authors can use <a href="http://lvildosola.blogspot.de/2009/03/code-snippet-plugin-for-windows-live.html">a nice plug-in</a> to Windows Live Writer to beautify the code they paste. Behind the scenes, the coloring and formatting of the code is achieved by applying CSS styles to it. This can tremendously increase the size of the HTML necessary to display the code. For example, this small snippet of code (147 characters) taken from a recent article…</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt"><span class="kwrd">private</span> <span class="kwrd">void</span> button1_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre class="alteven">{</pre> <!--CRLF--> <pre class="alt"> MyBeep myBeep = <span class="kwrd">new</span> MyBeep();</pre> <!--CRLF--> <pre class="alteven"> myBeep.PlaySound(BeepTypes.Information);</pre> <!--CRLF--> <pre class="alt">}</pre> <!--CRLF--></div> </div> <p>… is turned into a block of <strong>3313 characters</strong> in the RSS feed. In addition to the CSS styling information, the required encoding of HTML entities also adds quite a lot to this size. This means that we see a size increase of factor 22 here just for the added benefit of having colored code snippets. Stripping this formatting from the content when it is requested by the phone was a natural consequence. We still have some code formatting in the app (like using a fixed-size font), but without the syntax highlighting. This was one of the areas that required some work on the existing services. A newly added parameter for the feed generator solved this problem nicely. You can see the result using the following url:</p> <p><a href="http://www.silverlightshow.net/FeedGenerator.ashx?type=Article&stripCodeFormatting=true">http://www.silverlightshow.net/FeedGenerator.ashx?type=Article <br /> &stripCodeFormatting=true</a></p> <p>This change alone shrinks the size of the feed by approximately two thirds, depending on the actual content and the percentage of code in the current set of articles. At the moment, the new size is ~625 KiB:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_4.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_____________image_thumb_1.png" width="167" height="21" /></a></p> <p>The content on the phone after that looks similar to this…</p> <pre style="padding: 10px; background-color: #555555; font-family: 'courier new', consolas; color: #ffffff;">private void button1_Click(object sender, RoutedEventArgs e) { MyBeep myBeep = new MyBeep(); myBeep.PlaySound(BeepTypes.Information); }</pre> <p>… and only requires 118 additional characters <em>per document, </em>and these are generated on the device itself (more on that later).</p> <p>In addition to this, we also reduced the maximum number of articles returned to the phone from 25 to 10, as we felt that this is sufficient for the mobile device where you are more interested in being notified about new content than reading the archives. This of course also reduces the total size a lot.</p> <h4>Parsing HTML</h4> <p>A side note on stripping the code tags and CSS from the original content: this actually is a very interesting topic that we unfortunately do not have the time and space to cover in more detail here. Real-world HTML often does not follow the strict rules of normal XML content; especially when you're working with WSIWYG editors, and when multiple authors are responsible for a merged final output, the result might look significantly different from what you would expect. In most cases, trying to treat HTML as XML, and assuming that it follows the same strict rules is a dangerous thing to do. Therefore, I generally recommend against the usual approaches people attempt to follow when they work with that kind of data. In particular, <strong>do not</strong>:</p> <ul> <li>Use regular expressions</li> <li>Use string replacement</li> <li>Use XML readers or documents</li> </ul> <p>All of these fail quickly with faulty HTML, and are not flexible enough to handle the situations you <em>will</em> come across, with reasonable effort. So what is the alternative here? There are some projects out there that have put quite some work into creating more tolerant parsers for HTML that are capable of handling malformed tags and content better than probably any custom solution you (and I) would be able to create within the limits of a small phone project. One of these projects is the <a href="http://htmlagilitypack.codeplex.com/">Html Agility Pack</a> hosted on CodePlex. It has built-in support for Windows Phone and not only helped us strip the code formatting from the articles, but also to improve some other details of the content, like dealing with multi-column layouts and turn it into something that is more suitable for the small phone screen.</p> <p>If you are ever in the situation where you need to parse HTML, I recommend you take a look at this or similar projects to make your life easier, instead of trying to reinvent the wheel.</p> <h3>Local Caching</h3> <p>Another important feature of the SilverlightShow app is that we do not pull all the RSS items from the feeds whenever you hit the refresh button or start the app on your device. Instead, we locally store the items and only fetch those that we haven't retrieved in the past yet. To achieve this, another small extension of the existing service was implemented that allows you to restrict the returned data by date, by appending an "after" parameter to the url:</p> <p><a href="http://www.silverlightshow.net/FeedGenerator.ashx?type=Article&stripCodeFormatting=true&after=2012-04-03%2014:57:57Z">http://www.silverlightshow.net/FeedGenerator.ashx?type=Article <br /> &stripCodeFormatting=true <br /> &after=2012-04-03%2014:57:57Z</a></p> <p>Retrieving a single new article then results in a really small transferred size, depending of course on the actual article content. At the moment, retrieving only the newest article for example only requires transmitting 15.428 bytes.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________image_6.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_thumb_2.png" width="160" height="21" /></a></p> <p>This means that after the initial download of the full articles list, successive downloads will be much faster.</p> <h3>Mother of Optimization: Dynamic Data Compression</h3> <p>Surprisingly few people know about the possibility to compress dynamic content on the fly in IIS. By default this feature is disabled, and you may even have to add it manually using the "Turn Windows features on or off" or server roles dialog of the operating system:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________image_8.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/__________image_thumb_3.png" width="429" height="362" /></a></p> <p>This is a feature that comes virtually at no cost for normal application developers. In my experience, it also has little to no impact on existing clients and applications, as you are able to configure its details per application, and clients explicitly have to opt-in to make use of it (meaning if they don't support it, turning it on shouldn't break anything for existing clients). It does have some implications for your server however, because obviously it needs to compress the content it delivers on the fly now, which increases CPU load; if you're in doubt, talk to your system administrator or provider.</p> <p>Unfortunately, Windows Phone devs do not fall into the "normal application developers" category; even the most recent version of the SDK does not have built-in support for compressed content, which means the available networking classes do not explicitly opt-in to the feature and also do not do the decompression for you transparently. The benefit you get from implementing this manually however is tremendous for text-based content (like RSS feeds), so it's something you should always consider. As often, some people have done most of the work for you already. Morten Nielsen for example has created <a href="http://www.sharpgis.net/post/2012/01/23/Overwriting-the-default-WebRequest-used-by-WebClient.aspx">an implementation of this</a> that you can use with just a few lines of code, and the package also is conveniently available <a href="http://www.nuget.org/packages/SharpGIS.GZipWebClient">on NuGet</a>.</p> <p>I've used a very similar technique in all of my Windows Phone development that required downloading text-based content; for the SilverlightShow app, the code looks like this:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <div id="codeSnippet" class="csharpcode"> <pre class="alt">var request = WebRequest.CreateHttp(uri);</pre> <!--CRLF--> <pre class="alteven"><span class="rem">// opt-in to compressed content</span></pre> <!--CRLF--> <pre class="alt">request.Headers[HttpRequestHeader.AcceptEncoding] = <span class="str">"gzip"</span>;</pre> <!--CRLF--> <pre class="alteven">var ar = request.BeginGetResponse(GetResponse_Callback, feedResult);</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"><span class="kwrd">using</span> (var response = feedResult.Request.EndGetResponse(ar))</pre> <!--CRLF--> <pre class="alt">{</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">using</span> (var stream = response.GetResponseStream())</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// decide what to do</span></pre> <!--CRLF--> <pre class="alt"> Stream decodedStream;</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">if</span> (response.Headers[HttpRequestHeader.ContentEncoding] == <span class="str">"gzip"</span>)</pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> decodedStream = <span class="kwrd">new</span> GZipStream(stream, CompressionMode.Decompress);</pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven"> <span class="kwrd">else</span></pre> <!--CRLF--> <pre class="alt"> {</pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// simply use the original</span></pre> <!--CRLF--> <pre class="alt"> decodedStream = stream;</pre> <!--CRLF--> <pre class="alteven"> }</pre> <!--CRLF--> <pre class="alt"> </pre> <!--CRLF--> <pre class="alteven"> <span class="rem">// ...</span></pre> <!--CRLF--> <pre class="alt"> }</pre> <!--CRLF--> <pre class="alteven">} </pre> <!--CRLF--></div> </div> <p>Here, "GZipStream" is my own custom implementation similar to what Morten has developed himself. The savings are tremendous. The original feed that currently has 1,591,787 bytes, without any of the other phone optimizations applied, is reduced to a size of 302,537 bytes:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______image_10.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/________image_thumb_4.png" width="167" height="23" /></a></p> <h2>Final Comparison</h2> <p>Let's take a final look at the before and after situation for the articles RSS feed with all the optimizations in place:</p> <table border="1" cellspacing="0" cellpadding="2" width="643"> <tbody> <tr> <td valign="top" style="width: 179px;"> </td> <td valign="top" style="width: 207px;"><strong>Original RSS</strong></td> <td valign="top" style="width: 209px;"><strong>Optimized for the phone + gzipped</strong></td> <td valign="top" style="width: 46px;"> <p style="text-align: center;"><strong>Saved</strong></p> </td> </tr> <tr> <td valign="top" style="width: 179px;"><strong>Retrieving the full list (25/10)</strong></td> <td valign="top" style="width: 207px;"> <p style="margin-right: 0px;" dir="ltr">1,591,787 bytes</p> </td> <td valign="top" style="width: 209px;">91,399 bytes</td> <td valign="top" style="width: 46px;"> <p style="text-align: center;"><span style="color: #ff0000;">94%</span></p> </td> </tr> <tr> <td valign="top" style="width: 179px;"><strong>Update (1 new item)</strong></td> <td valign="top" style="width: 207px;"> <p style="margin-right: 0px;" dir="ltr">1,591,787 bytes</p> </td> <td valign="top" style="width: 209px;">~5,000 – 15,000 bytes</td> <td valign="top" style="width: 46px;"> <p style="text-align: center;"><span style="color: #ff0000;">>99%</span></p> </td> </tr> </tbody> </table> <p>This is a very reasonable amount of data to handle for the phone. Also please remember that we are only looking at the article feed here. All the other feeds we're using in the app (news, events etc.) are much smaller in their nature anyway, but have the same optimizations applied. This is one of the reasons why the app works well even with not so fast internet connections, and updating or refreshing the list typically only takes a few seconds, at the most.</p> <p>Now that we have the possibility to pull content into the app, and also optimized the amount of data that has to be transferred for this, what do we do with that content? It's all HTML formatted text, images, and tables – we need to find a way to nicely display that content to the user. This topic will be covered in the next part of the series.</p> http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx#comments http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App-part-2.aspx Wed, 11 Apr 2012 11:43:00 GMT Creating the SilverlightShow Windows Phone App: part 1 <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx" data-count="horizontal" data-text="Reading @Mister_Goodcat's article: Creating the SilverlightShow #WindowsPhone App: part 1 #wpdev" data-url="http://slshow.net/GCLG2S">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>At the end of February, the official SilverlightShow Windows Phone app has been accepted into the Marketplace. The app gives you access to some of the content of this website, including <strong>news</strong>, <strong>articles </strong>and <strong>events</strong>, and is completely free for use (also ad-free!). Some of the convenience features include the possibility to<strong> create reminders for upcoming events and webinars directly on your phone</strong>, to get <strong>notifications about new content in the form of live tiles</strong>, and to maintain a local list of <strong>favorites </strong>that allows you to permanently store items for later reading. If you haven’t checked out the app yet, you can find more details and a quick intro video <a href="http://www.silverlightshow.net/video/SilverlightShow-WP7-App-Intro.aspx">here</a>, or visit its Marketplace page <a href="http://windowsphone.com/s?appid=aa47a1d4-3418-496d-862f-36eb1ec78f43">here</a>.</p> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>More resources...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Advanced-MVVM-for-WPDev-Webinar.aspx">Recording of Peter's webinar: Advanced MVVM for Windows Phone Devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx">Peter's ebook on creating the SilverlightShow Windows Phone app</a></li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/silverlightshow_windows_phone.aspx"><img style="width: 80px; height: 113px; border-width: 0px; border-style: solid;" alt="Getting Ready for the Windows Phone 7 Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/sls_windowsphone_app.png" usemap="#rade_img_map_1291385581316" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p>The creation of the app was an interesting experience, because unlike other phone projects I had worked on in the past, this one wasn’t a greenfield development. Obviously the SilverlightShow portal already existed, had a long-established production infrastructure and already a lot of existing content available.  <br />  <br /> During the course of developing the application, we thought it would be a nice idea to share some of the experiences with the SilverlightShow readers, because it is a nice example of discussing a real-world application, with real-world problems (and solutions :)). The idea of this mini-series of articles was born, where you will discover both details about the development process as well as some technical challenges we came across. <strong>This first part will deal with the process itself, so prepare for some more text and less code (read: no code) than usual.</strong></p> <h2>Prerequisites</h2> <p>With almost every piece of software you are developing, you usually (hopefully?) don’t start coding right away, but begin with some sort of requirements engineering, and then create the concept of your software. You may not be aware of the order and existence of these actions if you’re only a hobby programmer, or you may not be familiar with the formal terms and definitions, but even if you’re only creating a really small app, these steps are part of the development process in one form or the other. We can sum up these two elements by two simple questions:</p> <ul> <li>What is it our software is intended to do?</li> <li>How shall our software achieve this goal?</li> </ul> <p>As I wrote, the details on how sophisticated you analyze these questions and the ways you maintain the results of this analysis is a direct result of several factors, like the development process you intend to use, your personal experience, external requirements, and the complexity of the project you’re taking on. Sometimes all this information may only exist in your head, in other situations it will result in huge documents being produced upfront.</p> <p>When you’re developing an app based on an already existing eco system, there are additional steps you need to perform. In particular, you have to do an analysis of the existing infrastructure to see what parts you can make use of and integrate with your own development, <em>how</em> you can achieve this, whether other parts require work or need to change, and what features you rely on are missing completely. Sometimes, the intended requirements of the result even depend on what’s possible to achieve with a reasonable amount of effort, taking the given system into consideration. This is how extending an existing system can be both good and evil: it may speed up your development when you’re able to reuse components that are already available, but it may also limit your possibilities, and even bring up whole new problems that you wouldn’t have to face if you started from scratch.</p> <h2>The Existing Infrastructure</h2> <p>Building an app for the SilverlightShow portal wasn’t any different in this. The web site obviously existed already, and a great variety of people, consisting of both the SilverlightShow staff as well as external authors, actively contributes to the content. To allow comfortable and easy editing, the SilverlightShow team has put a great amount of work into integrating the site nicely with WYSIWYG tools, especially Windows Live Writer. As a result, the content available on the site is maintained in a blog-like manner, and stored as rich content in a corresponding data store.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/______________image_2.png"><img style="border: 0px; background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/_______________image_thumb.png" width="418" height="203" /></a></p> <p>On the consuming side of things, we have the web user interface you’re directly interacting with at the moment, but there are other options to access the content of the site which are optimized for machine/automated access. This includes several RSS feeds that can be consumed by special reader software, so you can access the site through your favorite client and presentation software. Some other areas of the site also offer specialized web services tailored for being accessed by Silverlight clients.</p> <p><a href="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/___________image_4.png"><img style="border: 0px; background-image: none; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; padding-top: 0px;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/MisterGoodcat/____________image_thumb_1.png" width="243" height="175" /></a></p> <p>Since both working with the site itself as well as the authoring of content is a well-known, proven process that has evolved and been established over a longer period of time, it was a logical consequence to put the Windows Phone app on top of this existing infrastructure, and introduce as little changes as possible to the existing system. This was one of the first and most central requirements established in the development process of the app.</p> <h2>Requirements</h2> <p>Starting with the above information, we established a set of features we wanted to see in the app. In particular, we wanted to expose the most popular content of the site (news, articles, events/webinars), and at the same time make sure that we blend in nicely with the phone platform, by implementing typical features the user would expect: notifications, reminders, and a Metro-style native experience.</p> <h2>Concept</h2> <p>If you carefully read through the requirements and the result of the infrastructure analysis listed above, then maybe you can see how a lot of this more or less determined fundamental parts of the concept and later implementation already. Let’s pick some of the more interesting details, all of which will be covered over the course of this mini-series:</p> <ul> <li>Like said, we wanted to make use of the existing system and introduce as little changes as possible. A logical consequence of this was that we would make use of the already existing rich content directly if possible, so both the web interface and phone app could work directly on the same data.</li> <li>Another logical step of this was to use the already existing RSS feeds to get access to that data, instead of creating a whole new solution that would exist in parallel (and require additional implementation and maintenance costs).</li> <li>Consequently, that same premise also affected features of the app you would not expect or think about at first. Take the notifications requirement, for example. Implementing a full-blown push notification solution would’ve required setting up quite some additional server infrastructure and server-side logic, something that we didn’t want to do. Eventually, this resulted in the decision to use a local background agent to add the notification features to the app.</li> <li>Since we wanted to create a nice and smooth Metro-style experience with the app, we ruled out alternate ways of creating such an accompanying app pretty quickly. For example, I have seen quite some “wrapper” apps in the Marketplace that are using a web browser control to display a mobile version of a web site – simple, quick to set up, but in no way living up to the expectations of the SilverlightShow users and definitely not what we were looking for. We wanted to present a rich, familiar look and feel based on a native Silverlight implementation. And, after all, this is SilverlightShow.net, not WebBrowserControlWrapper.net :-). </li> </ul> <h2>Prototype</h2> <p>In some areas, we weren’t sure whether it really would be possible to achieve good results in terms of performance and user experience by using the concept we created. This is a common problem when you’re developing software: sometimes the complexity is just too high, or the involved technology is not understood well enough or has too many dependencies to allow for a definite answer and final design just by thinking about it in theory. In these cases, the way you should probably take into consideration is to create a prototype. This is a small piece of software that takes on the most pressing aspects of your concept and delivers a proof that what you intend to do will work as expected, or can work by modifying some details of the concept or add tuning – hence the naming “proof of concept”. </p> <p>This is exactly what we did with some of the fundamental topics I have listed above. The small prototype allowed us to eliminate some mistakes in the concept that had slipped through, and to identify other issues we would be running into later on, which we now could plan for accordingly, early in the process. This very short phase of the development process helped enormously with clarifying some details and laying out the foundation and basic structure of the app.</p> <p>By the way, the result of creating a prototype can also be that what you intended to do is not feasible – you should not think of a situation like that as a defeat, but a huge success. Imagine the wasted effort if you discovered the dead end only months after starting development. It’s much better to return to the drawing board early.</p> <h2>Implementation</h2> <p>For a passionate developer, starting with the actual implementation is the most exciting moment during a development process like this, after having built up all the excitement during the previous phases. And if you have worked on some projects like that before, you know that during implementation you get to crack the real problems, low-level, that nobody anticipated when they wrote the specs. Even when you have used advanced techniques like prototyping you <em>will</em> run into those pesky little details in your daily work that you hate, curse, and love to beat. So did we during the implementation phase of the app – some of these details and experiences will be covered in the next part of the series, and it will become a lot more technical then.</p> <h2>Conclusion</h2> <p>I didn’t go into the details of specific techniques of requirements engineering, creating specifications or even the implementation process itself. This of course exceeds the scope of this article. But whether you’re using agile processes or classic approaches doesn’t matter. What I wanted to show you is that things you may know from your day job can also be applied to this much smaller scale of creating relatively simple phone apps, and that it in fact helps with being more effective. I hope you enjoyed this first part, and are looking forward to dive into some of the technical problems we were facing next time.</p> http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx editorial@silverlightshow.net (Peter Kuhn ) http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx#comments http://www.silverlightshow.net/items/Creating-the-SilverlightShow-Windows-Phone-App.aspx Wed, 21 Mar 2012 10:06:00 GMT Consume JSON with Windows Phone: a seamless solution <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx" data-count="horizontal" data-text="Read @aboschin's article 'Consume JSON with #WindowsPhone: a seamless solution' #wpdev" data-url="http://slshow.net/zRYgPP">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p style="text-align: justify;">One of the growing needs of these days, is the requirements of exposing services that are available to multiple platforms. This request come obviously from the increasing availability of a number of mobile platforms that is forcing companies to adopt strategies to decrease the complexity and use technologies that are able to respect the verb "write once and use everywhere". </p> <div style="border:1px solid #dddddd;width: 200px; padding-top: 5px; padding-bottom: 5px; padding-left: 10px; margin-top: 5px; margin-left: 10px; float: right; background-color: #f3f3f3; border-image: initial;"> <h3>Don't miss...</h3> <ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 20px; font-size: 12px; list-style-type: circle;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Recording-of-Windows-Phone-Raw-Camera-Webinar.aspx">Recording of Webinar: Windows Phone Raw Camera Access</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/items/Windows-Phone-7.1-Local-SQL-Database.aspx">8-part Article Series: Windows Phone 7.5</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx">The ebook 'Getting Ready for the Windows Phone Exam 70-599':</a> </li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"><img style="border:0px solid; width: 100px; height: 141px; border-image: initial;" alt="Getting Ready for the Windows Phone Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/wp7_exam_cover.png" /><br /> <strong><span style="font-size: 13px;">($4.99)</span></strong></a></p> <strong> <a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"></a> <p style="font-size: 12px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </strong></div> <p style="text-align: justify;"><strong>Javascript object notation</strong> - or as everyone know for sure, JSON - is something that has emerged as the common denominator, when the need is to expose services and APIs that may be easily consumed by multiple platforms. JSON is a simple notation - born long before the birth of the today's mobile world - that is able to describe object instances with a javascript syntax. The primary feature of JSON is the compactness, that is better than any other text based serialization strategy and many times better than XML. JSON is made of a combination of curly and square braces, of comma, colon and quotes. Explaining the syntax of JSON is out of the scope of this article but here is a basic example of the notation:</p> <div style="text-align: justify;"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> { <span style="color: #006080;">"FirstName"</span> : <span style="color: #006080;">"Andrea"</span>, <span style="color: #006080;">"LastName"</span> : <span style="color: #006080;">"Boschin"</span>, <span style="color: #006080;">"Age"</span> : 43 }</pre> <!--CRLF--></div> </div> <p style="text-align: justify;">This notation, as you can easily understand, describes a Person instance that exposes FirstName, LastName and Age properties. JSON let you describe objects and arrays and it always remain compact in size. The reason of its popularity is not only about compactness, but comes from the fact that every platform, mobile or not, has a way to serialize and deserialize this smart notation.</p> <p style="text-align: justify;">Windows Phone is not different in this. Including the System.ServiceModel.Web.dll you have a DataContractJsonSerializer class that is able to perform the required conversion between JSON to plain objects and viceversa. But what about if you have to create a json service and consume it with Windows Phone? For us, developers that usually take advantage of great Visual Studio IDE, able to generate code on behalf of us, using a json service may be matter of give up of helpers and write all by hand.</p> <h4 style="text-align: justify;">Architect your service</h4> <p style="text-align: justify;">So let say you have the common need of expose a set of APIs from your website and obviously you want to create a native app for Windows Phone that have to consume these APIs. The requirement is to prepare the connection points to be ready to be consumed by other devices so you want to use JSON as output. </p> <p style="text-align: justify;">The first thing to do is configure your service. WCF is a good starting point because, thanks to the WebHttpBinding, you can write services, with the common constraints you already know and then configure an endpoint to accept calls made with json. The starting point, as usual is to create the contract:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> [ServiceContract]</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> [ServiceKnownType(<span style="color: #006080;">"GetKnownTypes"</span>, <span style="color: #0000ff;">typeof</span>(KnownTypesProvider))]</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">interface</span> ITestService</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> [OperationContract]</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> [WebInvoke(</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> Method = <span style="color: #006080;">"POST"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> BodyStyle = WebMessageBodyStyle.Wrapped,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> RequestFormat = WebMessageFormat.Json,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> ResponseFormat = WebMessageFormat.Json)]</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> Article GetArticleById(<span style="color: #0000ff;">int</span> id);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #008000;">// add here other methods...</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">In this snippet there are two important details. The service contract is decorated with the ServiceKnownType attribute that is useful to instruct your service about the types you need to serialize and deserialize. This attribute indicate a type to be the source of the types WCF has to know. This class has to expose the "GetKnownTypes" method:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> KnownTypesProvider</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">yield</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">typeof</span>(Article);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #008000;">// yield here other types...</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The code returns the Article type, but you have to add all other types that have to cross the service boundary, particularly if this type is not directly the return type of a method. </p> <p style="text-align: justify;">The other important thing to note is the WebInvoke attribute. This attribute, applied to the operations, determine the way the input and output will be serialized. In this sample I use WebMessageFormat.Json for both RequestFormat and ResponseFormat, meaning it will return and accept data formatted with json. Another important attribute is BodyStyle. Setting this argument as "Wrapped" means that we want WCF to encapsulate arguments in a envelope that describe the signature of the method. This wrapper contains the name of the method, and the name of the parameters. Here is an example ot the input and output of the above method:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #008000;">// Signature</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> Article GetArticleById(<span style="color: #0000ff;">int</span> id);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #008000;">// Input Message</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> {<span style="color: #006080;">"id"</span>:27}</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #008000;">// Output Message</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {<span style="color: #006080;">"GetArticleByIdResult"</span>:{<span style="color: #006080;">"Id"</span>:27,<span style="color: #006080;">"MediumVote"</span>:0,<span style="color: #006080;">"Title"</span>:<span style="color: #006080;">"test"</span>,<span style="color: #006080;">"VoteCount"</span>:0}}</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">Once the contract has been prepared now you can implement all the methods you need. In the example attached to the article you will find all the needed code. The most important thing is the configuration of the service, in the Web.Config. This chunk of code specified the connection endpoint and some important details about the nature of the binding and transport:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">system.serviceModel</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">services</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">service</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="XPG.WindowsPhoneJson.Services.TestService"</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">endpoint</span> <span style="color: #ff0000;">address</span><span style="color: #0000ff;">=""</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #ff0000;">binding</span><span style="color: #0000ff;">="webHttpBinding"</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #ff0000;">contract</span><span style="color: #0000ff;">="XPG.WindowsPhoneJson.Services.ITestService"</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #ff0000;">behaviorConfiguration</span><span style="color: #0000ff;">="ITestService_WebHttp"</span> <span style="color: #0000ff;">/></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">service</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">services</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">behaviors</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">endpointBehaviors</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">behavior</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ITestService_WebHttp"</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;"><</span><span style="color: #800000;">webHttp</span> <span style="color: #0000ff;">/></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">behavior</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">endpointBehaviors</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">behaviors</span><span style="color: #0000ff;">></span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> <span style="color: #0000ff;"></</span><span style="color: #800000;">system.serviceModel</span><span style="color: #0000ff;">></span></pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The keys of this configuration are the webHttpBinding assigned to the binding attribute and the <webHttp /> element. These two configurations enable our service to accept calls with simple POST and make the service completely interoperable with a number of platforms.</p> <h4 style="text-align: justify;">Architect your App</h4> <p style="text-align: justify;">Moving to the Windows Phone application, when all the methods of the services are implemented, you cannot simply generate a proxy as you do usually with services. To simplest way to consume the json service is to make POST calls using the WebClient class. This means write the json message, prepare the string to send to the service and then place the call. Then, when the service returns a value you have to make the deserialization. I really love to write code, but I do not like to write the same code lot of times to do always the same thing. So finally I put together a bunch of classes that simplify my work. </p> <p style="text-align: justify;">My solution is made of two classes: Channel is responsible of manage the communication between the client and server. It initializes the WebClient, sets the required headers and then send the message along the wire. Then, when the answer returns, it check for errors and cleanup the resources. On the other side the JsonSerializer use a DataContractJsonSerializer to prepare the message to send and read the returning answer:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Call<K>(<span style="color: #0000ff;">string</span> method, <span style="color: #0000ff;">object</span> args, Action<K> success, Action<Exception> fail)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">string</span> message = <span style="color: #0000ff;">this</span>.Parser.Serialize(args);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> Uri uriToCall = <span style="color: #0000ff;">new</span> Uri(<span style="color: #0000ff;">this</span>.Uri.AbsoluteUri + <span style="color: #006080;">"/"</span> + method);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">this</span>.Client.Headers[HttpRequestHeader.ContentType] = <span style="color: #006080;">"application/json"</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> UploadStringCompletedEventHandler handler = <span style="color: #0000ff;">null</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> handler = (s, e) =></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">this</span>.Client.UploadStringCompleted -= handler;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;">if</span> (e.Error != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> fail(e.Error);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> K result = <span style="color: #0000ff;">this</span>.Parser.Deserialize<K>(method, e.Result);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> success(result);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> <span style="color: #0000ff;">this</span>.Client.UploadStringCompleted += handler;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">this</span>.Client.UploadStringAsync(uriToCall, message);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The above method, is from the Channel class. as you can see it accept a method name (the name of the service operation to call) and an args parameter. This argument, of type object, is used to easily pass the arguments using anonymous types. Then the method prepares the uri, attaching the method name to the base uri of the service. Finally it sets the application/json content-type and place the call. The JsonSerializer class collaborate with the Call method:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> T Deserialize<T>(<span style="color: #0000ff;">string</span> method, <span style="color: #0000ff;">string</span> message)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> Match match = Regex.Match(message, <span style="color: #006080;">@"{"</span><span style="color: #006080;">""</span> + method + <span style="color: #006080;">@"Result"</span><span style="color: #006080;">":(?<inner>.*)}"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">if</span> (match.Success)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">return</span> FromJson<T>(match.Groups[<span style="color: #006080;">"inner"</span>].Value);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> FormatException(<span style="color: #006080;">"Message format is not valid"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Serialize(<span style="color: #0000ff;">object</span> args)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> Type type = args.GetType();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> StringBuilder builder = <span style="color: #0000ff;">new</span> StringBuilder();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">bool</span> isFirst = <span style="color: #0000ff;">true</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> builder.Append(<span style="color: #006080;">"{"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> <span style="color: #0000ff;">foreach</span> (PropertyInfo property <span style="color: #0000ff;">in</span> type.GetProperties(BindingFlags.Public | BindingFlags.Instance))</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> <span style="color: #0000ff;">object</span> <span style="color: #0000ff;">value</span> = property.GetValue(args, <span style="color: #0000ff;">null</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #0000ff;">if</span> (!isFirst) builder.Append(<span style="color: #006080;">","</span>); <span style="color: #0000ff;">else</span> isFirst = <span style="color: #0000ff;">false</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> builder.AppendFormat(<span style="color: #006080;">"\"{0}\":{1}"</span>, property.Name, <span style="color: #0000ff;">this</span>.ToJson(<span style="color: #0000ff;">value</span>));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> builder.Append(<span style="color: #006080;">"}"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> <span style="color: #0000ff;">return</span> builder.ToString();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The trick is done creating the right wrapping code. The DataContractJsonSerializer simple convert the object to json but it does not directly handles the wrapped format of the message for the json service. So, if in the Deserialize method I strip away the wrapper just before of passing the message to the DataContractJsonSerializer , in the Serialize method I read the properties of the args value and I add the wrap calling the DataContractJsonSerializer of each parameter. </p> <p style="text-align: justify;"><a href="http://www.silverlightshow.net/Storage/Users/AndreaBoschin/image_5.png"><img style="border:0px; border-image: initial; background-image: none; margin-top: 6px; margin-right: 15px; margin-bottom: 0px; margin-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; float: left;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/AndreaBoschin/_image_thumb.png" width="276" height="261" /></a>Unfortunately, the DataContractJsonSerializer needs to know the types that it has to serialize or deserialize. In a normal web service this problem is handled generating a copy ot the DataContracts on the client side, but her we have not a copy of these classes. So we have to manage add a copy of the data contracts to the client solution. This is done creating a link between the Windows Phone application project and the Service application project. In a real world example you shoud generate data contract in a specific assembly and then link these classes in another assembly, compiled for Windows Phone. </p> <p style="text-align: justify;">In the figure on the left side you see the solution where the Article and KnowTypesProvider class are defined in the server assembly and linked in the WP7 class library. The important thing to note is that the base namespace for both the classes is the same "XPG.WindowsPhoneJson.Entities" because I've removed the "WP7" part in the settings. After you linked the assemblies on the respective part (service and client) you can instruct the DataContractJsonSerializer to use them:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> T FromJson<T>(<span style="color: #0000ff;">string</span> json)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> DataContractJsonSerializer dcjs =</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">new</span> DataContractJsonSerializer(<span style="color: #0000ff;">typeof</span>(T), KnownTypesProvider.GetKnownTypes(<span style="color: #0000ff;">null</span>));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">using</span> (MemoryStream stream = <span style="color: #0000ff;">new</span> MemoryStream(Encoding.UTF8.GetBytes(json)))</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">return</span> (T)dcjs.ReadObject(stream);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> ToJson(<span style="color: #0000ff;">object</span> <span style="color: #0000ff;">value</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> DataContractJsonSerializer dcjs =</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #0000ff;">new</span> DataContractJsonSerializer(<span style="color: #0000ff;">value</span>.GetType(), KnownTypesProvider.GetKnownTypes(<span style="color: #0000ff;">null</span>));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">using</span> (MemoryStream stream = <span style="color: #0000ff;">new</span> MemoryStream())</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> dcjs.WriteObject(stream, <span style="color: #0000ff;">value</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;">return</span> Encoding.UTF8.GetString(stream.ToArray(), 0, (<span style="color: #0000ff;">int</span>)stream.Length);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> }</pre> <!--CRLF--></div> </div> </div> <h4 style="text-align: justify;">Write your own proxy</h4> <p style="text-align: justify;">When you generate code from a service endpoint, side by side with your datacontracts, you get the main wrapper for the service under the form of a class that is usually called proxy. It main scope is to create an abstraction of the service to provide a way to consume its methods seamless. Once the Channel class has been build, is become very easy to write a proxy for a json service. Thanks to the structure I've illustrated it is a matter of write a single line of code, in a method that serves as a way to make parameters more user friendly. Here is a simple service wrapper based on the Channel class:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> TestService : Channel<JsonSerializer></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">public</span> TestService(Uri uri)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> : <span style="color: #0000ff;">base</span>(uri)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> { }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> GetArticleById(<span style="color: #0000ff;">int</span> id, Action<Article> success, Action<Exception> fail)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;">base</span>.Call<Article>(MethodBase.GetCurrentMethod().Name, <span style="color: #0000ff;">new</span> { id }, success, fail);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> VoteArticle(<span style="color: #0000ff;">int</span> id, <span style="color: #0000ff;">int</span> vote, Action<<span style="color: #0000ff;">int</span>> success, Action<Exception> fail)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;">base</span>.Call<<span style="color: #0000ff;">int</span>>(MethodBase.GetCurrentMethod().Name, <span style="color: #0000ff;">new</span> { id, vote }, success, fail);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> SaveArticle(Article article, Action success, Action<Exception> fail)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> <span style="color: #0000ff;">base</span>.Call(MethodBase.GetCurrentMethod().Name, <span style="color: #0000ff;">new</span> { article }, success, fail);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">Thanks to the call method you can write a method that is ready to the asynchronous nature of network calls made with windows phone. You can user the generic method when you need to return a value or the base implementation when the method returns void. The first parameter is the name of the method you want to call. If you respect the convention of calling the proxy method with the same name of the service method you can use the MethodBase.GetCurrentMethod() to retrieve the name of the method to call. </p> <p style="text-align: justify;">Finally it is important you also use the same name for method parameters. When you pass the arguments as an anonymous type, Visual Studio automatically create the properties with the same name as the parameter we pass. Internally the Call method scans these properties and add them to the service call with the right name.</p> <h4 style="text-align: justify;">Beat the competitors</h4> <p style="text-align: justify;">The proxy you have created in this brief article is highly reusable, but the same is true if you think at the output of the web service. This let you provide a service that is fully interoperable with all the platforms, but Windows Phone will beat other competitors in term of fast development, using the services in a seamless way. As a side note, please be sure that you can apply the same tecnique to provide a version of the proxy to Silverlight.</p> <p style="text-align: justify;"><a href="http://www.silverlightshow.net/Storage/Sources/XPG.WindowsPhoneJson.zip"><strong>Download the source code</strong></a></p> http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx editorial@silverlightshow.net (Andrea Boschin ) http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx#comments http://www.silverlightshow.net/items/Consume-JSON-with-Windows-Phone-a-seamless-solution.aspx Wed, 14 Mar 2012 10:47:00 GMT Windows Phone + SignalR = Awesome Possibilities! <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx" data-count="horizontal" data-text="Reading @samidip's article '#WindowsPhone + #SignalR = Awesome Possibilities!' #wpdev" data-url="http://slshow.net/xgcRV8">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p>Real-time communication. Many software applications on variety of platforms & form factors have a genuine need for it. But persistent networks, real-time connectivity & asynchrony continue to challenge us developers in building such applications. Is there a silver lining? Could we have near-real-time communication in our mobile apps? Imagine the possibilities.</p> <h4><a href="http://www.silverlightshow.net/Storage/Sources/SignalR_WP7.zip">Download Source Code</a></h4> <h4> </h4> <h4>Live Demo</h4> <p>Now, let’s do something a little fun before we get to the crux of what this article is about. </p> <div style="border:1px solid #dddddd;border-image: initial; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; margin-right: 5px; padding-top: 5px;"> <h3>Don't miss...</h3> <ul style="list-style-type: circle; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/10-Best-Practices-for-Windows-Phone-Devs-Webinar.aspx">Recording of Samidip's Webinar: 10 Best Practices for WP devs</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/items/Producing-and-Consuming-OData-in-a-Silverlight-and-Windows-Phone-7-application.aspx">The article series: Producing and Consuming OData in a Silverlight and WP7 application</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/odata_cloud.aspx">Samidip's Ebook 'OData & Cloud Augmentation of Windows Phone Apps':</a> </li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/odata_cloud.aspx"><img style="width: 107px; height: 150px;" alt="Producing and Consuming OData in a Silverlight and WP7 App Ebook" src="http://www.silverlightshow.net/Storage/Ebooks/odata_cloud.png" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> How about a live demo of the sample application in action? Works from anywhere on earth with a data connection; in fact, more & diverse the user demographics, the merrier. Let’s do this: <ul> <li>This demo will work with your Windows Phone emulator; but better with your unlocked Windows Phone that can side-load apps, given XAP or source code. </li> <li>Download the Source Code & extract the Windows Phone solution. </li> <li>Load in Visual Studio, build & Deploy to emulator/phone. </li> <li>The sample Windows Phone app essentially shares your location & connects you to a backend SignalR server for continuous real-time chat. </li> <li>Go to <a href="http://signalrserver.cloudapp.net/" target="_blank">http://signalrserver.cloudapp.net/</a> and keep it open. </li> <li>Fire up the app and give yourself a name for the Chatroom. </li> <li>Share your location & join the fun. </li> <li>If on a Windows Phone, you should see a pushpin on the Bing map for your actual location (if allowed by your settings). On the emulator, you’ll start out at the mothership, that is, Seattle. Feel free to use the location simulator to fake your position. </li> <li>See yourself pop up in the chat dialog box? </li> <li>Now fire away what you want to say .. no profanity please. </li> <li>See what you say show up in your phone’s chat dialog & on the Server almost immediately? Fun, eh? </li> <li>Exit the chatroom and you’ll see yourself leave, along with a disappearing pushpin on map. </li> </ul> <p>The result should be something like this:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_24.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_10.png" width="604" height="284" /></a></p> <p>I’m hoping if we keep the site running, we can see Pushpins show up on different parts of the world map; the Bing map used should zoom in & out to accommodate all pins. Having said that, the server side code isn’t hosted on massive hardware. I’ll try to keep it up; but if load or other issues force it down, please feel free unpack the server code & run it locally. It is a simple MVC3 app that should run just fine on your machine. Only change you would have to do is to point your Windows Phone app to <em>Localhost</em>, instead of the above server. So, let’s hope the site stays up & we can see folks from different places show up on live map & chatroom.</p> <h4>Introduction</h4> <p>SignalR is an async persistent connection library for client-server communication that aids in building real-time, multi-user connected applications across multiple platforms. The connection between clients & server is persisted over best possible transport mechanism, which could be a combination of long polling, periodic polling & sockets. The point is the transport layer is abstracted away to provide a seamless persistent connection for ease of development in making connected applications across the web, mobile & other form factors.</p> <p>SignalR was started by <a href="https://twitter.com/#!/DamianEdwards" target="_blank">Damian Edwards</a> & <a href="https://twitter.com/#!/davidfowl" target="_blank">David Fowler</a> from the ASP.NET team and is now an OSS on GitHub (<a href="https://github.com/SignalR/SignalR" target="_blank">https://github.com/SignalR/SignalR</a>). Want to chat with these & other cool folks working with SignalR? Join the conversations @ <a href="http://jabbr.net/#/rooms/signalr" target="_blank">http://jabbr.net/#/rooms/signalr</a>. The easiest way to start using SignalR is to utilize the Nugets as need in your application. They are:</p> <ul> <li><a href="http://nuget.org/List/Packages/SignalR" target="_blank">SignalR</a> - Package for SignalR.Server and SignalR.Js </li> <li><a href="http://nuget.org/List/Packages/SignalR.Server" target="_blank">SignalR.Server</a> - Server components needed for SignalR endpoints </li> <li><a href="http://nuget.org/List/Packages/SignalR.Js" target="_blank">SignalR.Js</a> - Javascript client for SignalR </li> <li><a href="http://nuget.org/List/Packages/SignalR.Client" target="_blank">SignalR.Client</a> - .NET client for SignalR </li> <li><a href="http://nuget.org/List/Packages/SignalR.Ninject" target="_blank">SignalR.Ninject</a> - Ninject dependeny resolver for SignalR </li> </ul> <p>These can be incorporated in your project by using the visual Nuget Library Manager or the command-based Management console. This one statement gets you all dependencies:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_12.png"><img style="background-image: none; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_4.png" width="444" height="44" /></a></p> <p>While there are other technologies that have tried to solve the real-time communication problem, like Socket.IO or HTML5 WebSockets, few do it as simply as SignalR and support cross-platform between the web and mobile platforms like Windows Phone, <a href="https://github.com/DyKnow/SignalR-ObjC" target="_blank">iOS</a> & Android (through Mono). While the low-level <em>PersistenceConnection</em> class might give you more control, most times the abstraction over it called the <em>Hub</em> class & your implementation of it, will provide easy persistence between client & Server. Want to learn more about SignalR? Try these wonderful posts:</p> <ul> <li><a title="http://bit.ly/qeJFyf" href="http://bit.ly/qeJFyf">http://bit.ly/qeJFyf</a> </li> <li><a href="http://jbeckwith.com/2011/10/12/building-a-user-map-with-signalr-and-bing/">http://jbeckwith.com/2011/10/12/building-a-user-map-with-signalr-and-bing/</a> </li> <li><a href="http://blog.maartenballiauw.be/post/2011/12/06/Using-SignalR-to-broadcast-a-slide-deck.aspx">http://blog.maartenballiauw.be/post/2011/12/06/Using-SignalR-to-broadcast-a-slide-deck.aspx</a> </li> <li><a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=780">http://www.dotnetcurry.com/ShowArticle.aspx?ID=780</a> </li> </ul> <h4> </h4> <h4>The Sample</h4> <p>So, having learnt a little about SignalR, do you think it would work with and have applications in Windows Phone development? Absolutely! Real-time communication with a backend server on a personal device like the Windows Phone has potentially tons of ways to leverage the technology in Apps. Allow me to show you two here – mapping Windows Phone App users across the globe and real-time chat dialog between multiple Windows Phones & the web. The rest is up to your imagination ..</p> <h4>The Server</h4> <p>You obviously have choices here. I started with a default MVC3 web application; but wanted to change the look to showing mapping & chat dialog. First up, let’s get it ready to be a SignalR server. Here’s how to add the Nuget package:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_14.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_5.png" width="544" height="364" /></a></p> <p>With that, we know what a <em>Hub</em> is. Let us extend it to make something our own. We essentially want to uniquely keep track of Windows Phone users using our app; so let’s define a class for the phone clients:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #008000;">// Individual Phone clients.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> PhoneClient</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> PhoneClientId { get; set; }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">float</span> Latitude { get; set; }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">float</span> Longitude { get; set; }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> }</pre> <!--CRLF--></div> </div> <p>Next, let’s add functionality to add phone clients to Hub, disconnect & broadcast messages to all:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #008000;">// The Hub of communication.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> MessagingHub : Hub</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> List<PhoneClient> PhoneClientList = <span style="color: #0000ff;">new</span> List<PhoneClient>(); </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> JoinFromPhone(<span style="color: #0000ff;">string</span> phoneID, <span style="color: #0000ff;">float</span> latitude, <span style="color: #0000ff;">float</span> longitude)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> PhoneClient phoneClientToAdd = <span style="color: #0000ff;">new</span> PhoneClient();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> phoneClientToAdd.PhoneClientId = phoneID; </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> phoneClientToAdd.Latitude = latitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> phoneClientToAdd.Longitude = longitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> PhoneClientList.Add(phoneClientToAdd);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> Clients.addClient(phoneClientToAdd);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">this</span>.Caller.addClients(PhoneClientList.ToArray());</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Disconnect(<span style="color: #0000ff;">string</span> phoneID)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> PhoneClient client = <span style="color: #0000ff;">null</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #0000ff;">foreach</span> (PhoneClient existingClient <span style="color: #0000ff;">in</span> PhoneClientList)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">if</span> (phoneID == existingClient.PhoneClientId)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> client = existingClient;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> <span style="color: #0000ff;">break</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span> PhoneClientList.Remove(client);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum32" style="color: #606060;"> 32:</span> Clients.removeClient(client);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum33" style="color: #606060;"> 33:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum34" style="color: #606060;"> 34:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum35" style="color: #606060;"> 35:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> PushMessageToClients(<span style="color: #0000ff;">string</span> message)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum36" style="color: #606060;"> 36:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum37" style="color: #606060;"> 37:</span> Clients.addChatMessage(message);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum38" style="color: #606060;"> 38:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum39" style="color: #606060;"> 39:</span> }</pre> <!--CRLF--></div> </div> <p>Wondering what some of the function calls are within our Hub? Well .. that’s the magic! These are actually JavaScript methods defined in our web UI view. So, let’s shoot for a UI like this (in the Index view off our Home controller).. Chat dialog on left & Bing Maps to show the pushpins on the right:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_16.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_6.png" width="604" height="332" /></a></p> <p>Here’s what’s on the view, along with subtle styling included in the downloadable code:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <script charset=<span style="color: #006080;">"UTF-8"</span> type=<span style="color: #006080;">"text/javascript"</span> src=<span style="color: #006080;">"http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"</span>></script></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> <script src=<span style="color: #006080;">"@Url.Content("</span>~/Scripts/jquery-1.6.4.min.js<span style="color: #006080;">")"</span> type=<span style="color: #006080;">"text/javascript"</span>></script></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <script src=<span style="color: #006080;">"@Url.Content("</span>~/Scripts/jquery.signalR.min.js<span style="color: #006080;">")"</span> type=<span style="color: #006080;">"text/javascript"</span>></script></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <script type=<span style="color: #006080;">"text/javascript"</span> src=<span style="color: #006080;">"@Url.Content("</span>~/signalr/hubs<span style="color: #006080;">")"</span>></script></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <div id=<span style="color: #006080;">'container'</span>></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <div id=<span style="color: #006080;">'chat'</span>></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <b>Chatroom:</b></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <br /><br /></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <input type=<span style="color: #006080;">"text"</span> id=<span style="color: #006080;">"message"</span> maxlength=<span style="color: #006080;">"20"</span> /></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> <input type=<span style="color: #006080;">"button"</span> id=<span style="color: #006080;">"broadcast"</span> <span style="color: #0000ff;">value</span>=<span style="color: #006080;">"Broadcast"</span> /></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <input type=<span style="color: #006080;">"button"</span> id=<span style="color: #006080;">"clear"</span> <span style="color: #0000ff;">value</span>=<span style="color: #006080;">"Clear"</span> /></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <br /><br /></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <ul id=<span style="color: #006080;">"chatdialog"</span>></ul> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> </div></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <div id=<span style="color: #006080;">'map'</span>></div></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> </div></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> <div id=<span style="color: #006080;">"legend"</span>></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> <label <span style="color: #0000ff;">for</span>=<span style="color: #006080;">"userCount"</span>>Mapped Users: </label></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> <span id=<span style="color: #006080;">"userCount"</span>>0</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> </div></pre> <!--CRLF--></div> </div> <p>The Bing Maps on the page would be using the <a href="http://www.microsoft.com/maps/isdk/ajax/" target="_blank">Bing Maps Ajax/JavaScript SDK</a>. If you need to use this on your own, please make sure to get yourself a developer ID that you could pass along to Bing; get it <a href="http://www.microsoft.com/maps/developers/web.aspx" target="_blank">HERE</a>.</p> <p>Now, most of the connectivity magic offered by the SignalR server will be in the code bits below. You’ll see how we open a connection to our SignalR Hub from the web client and define JavaScript methods to manipulate the UI that will be used by the Hub. You’ll notice how we add/remove PushPins on the map using JavaScript & location of phone clients joining the Hub. Also, you’ll see the code sending off Chat messages typed in from the web and appending those received from the server. So, here goes:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <script type=<span style="color: #006080;">"text/javascript"</span>></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> var map = <span style="color: #0000ff;">null</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> $(function () </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #008000;">// Create the connection to our SignalR Hub.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> var signalRHub = $.connection.messagingHub;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #008000;">// Define some Javascript methods the server-side Hub can invoke.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #008000;">// Add a new client to the map.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> signalRHub.addClient = function (client) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> var pins = getPushPins();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> addClient(client);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> centerMap();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> $(<span style="color: #006080;">"#userCount"</span>).html(pins.length + 1)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> <span style="color: #008000;">// Remove a client from the map.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> signalRHub.removeClient = function (client) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">for</span> (var i = map.entities.getLength() - 1; i >= 0; i--) {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> var pushpin = map.entities.get(i);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> <span style="color: #0000ff;">if</span> (pushpin instanceof Microsoft.Maps.Pushpin) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> <span style="color: #0000ff;">if</span> (pushpin.getLocation().latitude == client.Latitude && pushpin.getLocation().longitude == client.Longitude) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span> map.entities.removeAt(i);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span> var pins = getPushPins();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum32" style="color: #606060;"> 32:</span> $(<span style="color: #006080;">"#userCount"</span>).html(pins.length)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum33" style="color: #606060;"> 33:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum34" style="color: #606060;"> 34:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum35" style="color: #606060;"> 35:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum36" style="color: #606060;"> 36:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum37" style="color: #606060;"> 37:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum38" style="color: #606060;"> 38:</span> <span style="color: #008000;">// Add chat messages from server to dialog.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum39" style="color: #606060;"> 39:</span> signalRHub.addChatMessage = function (message) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum40" style="color: #606060;"> 40:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum41" style="color: #606060;"> 41:</span> $(<span style="color: #006080;">'#chatdialog'</span>).append(<span style="color: #006080;">'<li>'</span> + message + <span style="color: #006080;">'</li>'</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum42" style="color: #606060;"> 42:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum43" style="color: #606060;"> 43:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum44" style="color: #606060;"> 44:</span> <span style="color: #008000;">// Click event-handler for broadcasting chat messages.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum45" style="color: #606060;"> 45:</span> $(<span style="color: #006080;">'#broadcast'</span>).click(function () </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum46" style="color: #606060;"> 46:</span> { </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum47" style="color: #606060;"> 47:</span> <span style="color: #008000;">// Call Server method.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum48" style="color: #606060;"> 48:</span> signalRHub.pushMessageToClients($(<span style="color: #006080;">'#message'</span>).val());</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum49" style="color: #606060;"> 49:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum50" style="color: #606060;"> 50:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum51" style="color: #606060;"> 51:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum52" style="color: #606060;"> 52:</span> <span style="color: #008000;">// Start the SignalR Hub.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum53" style="color: #606060;"> 53:</span> $.connection.hub.start(function () </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum54" style="color: #606060;"> 54:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum55" style="color: #606060;"> 55:</span> showMap();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum56" style="color: #606060;"> 56:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum57" style="color: #606060;"> 57:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum58" style="color: #606060;"> 58:</span> <span style="color: #008000;">// Click event-handler for clearing chat messages.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum59" style="color: #606060;"> 59:</span> $(<span style="color: #006080;">'#clear'</span>).click(function () </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum60" style="color: #606060;"> 60:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum61" style="color: #606060;"> 61:</span> $(<span style="color: #006080;">'ul li'</span>).remove();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum62" style="color: #606060;"> 62:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum63" style="color: #606060;"> 63:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum64" style="color: #606060;"> 64:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum65" style="color: #606060;"> 65:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum66" style="color: #606060;"> 66:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum67" style="color: #606060;"> 67:</span> function addClient(client) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum68" style="color: #606060;"> 68:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum69" style="color: #606060;"> 69:</span> var location = <span style="color: #0000ff;">new</span> Microsoft.Maps.Location(client.Latitude, client.Longitude);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum70" style="color: #606060;"> 70:</span> var pushpin = <span style="color: #0000ff;">new</span> Microsoft.Maps.Pushpin(location, { text: <span style="color: #006080;">'P'</span>});</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum71" style="color: #606060;"> 71:</span> map.entities.push(pushpin);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum72" style="color: #606060;"> 72:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum73" style="color: #606060;"> 73:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum74" style="color: #606060;"> 74:</span> function showMap() </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum75" style="color: #606060;"> 75:</span> { </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum76" style="color: #606060;"> 76:</span> var mapOptions = {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum77" style="color: #606060;"> 77:</span> credentials: <span style="color: #006080;">"AuoGTNP56_kmS3IKUa0E-p_PBX1oWJO6WTpw2xFd-hZqFsffSh3FhKGXhFHQD52y"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum78" style="color: #606060;"> 78:</span> center: <span style="color: #0000ff;">new</span> Microsoft.Maps.Location(39.80, -98.55),</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum79" style="color: #606060;"> 79:</span> zoom:5</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum80" style="color: #606060;"> 80:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum81" style="color: #606060;"> 81:</span> map = <span style="color: #0000ff;">new</span> Microsoft.Maps.Map(document.getElementById(<span style="color: #006080;">"map"</span>), mapOptions); </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum82" style="color: #606060;"> 82:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum83" style="color: #606060;"> 83:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum84" style="color: #606060;"> 84:</span> function centerMap() </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum85" style="color: #606060;"> 85:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum86" style="color: #606060;"> 86:</span> var pins = getPushPins();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum87" style="color: #606060;"> 87:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum88" style="color: #606060;"> 88:</span> var locations = []; </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum89" style="color: #606060;"> 89:</span> <span style="color: #0000ff;">for</span> (var i = pins.length-1; i>=0; i--) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum90" style="color: #606060;"> 90:</span> locations.push(pins[i].getLocation());</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum91" style="color: #606060;"> 91:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum92" style="color: #606060;"> 92:</span> map.setView({</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum93" style="color: #606060;"> 93:</span> bounds: Microsoft.Maps.LocationRect.fromLocations(locations),</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum94" style="color: #606060;"> 94:</span> zoom: 6</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum95" style="color: #606060;"> 95:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum96" style="color: #606060;"> 96:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum97" style="color: #606060;"> 97:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum98" style="color: #606060;"> 98:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum99" style="color: #606060;"> 99:</span> function getPushPins() </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum100" style="color: #606060;"> 100:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum101" style="color: #606060;"> 101:</span> var pins = [];</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum102" style="color: #606060;"> 102:</span> <span style="color: #0000ff;">for</span> (var i = map.entities.getLength() - 1; i >= 0; i--) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum103" style="color: #606060;"> 103:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum104" style="color: #606060;"> 104:</span> var pushpin = map.entities.get(i);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum105" style="color: #606060;"> 105:</span> <span style="color: #0000ff;">if</span> (pushpin instanceof Microsoft.Maps.Pushpin) </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum106" style="color: #606060;"> 106:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum107" style="color: #606060;"> 107:</span> pins.push(pushpin); </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum108" style="color: #606060;"> 108:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum109" style="color: #606060;"> 109:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum110" style="color: #606060;"> 110:</span> <span style="color: #0000ff;">return</span> pins;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum111" style="color: #606060;"> 111:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum112" style="color: #606060;"> 112:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum113" style="color: #606060;"> 113:</span> </script></pre> <!--CRLF--></div> </div> <h4> </h4> <h4> </h4> <h4>The Windows Phone Client</h4> <p>Now that we have the SignalR server all set up and waiting for interaction from phone clients, let us develop our Windows Phone client app. We’ll build a regular one page Windows Phone application just to demo functionality & connectivity to the SignalR Hub. Let’s begin by adding the appropriate SignalR nuget as below:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_18.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_7.png" width="604" height="404" /></a></p> <p>As we launch the app, we ask for a one-time user name so the phone client can be identified in the chatroom. For brevity, let us skip showing the simple XAML markup; you may find it in the downloadable code. Both UIs as below:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_20.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_8.png" width="254" height="484" /></a>  <a href="http://www.silverlightshow.net/Storage/Users/samidip/_image_22.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;border-style: solid;" title="image" alt="image" src="http://www.silverlightshow.net/Storage/Users/samidip/_image_thumb_9.png" width="254" height="484" /></a></p> <p>As the user indicates with button click that he/she wants to join, we use location awareness in Windows Phone to figure out current geo-coordinates of the user with a physical device or read mock emulator inputs. Here’s some code:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> GeoCoordinateWatcher gcw;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">double</span> phoneLatitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">double</span> phoneLongitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> connectButton_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">if</span> (gcw == <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #008000;">// Look for present geo-location with GPS.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> gcw = <span style="color: #0000ff;">new</span> GeoCoordinateWatcher(GeoPositionAccuracy.High);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> gcw.MovementThreshold = 10;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> gcw.StatusChanged += <span style="color: #0000ff;">new</span> EventHandler<GeoPositionStatusChangedEventArgs>(gcw_StatusChanged);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> gcw.Start(); </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> }</pre> <!--CRLF--></div> </div> <p>Once we have location, it’s time to fire up the reference to the SignalR server and try to connect. Here’s the sample code:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> IHubProxy SignalRServerHub;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> HubConnection connection = <span style="color: #0000ff;">new</span> HubConnection(<span style="color: #006080;">"http://localhost:49968/"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> gcw_StatusChanged(<span style="color: #0000ff;">object</span> sender, GeoPositionStatusChangedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">if</span> (e.Status == GeoPositionStatus.Ready)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #008000;">// Get position from watcher & stop it to conserve battery.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> phoneLatitude = gcw.Position.Location.Latitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> phoneLongitude = gcw.Position.Location.Longitude;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> gcw.Stop();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #008000;">// Reference to SignalR Server Hub & Proxy. </span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> var messagingHub = connection.CreateProxy(<span style="color: #006080;">"SignalRServer.MessagingHub"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> SignalRServerHub = messagingHub; </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> <span style="color: #008000;">// Fire up SignalR Connection & share location. </span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> connection.Start().ContinueWith(task =></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> <span style="color: #0000ff;">if</span> (task.IsFaulted)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #008000;">// Oopsie, do some error handling.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> <span style="color: #008000;">// Join the Server's list of mapped clients.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> messagingHub.Invoke(<span style="color: #006080;">"JoinFromPhone"</span>, deviceID, phoneLatitude, phoneLongitude).Wait();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> <span style="color: #008000;">// Tell the chatroom that you joined.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> SignalRServerHub.Invoke(<span style="color: #006080;">"PushMessageToClients"</span>, App.Current.userName + <span style="color: #006080;">" just joined!"</span>).Wait(); </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum32" style="color: #606060;"> 32:</span> }</pre> <!--CRLF--></div> </div> <p>Notice how we build a proxy on the fly (not tight-binding though) and invoke the “<em>JoinFromPhone()</em>” method of the server from the phone app, passing in some identifying information & location coordinates. The point is, you can pass in whatever your server needs. The unique qualifier that we pass in for every phone client to the server is the unique Device ID of the phone. Once pinged, the SignalR Hub wakes up, adds the incoming phone client to an internal collection (which you can persist) and reaches back to each web client (MVC3 view) to invoke some JavaScript functions that actually add a Pushpin on the map. Next up, we also announce on the Chatroom that a new user has joined the Hub by invoking the “<em>PushMessageToClients()</em>” server method. Simple enough, right?</p> <p>When the user types in some content and hits the Chat button, we got to let the SignalR server know, so that the chat message gets posted on the web front-end & all connected Windows Phone clients. Here’s how we achieve that .. notice that we are making some of these server calls on background threads so as to not hose up our UI:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> chatButton_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">if</span> (chatTextbox.Text != <span style="color: #0000ff;">string</span>.Empty && chatTextbox.Text != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #008000;">// Fire off background thread to post message to server Chatroom.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> chatMessage = chatTextbox.Text.Trim();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> chatTextbox.Text = <span style="color: #0000ff;">string</span>.Empty;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> ChatBackgroundDataWorker.RunWorkerAsync();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> ChatBackgroundDataWorker_DoWork(<span style="color: #0000ff;">object</span> sender, DoWorkEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #008000;">// Post message to server chatroom.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> SignalRServerHub.Invoke(<span style="color: #006080;">"PushMessageToClients"</span>, chatMessage).Wait();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> chatMessage = <span style="color: #0000ff;">string</span>.Empty;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> }</pre> <!--CRLF--></div> </div> <p>Now, this takes care of the chat message posting part where the server informs all other clients. However, if someone posts a chat message from the web front-end or other phone clients, how does our app know to update the chat dialog with content? There has to be a trigger, right? Unlike JavaScript clients which the SignalR server can directly reach out to in case something of interest happens, there isn’t an easy proposition for .NET clients since we do not have a reference. But, we do have a persistent connection and there is an “<em>On</em>” method on the connection that can be rigged up to fire anytime a certain event happens on the server. Let us do that any time the server posts a message to all clients. Here’s the code .. you’ll be surprised how instantaneously this mechanism posts the chat message to all connected Windows Phone clients:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #008000;">// Listen in on when Server posts anything to Chatroom.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> SignalRServerHub.On<<span style="color: #0000ff;">string</span>>(<span style="color: #006080;">"addChatMessage"</span>, message =></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #008000;">// Add to local ChatRoom.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> chatDialog.Text += <span style="color: #006080;">"\r\n"</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> chatDialog.Text += message.Trim();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> });</pre> <!--CRLF--></div> </div> <p>Now, when you are done chit-chatting with your fellow geeks, you would like to disconnect officially and take your Pushpin out, right? Let’s add this code to disconnect, so that the corresponding Disconnect method is fired on the server. Again, notice how we do this on the background thread and officially sign out of the chatroom:</p> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> disconnectButton_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> { </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> DisconnectBackgroundDataWorker.RunWorkerAsync();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> chatTextbox.IsEnabled = <span style="color: #0000ff;">false</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> chatButton.IsEnabled = <span style="color: #0000ff;">false</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> disconnectButton.IsEnabled = <span style="color: #0000ff;">false</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> connectButton.IsEnabled = <span style="color: #0000ff;">true</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> DisconnectBackgroundDataWorker_DoWork(<span style="color: #0000ff;">object</span> sender, DoWorkEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #008000;">// Send Farewell to Chatroom.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> SignalRServerHub.Invoke(<span style="color: #006080;">"PushMessageToClients"</span>, App.Current.userName + <span style="color: #006080;">" just left!"</span>).Wait();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #008000;">// Disconnect from Hub.</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> SignalRServerHub.Invoke(<span style="color: #006080;">"Disconnect"</span>, deviceID).Wait();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> }</pre> <!--CRLF--></div> </div> <h4> </h4> <h4>Conclusion</h4> <p>That’s it. A functional Windows Phone client that connects to a SignalR server backend and allows us to see the interactions on a web front-end. The SignalR magic simply provides the persistent connectivity through whatever transport means feasible. Now, could there be potential benefit in leveraging such technology in our Windows Phone apps? Think, think ...</p> <h4> </h4> <h4>About the Author</h4> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/_ActualPic_5.jpg"><img style="background-image: none; margin-top: 0px; margin-right: 15px; margin-bottom: 0px; margin-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; float: left; border-width: 0px;border-style: solid;" title="ActualPic" alt="ActualPic" src="http://www.silverlightshow.net/Storage/Users/samidip/_ActualPic_thumb_4.jpg" width="154" height="188" /></a></p> <p>Samidip Basu (<a href="https://twitter.com/#!/samidip">@samidip</a>) is a technologist & gadget-lover working as a Manager & Solutions Lead for Sogeti USA out of the Columbus Unit. With a strong developer background in Microsoft technology stack, he now spends much of his time in spreading the word to discover the full potential of the Windows Phone platform & cloud-backed mobile solutions in general. He passionately runs the Central Ohio Windows Phone User Group (<a href="http://cowpug.org/">http://cowpug.org</a>), labors in M3 Conf (<a href="http://m3conf.com/">http://m3conf.com/</a>) organization and can be found with at-least a couple of hobbyist projects at any time. His spare times call for travel and culinary adventures with the wife. Find out more at <a href="http://samidipbasu.com/">http://samidipbasu.com</a>.</p> http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx editorial@silverlightshow.net (Samidip Basu ) http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-SignalR-Awesome-Possibilities.aspx Mon, 27 Feb 2012 04:29:00 GMT Windows Phone 7.5: Using sockets <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx" data-count="horizontal" data-text="Reading the article 'Windows Phone 7.5 -Using sockets' by @aboschin #wpdev #windowsphone" data-url="http://slshow.net/whB4Pk">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p style="text-align: justify;">Also if the technical specifications of Windows Phone 7.0 stated that it is compatible with Silverlight 3.0, this only means that every feature you can use in the phone is available on the desktop but not viceversa. Sockets are a clear demonstration of this sentence. While they are perfectly available on Silverlight 3.0, they are locked down in the phone for the, so called, "security purposes". Curiously if you watch at the codebase of Silverlight for Windows Phone 7.0 you see that, the Socket class exists but it is declared "internal". </p> <div style="border:1px solid #dddddd;width: 200px; padding-top: 5px; padding-bottom: 5px; padding-left: 10px; margin-top: 5px; margin-left: 10px; float: right; background-color: #f3f3f3; border-image: initial;"> <h3>Don't miss...</h3> <ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 20px; font-size: 12px; list-style-type: circle;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/items/Data-Access-Strategies-WebClient.aspx">The article series 'WP7 Data Access Strategies'</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Webinar-Azure-for-WP7-Devs.aspx"><strong>Recording of the webinar</strong>: Azure for the Windows Phone Developer</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx">The ebook 'Getting Ready for the Windows Phone Exam 70-599':</a> </li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"><img style="border:0px solid; width: 100px; height: 141px; border-image: initial;" alt="Getting Ready for the Windows Phone Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/wp7_exam_cover.png" /><br /> <strong><span style="font-size: 13px;">($4.99)</span></strong></a></p> <a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"></a> <p style="font-size: 12px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> <p style="text-align: justify;">The new OS 7.5 have made Sockets available to developers, opening the way to a wide series of applications that uses this low-level communication way. Sockets are for sure difficult from the programming side, but they offer a connected/disconnected, fast and reliable way of exchange data that is unreplaceable for many purposes.</p> <h4 style="text-align: justify;">What sockets can do (and what they can't)</h4> <p style="text-align: justify;">Sockets are something that we use every day. Also if we are not aware of this, they are at the very base of each network protocol, comprised HTTP, SMTP, PO3, and so on. Their purpose is to create a communication channel between two boundaries where they can send and receive something that usually is a binary message. There are two ways to create a Socket connection. The TCP and the UDP. Since TCP is an always connected protocol that is tailored to exchange continuous streams, UDP is mostly made to exchange fast and short packets of information - called datagrams - while the boundaries aren't continuously connected. To make a practical example, HTTP is based on the TCP protocol where the client and the server establish a connected channel and they both send and receive on this channel until the communication ends. On the other side, DNS is mostly UDP based because the client sends a request datagram and the server answers with another datagram but there is not a real channel established between the two boundaries. Do not underestimate UDP since it is often very effective. Infact a number of streaming protocols are based on it.</p> <p style="text-align: justify;">While Silverlight only supports TCP, Windows Phone 7.5 also supports UDP Sockets. I'm always really amazed about the confusion of team's choices, but to me it is really not understandable the reason that leads to diverge the sockets capabilities in this matter. But so it is. So, while in Silverlight for desktop we can only use TCP and a limited set of ports, if application is not fully trusted, with Windows Phone 7.5 we have the very full set of knifes to work with.</p> <p style="text-align: justify;">No matter you are using a TCP or UDP connection, a communication is ruled by the same process and by the same structures. Once you have choose the endpoint to connect to, in terms of ip address and port, the process of communications is the following:</p> <ol> <li> <div style="text-align: justify;">Create the Socket class</div> </li> <li> <div style="text-align: justify;">Connect the socket</div> </li> <li> <div style="text-align: justify;">Send and receive data</div> </li> <li> <div style="text-align: justify;">Shutdown the connection</div> </li> </ol> <p style="text-align: justify;">The correct sequence of operations at point 3 is determined by the network protocol you are implementing. As an example if you are placing an HTTP call, first of all you send the request and the receive the response, but there are many cases where you can simply start to receive a continuous stream because the protocol continuously broadcast packets.</p> <p style="text-align: justify;">All the phases of the socket connection are ruled by at least an instance of SockerAsyncEventArgs. This class contains the reference to the remote endpoint, the operation in progress/completed, the data that is sent to or received by the peer. In a simple connection you will have only a single instance but, for performance purposes (e.g. in a multithreaded environment), you can have a pool of instances to use for the various operations. </p> <h4 style="text-align: justify;">Implementing a simple UDP protocol (NTP)</h4> <p style="text-align: justify;">For the sake of the article I will show now how to implement a simple protocol. The NTP protocol I will show, is very basic, just because I do not want to spend most of the time explaining the protocol itself. NTP stands for Network Time Protocol and despite the very simple datagram you have to exchange over an UDP socket, the RFC is really complex because of the server implementation that have to ensure redundancy and precision across multiple sources.</p> <p style="text-align: justify;">To make an NTP request you have to do the following:</p> <ol> <li> <div style="text-align: justify;">Connect to a NTP server on port 123</div> </li> <li> <div style="text-align: justify;">Prepare a datagram of 48 zeroed bytes with the first byte set to 0x1b</div> </li> <li> <div style="text-align: justify;">Send the datagram over UDP</div> </li> <li> <div style="text-align: justify;">Receive the same datagram filled with time information</div> </li> <li> <div style="text-align: justify;">Close the socket</div> </li> <li> <div style="text-align: justify;">Decode and use the result</div> </li> </ol> <p style="text-align: justify;">The returned bytes represents a DateTime and I do not enter in the format of the response. If you are interested simply watch at the decoding method in my example. The first thing to do is to create a NtpClient class. This class will represent a single server and is initialized with the remote endpoint:</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> NtpClient</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">private</span> Socket Socket { get; set; }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">private</span> SocketAsyncEventArgs Args { get; set; }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">public</span> NtpClient(EndPoint endPoint)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum7" style="color: #606060;"> 7:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">this</span>.Args = <span style="color: #0000ff;">new</span> SocketAsyncEventArgs</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum9" style="color: #606060;"> 9:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum10" style="color: #606060;"> 10:</span> RemoteEndPoint = endPoint</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum11" style="color: #606060;"> 11:</span> };</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum12" style="color: #606060;"> 12:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #0000ff;">this</span>.Args.Completed += <span style="color: #0000ff;">new</span> EventHandler<SocketAsyncEventArgs>(Operation_Completed);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum14" style="color: #606060;"> 14:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum15" style="color: #606060;"> 15:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Operation_Completed(<span style="color: #0000ff;">object</span> sender, SocketAsyncEventArgs e)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum17" style="color: #606060;"> 17:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum18" style="color: #606060;"> 18:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum19" style="color: #606060;"> 19:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">In this first part I create an instance of the SocketAsyncEventArgs and initialize it with the RemoteEndPoint. This instance is shared by all the network calls so it is defined as a private member property. The code also attach the Completed event of this instance. Every time I will perform an action on the socket, using this instance, the Completed event is raised and the LastOperation property will be set with a value representing the action I did.</p> <p style="text-align: justify;">The GetNetworkTimeAsync method initializes the Socket class and initiates the connection. Under the hoods, the meaning of "ConnectAsync" is different between TCP and UDP but it has to be made for both the protocols. Here I am using an UDP connection so the values in the ctor indicate ProtocolType.Udp and a SocketType.Dgram. If I would use a TCP channel I should use SocketType.Stream and ProtocolType.Tcp.</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> GetNetworkTimeAsync()</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">this</span>.Socket = <span style="color: #0000ff;">new</span> Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">this</span>.Socket.ConnectAsync(<span style="color: #0000ff;">this</span>.Args);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">From this point, the lifetime of the class is governed by the Operation_Completed event. Every time I perform an action this method collects the result. So when I call connect the method receives the result, but the same happen when I call SendAsync and ReveiceAsync. Inside the Operation_Completed I create a chain of operation, always calling the following action as the result of another.</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Operation_Completed(<span style="color: #0000ff;">object</span> sender, SocketAsyncEventArgs e)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">if</span> (e.SocketError == SocketError.Success)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">switch</span> (e.LastOperation)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">case</span> SocketAsyncOperation.Connect:</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">this</span>.SendRequest();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;">break</span>;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">case</span> SocketAsyncOperation.Send:</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum11" style="color: #606060;"> 11:</span> <span style="color: #0000ff;">this</span>.ReceiveResponse();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">break</span>;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #0000ff;">case</span> SocketAsyncOperation.Receive:</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;">this</span>.ReadAndClose();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">break</span>;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum16" style="color: #606060;"> 16:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum17" style="color: #606060;"> 17:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum19" style="color: #606060;"> 19:</span> <span style="color: #0000ff;">this</span>.OnError(e.SocketError);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum20" style="color: #606060;"> 20:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;"> </p> <p style="text-align: justify;">The chain indicates that following the Connect I call SendRequest then ReceiveResponse and finally ReadAndClose. These decisions are wrapped from an if construct that handles the socket errors. Only when e.SocketError equals Success the chain continues. The SendRequest method creates the datagram and sends it over the channel:</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> SendRequest()</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">byte</span>[] ntpData = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span>[48];</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span> Array.Clear(ntpData, 0, ntpData.Length);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span> ntpData[0] = 0x1b;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">this</span>.Args.SetBuffer(ntpData, 0, ntpData.Length);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">this</span>.Socket.SendAsync(<span style="color: #0000ff;">this</span>.Args);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">As you can see the 48 bytes array is cleared and the first byte is set to 0x1b then the entire buffer is assigned to the SocketAsyncEventArgs using the SetBuffer method. Finally it is passed to the SendAsync method so it is sent to the connected peer. The ReceiveResponse method instead, does not change the SocketAsyncEventArgs but simply calls the ReceiveAsyncMethod. The purpose of this method is not receiving bytes but putting the socket in receive mode so when a packet arrives it is received.</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> ReceiveResponse()</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">this</span>.Socket.ReceiveAsync(<span style="color: #0000ff;">this</span>.Args);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;"> </p> <p style="text-align: justify;">When the packet arrives, it is written inside the buffer prepared into the SocketAsyncEventArgs and I receive this data in the Operation_Completed method when LastOperation is Receive. This meand that between ReadAsync and Operation_Completed it may pass a long time depending on how fast is the answer from the server. </p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> ReadAndClose()</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">byte</span>[] ntpData = <span style="color: #0000ff;">this</span>.Args.Buffer;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">byte</span> offsetTransmitTime = 40;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">ulong</span> intpart = 0;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">ulong</span> fractpart = 0;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum8" style="color: #606060;"> 8:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i <= 3; i++)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum10" style="color: #606060;"> 10:</span> intpart = 256 * intpart + ntpData[offsetTransmitTime + i];</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 4; i <= 7; i++)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum13" style="color: #606060;"> 13:</span> fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum14" style="color: #606060;"> 14:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">ulong</span> milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum16" style="color: #606060;"> 16:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum17" style="color: #606060;"> 17:</span> TimeSpan timeSpan = TimeSpan.FromTicks((<span style="color: #0000ff;">long</span>)milliseconds * TimeSpan.TicksPerMillisecond);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum18" style="color: #606060;"> 18:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum19" style="color: #606060;"> 19:</span> DateTime dateTime = <span style="color: #0000ff;">new</span> DateTime(1900, 1, 1);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum20" style="color: #606060;"> 20:</span> dateTime += timeSpan;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum21" style="color: #606060;"> 21:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum22" style="color: #606060;"> 22:</span> DateTime networkDateTime = dateTime.ToLocalTime();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum23" style="color: #606060;"> 23:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">this</span>.OnCompleted(networkDateTime);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum25" style="color: #606060;"> 25:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum26" style="color: #606060;"> 26:</span> <span style="color: #0000ff;">this</span>.Socket.Shutdown(SocketShutdown.Both);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum27" style="color: #606060;"> 27:</span> <span style="color: #0000ff;">this</span>.Socket.Close();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum28" style="color: #606060;"> 28:</span> <span style="color: #0000ff;">this</span>.Socket = <span style="color: #0000ff;">null</span>;</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum29" style="color: #606060;"> 29:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;"> </p> <p style="text-align: justify;">The ReadAndClose method receive the buffer and decode its content according with the NTP protocol specifications. Finally it calls ShutDown and Close to terminate the connection. After this the Socket instance is cleared because on the next request I have to create it again. </p> <h4 style="text-align: justify;">Using the NtpClient</h4> <p style="text-align: justify;">Once the NtpClient class has been created it is time to use it in a Windows Phone application. Using this class is straightforward. You create the client instance and then call the GetNetworkTimeAsync every time you need to request the datetime. The class exposes two events Completed and Error that are raised accordin with the result of the request:</p> <div style="text-align: justify;"> <div id="codeSnippetWrapper" style="border:1px solid silver;margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; border-image: initial; width: 97.5%; line-height: 12pt; overflow-x: auto; overflow-y: auto; font-family: 'courier new', courier, monospace; font-size: 8pt; cursor: text; direction: ltr; max-height: 200px; background-color: #f4f4f4; text-align: left;"> <div id="codeSnippet" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4; text-align: left;"> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> MainPage : PhoneApplicationPage</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">public</span> NtpClient Client { get; set; }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">public</span> MainPage()</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum7" style="color: #606060;"> 7:</span> InitializeComponent();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum8" style="color: #606060;"> 8:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;">this</span>.Client = <span style="color: #0000ff;">new</span> NtpClient(<span style="color: #0000ff;">new</span> DnsEndPoint(<span style="color: #006080;">"0.pool.ntp.org"</span>, 123));</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">this</span>.Client.Completed += <span style="color: #0000ff;">new</span> EventHandler<NtpQueryCompletedEventArgs>(Client_Completed);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum11" style="color: #606060;"> 11:</span> <span style="color: #0000ff;">this</span>.Client.Error += <span style="color: #0000ff;">new</span> EventHandler<NtpQueryErrorEventArgs>(Client_Error);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum12" style="color: #606060;"> 12:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum13" style="color: #606060;"> 13:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Button_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum15" style="color: #606060;"> 15:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;">this</span>.Client.GetNetworkTimeAsync();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum17" style="color: #606060;"> 17:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum18" style="color: #606060;"> 18:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum19" style="color: #606060;"> 19:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Client_Completed(<span style="color: #0000ff;">object</span> sender, NtpQueryCompletedEventArgs e)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum20" style="color: #606060;"> 20:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum21" style="color: #606060;"> 21:</span> <span style="color: #0000ff;">this</span>.Result.Text = e.Result.ToString(CultureInfo.CurrentCulture);</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum22" style="color: #606060;"> 22:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum23" style="color: #606060;"> 23:</span>  </pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Client_Error(<span style="color: #0000ff;">object</span> sender, NtpQueryErrorEventArgs e)</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum25" style="color: #606060;"> 25:</span> {</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum26" style="color: #606060;"> 26:</span> <span style="color: #0000ff;">this</span>.Result.Text = e.Error.ToString();</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: white;"><span id="lnum27" style="color: #606060;"> 27:</span> }</pre> <!--CRLF--> <pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow-x: visible; overflow-y: visible; font-family: 'courier new', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span id="lnum28" style="color: #606060;"> 28:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;"> </p> <p style="text-align: justify;">The NtpClient class does not gracefully handles a double connection request but simply throw away the preceding destroying the socket before creating another one. This is for sure an improvement you can do by yourself. </p> <p style="text-align: justify;">The socket are a great opportunity for doing beautiful applications. An example of the power of sockets is my <a href="http://www.xamlplayground.org/post/2011/11/18/Silver-VNC-10-for-Windows-Phone-Mango.aspx" target="_blank">Silver VNC Client for Windows Phone</a> that is available on marketplace The VNC client uses a TCP channel to connect to a VNC server and remotely view the desktop of a computer. I hope you enjoy the free edition.</p> <p style="text-align: justify;"><a href="http://www.silverlightshow.net/Storage/Sources/XPG.NTP.zip"><strong>Download the source code</strong></a></p> <p style="text-align: justify;"> </p> http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx editorial@silverlightshow.net (Andrea Boschin ) http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-sockets.aspx Mon, 16 Jan 2012 17:10:00 GMT Windows Phone 7.5 - Using advanced tiles API <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx" data-count="horizontal" data-text="Reading the article 'Windows Phone 7.5 - Using advanced tiles API' by @aboschin #wpdev" data-url="http://slshow.net/zYx7bj">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <p style="text-align: justify;">There is not any doubt, the first thing you meet when you use Windows Phone are the tiles. These are the large squares on the home screen that identifies some applications and they are also a distinguishable character that make your Windows Phone unique. </p> <div style="border:1px solid #dddddd;border-image: initial; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; padding-top: 5px;"> <h3>Don't miss...</h3> <ul style="list-style-type: circle; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/items/Data-Access-Strategies-WebClient.aspx">The article series 'WP7 Data Access Strategies'</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Webinar-Azure-for-WP7-Devs.aspx"><strong>Recording of the webinar</strong>: Azure for the Windows Phone Developer</a></li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx">The ebook 'Getting Ready for the Windows Phone Exam 70-599':</a> </li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"><img style="border:0px solid; border-image: initial; width: 100px; height: 141px;" alt="Getting Ready for the Windows Phone Exam 70-599" src="http://www.silverlightshow.net/Storage/Ebooks/wp7_exam_cover.png" /><br /> <strong><span style="font-size: 13px;">($4.99)</span></strong></a></p> <a href="http://www.silverlightshow.net/ebooks/wp7_exam.aspx"></a> <p style="font-size: 12px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div> As you know for sure, the tiles can be attached or detached from the home screen and some particular software can take advantage of double size tiles. While this is not a feature available to developers, in OS7.5, the tiles gained new features and a new set of APIs that you can use to enrich your applications. As an example you are now able to update your tiles from inside the application and you can use double faced tiles to improve information to the user. In this article I would like to explore these new features and show how to take advantage of them, while porting your software to the new operating system. <h4 style="text-align: justify;">Accessing and changing your tile(s)</h4> <p style="text-align: justify;">Once your application is running the user can have pinned its tile on the home screen. If this happened, you can have access to a bunch of tile's properties you can change at every time while the application is running, but please take note that it implies that the tile exists. Obviously, none of these APIs can work if your application is not pinned.</p> <p style="text-align: justify;">The root of your work is the ShellTile class that gives you access to a collection of ActiveTiles. At the very first place in this collection there is a structure that represents the main tile of your application. Reading the previous paragraph, you can expect this collection is empty when you application has not been pinned, but it is not true. The collection always contains at least one element, and you can update it every time also if the application's tile is not in the home screen. This does not cause a visible change but if the user choose to pin the application at a later time its tile will reflect these changes. The ShellTile class returned by this collection contains an "Update" method that is useful to change the tile's content:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> StandardTileData data = <span style="color: #0000ff;">new</span> StandardTileData</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> Title = <span style="color: #006080;">"My tile!"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> Count = 10,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> BackgroundImage = <span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"/Background.png"</span>, UriKind.RelativeOrAbsolute),</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> BackTitle = <span style="color: #006080;">"This is the back"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> BackContent = <span style="color: #006080;">"Hallo!"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> BackBackgroundImage = <span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"/Background.png"</span>, UriKind.RelativeOrAbsolute)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> ShellTile.ActiveTiles.First().Update(data);</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The properties of the StandardTileData class reflect the parts of the tile and are divided in two categories: Front and Back. So, we have a "Title" property that reflects the title of the tile on the front side and the "BackTitle" that has the same meaning for the back side. This led to the consideration that in OS 7.5, tiles can have two sides available. It suffice you set the value of one of the "Back" properties and the tile automatically activates the back side on a random schedule. </p> <p style="text-align: justify;"><a href="http://www.silverlightshow.net/Storage/Users/AndreaBoschin/______Capture.png"><img style="margin-top: 0px; margin-right: 17px; margin-bottom: 0px; margin-left: 0px; display: inline; float: left;" title="Capture" alt="Capture" src="http://www.silverlightshow.net/Storage/Users/AndreaBoschin/_____Capture_thumb.png" width="139" height="140" /></a></p> <p style="text-align: justify;">Tiles have also a background image, usually of the size of 173x173 pixels, that fills the entire square. The image must reside in the project as a resource and we can refer to it with a relative uri that starts at the root of the project. So "/Background.png" refers to the standard image, usually created by visual studio in the default project. Of course you can set different images for each side of the tile.</p> <p style="text-align: justify;">If you generate images on the fly, while the application is running, you can also use isolated storage to peek up images to show in the tiles. For this purpose you have to generate images in the standard path "/Shared/ShellContent", and then use the "isostore:" prefix when you refer to it in the tile's uri. Here is an extended example that shows this tecnique with a generated background image. The image contains a simple gradient as shown on the left side.</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> TilePath = <span style="color: #006080;">"/Shared/ShellContent/tile.jpg"</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">void</span> MainPage_Loaded(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> WriteableBitmap bmap = <span style="color: #0000ff;">new</span> WriteableBitmap(173, 173);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">byte</span> x = 0; x < 173; x++)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">byte</span> y = 0; y < 173; y++)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> bmap.Pixels[y * 173 + x] = (0xff << 24) | (x << 16) | y;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> <span style="color: #0000ff;">using</span> (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> <span style="color: #0000ff;">if</span> (file.FileExists(TilePath))</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> file.DeleteFile(TilePath);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;">using</span> (IsolatedStorageFileStream stream = file.CreateFile(TilePath))</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> bmap.SaveJpeg(stream, 173, 173, 0, 100);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> bCheckTiles_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> StandardTileData data = <span style="color: #0000ff;">new</span> StandardTileData</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> Title = <span style="color: #006080;">"andrea"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> Count = 10,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> BackTitle = <span style="color: #006080;">"This is the back"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> BackContent = <span style="color: #006080;">"Hallo!"</span>,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> BackBackgroundImage = <span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"isostore:/Shared/ShellContent/tile.jpg"</span>, UriKind.RelativeOrAbsolute)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum32" style="color: #606060;"> 32:</span> ShellTile.ActiveTiles.First().Update(data);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum33" style="color: #606060;"> 33:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">Finally you probably noticed an asimmetry in front and back properties. While front properties have a "Count" value, the background can specify a "BackContent". The "Count" property is made to specify a number to show on the right-top corner. This may be useful to applications that can check for email messages and so on. The BackContent instead, is used to fill the main content of the tile background. The tile figure on the left side show the word "Hallo!" in the place where content is displayed.</p> <h4 style="text-align: justify;">Schedule tile updates</h4> <p style="text-align: justify;">Once you configured your application's tile, your next need is probably to change the tile's content to notify the user about a service you are monitoring. This usually means use a time-based schedule that is able to check on a server if there is something to notify. Since OS 7.0, Windows Phone has a ShellTileSchedule. It was very limited because you was only able to update the background image, using a remote Uri to call on a scheduled basis. In OS 7.5 this has not changed a lot. The only thing we get added is the capability of also update secondary tiles (I will speak about secondary tiles in a few). You can connect the ShellTileSchedule to an arbitrary tile using the ActiveTiles collections as shown here:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> ShellTileSchedule schedule = <span style="color: #0000ff;">new</span> ShellTileSchedule(ShellTile.ActiveTiles.First())</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> Interval = UpdateInterval.EveryHour, </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> MaxUpdateCount = 0, </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> Recurrence = UpdateRecurrence.Interval, </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> StartTime = DateTime.Now,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> RemoteImageUri = <span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"http://xamlplayground.org/wp7updates/tile.jpg"</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> schedule.Start();</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">The ShellTileSchedule constructor accept a reference to a ShellTile in the collection so you can schedule multiple updates, one for each tile of your application. </p> <p style="text-align: justify;">As I shown in the example of the <a href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Use-Background-agents.aspx" target="_blank">previous article</a> about background agents, Windows Phone 7.5 gives an additional opportunity to schedule tile updates. You are able to use a ScheduledAgent and from inside the agent you are able to access the ActiveTiles collection and update almost every property you think useful to notify the user, with the sole limitation of a fixed schedule of 30 minutes. In the Panoramio example I showed how to access GPS position and retrieve a random image from Panoramio to update the application tile with a local image. Please check out the <a href="http://www.silverlightshow.net/items/Windows-Phone-7.5-Use-Background-agents.aspx" target="_blank">previous article</a> for a detailed explanation.</p> <h4 style="text-align: justify;">Using secondary tiles</h4> <p style="text-align: justify;">A great new opportunity with Windows Phone 7.5, is the ability of configure more than a tile, to pin to the home screen. These tiles can work as shortcuts for services exposed by your applications. To make a practical example, you can think at secondary tiles to expose different locations for a weather channel or to have a shortcut to airplanes flights and so on. The sole limit is your fantasy. </p> <p style="text-align: justify;">A secondary tile is simply created using the static Create method only on user input. This means your application cannot create tiles automatically, but only when the user explicitly ask it, interacting with the application interface. To create the tile you have to fill a StandardTileData class and pass it to the method. As a result the application exits and the user is brought to the tile position in the home screen. This also means that you can only create a secondary tile for each session because, the process close the application every time. Here is the code to create the tile:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> PinToStart(<span style="color: #0000ff;">string</span> address)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> Server server = Repository.GetServer(address);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">if</span> (server != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault(</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> t => t.NavigationUri.ToString().EndsWith(<span style="color: #006080;">"server="</span> + address));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">if</span> (tile == <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">string</span> destFileName = CopyImageToShellContent(address);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> StandardTileData newTile = <span style="color: #0000ff;">new</span> StandardTileData</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> Title = server.Name,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> Count = 0,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> BackgroundImage = <span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"Background.png"</span>, UriKind.Relative),</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> BackTitle = server.Name,</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> BackBackgroundImage = <span style="color: #0000ff;">new</span> Uri(destFileName, UriKind.Absolute),</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> BackContent = AppStrings.Title</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> };</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> ShellTile.Create(<span style="color: #0000ff;">new</span> Uri(<span style="color: #006080;">"/Pages/VNCPanorama.xaml?server="</span> + address, UriKind.Relative), newTile);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">This sample, taken directly from the next release of my <a href="http://www.xamlplayground.org/post/2011/11/18/Silver-VNC-10-for-Windows-Phone-Mango.aspx" target="_blank">Silver VNC client for Windows Phone 7</a>, shows how to create the tile. The important thing to note is the uri you have to pass to the Create method. This uri (called NavigationUri) is the one called when the user hits the pinned tile. It indicates the page inside your application that will be used as landing page for the request and can have multiple query string parameters to let the application decide how to answer to the request. Thanks to these parameters you can have multiple tiles that connect to the application with different actions. Inside the page that receive the user request you can parse the query string to evaluate the action to perform:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">void</span> OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">this</span>.txtName.Text = <span style="color: #0000ff;">string</span>.Empty;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">this</span>.txtAddress.Text = <span style="color: #0000ff;">string</span>.Empty;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">this</span>.Load();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> <span style="color: #0000ff;">this</span>.EvaluateFromPinnedTile(e);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">base</span>.OnNavigatedTo(e);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> EvaluateFromPinnedTile(NavigationEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">if</span> (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> Match match = Regex.Match(e.Uri.ToString(), <span style="color: #006080;">".*?server=(?<address>.*)"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> <span style="color: #0000ff;">if</span> (match.Success)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;">string</span> address = match.Groups[<span style="color: #006080;">"address"</span>].Value;</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> Server server = Repository.GetServer(address);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #0000ff;">if</span> (server != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> <span style="color: #0000ff;">this</span>.Connect(server);</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> MessageBox.Show(<span style="color: #0000ff;">string</span>.Format(AppStrings.Message_UnknownServer, address));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">Into the OnNavigated method I call the EvaluateFromPinnedTile method that is responsible to check if the navigation occur because the user hit the pinned tile. In the method I check the NavigationMode property, that is always set to "New" when it is raised from a secondary tile and the use a regular expression to effectively check the incoming uri and retrieve the address. If the call is validated then I retrieve the Server information, from the local database, and then I call the Connect method to start the VNC connection. </p> <p style="text-align: justify;">To be double sure to not have exceptions I also check that the server exists on the database. Also if I delete the tile when the server is deleted from the database, this check is more defensive. Here is the deletion code:</p> <div style="text-align: justify;"> <div style="border:1px solid silver;border-image: initial; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin-top: 20px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow-x: auto; overflow-y: auto; cursor: text; padding-top: 4px; text-align: left;" id="codeSnippetWrapper"> <div style="padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px; text-align: left;border-style: none;" id="codeSnippet"> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> TryUnpinFromStart(<span style="color: #0000ff;">string</span> address)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault(t => t.NavigationUri.ToString().EndsWith(<span style="color: #006080;">"server="</span> + address));</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> <span style="color: #0000ff;">if</span> (tile != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> tile.Delete();</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow-x: visible; overflow-y: visible; padding-top: 0px;border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> }</pre> <!--CRLF--></div> </div> </div> <p style="text-align: justify;">While programming secondary tiles, you must be cautious because the user can always remove the pinned tile from the home screen, without the application get any warn about it. So please always be careful about what you get and always try to be in sync between secondary tiles and application data.</p> <h4 style="text-align: justify;">Tile your apps.</h4> <p style="text-align: justify;">Tiles are probably the most distinctive feature you have in Windows Phone 7. As it happen for every hard decision you can only love or hate them. I meet lot of people that take tiles as an example of the wrong of the Windows Phone and lot of other people that think in the opposite way. My think is that for common people tiles are a great opportunity of access all the capabilities of the phone without have to deal with complicated interfaces. Only hit and pin, is the only thing you need. From the developer side, use tiles correctly gives you an additional gear to make you applications more flexible and effective. However, my think is that tiles are great; given I love the simplicity, they are one of the best features of my favorite phone.</p> http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx editorial@silverlightshow.net (Andrea Boschin ) http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx#comments http://www.silverlightshow.net/items/Windows-Phone-7.5-Using-advanced-tiles-API.aspx Mon, 09 Jan 2012 15:43:00 GMT Book Review: Windows Phone 7 Silverlight Cookbook <p><em>This review is for the book </em><em><a href="http://www.silverlightshow.net/book/Windows-Phone-7-Silverlight-Cookbook.aspx">'Windows Phone 7 Silverlight Cookbook'</a></em><em>, and has been submitted by a member of the </em><a href="http://wpug.net/" target="_blank"><em>Windows Phone 7 User Group</em></a><em> - a user group supported by SilverlightShow.</em></p> <p><em>We </em><a href="http://www.silverlightshow.net/About/Partners.aspx" target="_self"><em>support user groups</em></a><em> with books, swag, events promotion, free event passes and others. </em><a href="http://www.silverlightshow.net/About/contacts.aspx" target="_self"><em>Contact us to get support for your user group</em></a><em>. <br /> </em></p> <p><strong> Interested in this book? Get it for free</strong> by tweeting our next webinar <a href="http://www.silverlightshow.net/news/Free-SilverlightShow-Webinar-Leveraging-Windows-Azure-for-the-Windows-Phone-Developer.aspx" target="_self"><strong>Leveraging Windows Azure for the Windows Phone Developer</strong></a> using tag <strong>#webinarsilverlightshow</strong>. Three of you will get a free ebook copy provided by <a href="http://www.packtpub.com/" target="_blank">Packt Publishing</a>. <strong><a href="http://twitter.com/home?status=Free+%40SilverlightShow+webinar%3A+Leveraging+Azure+for+Windows+Phone%3A+http%3A%2F%2Fslshow.net%2Fvv6hvN+%23webinarsilverlightshow+%23WPdev" target="_blank">Tweet this webinar now!</a></strong></p> <p> </p> <p>This book is another in the ever growing number offering an introduction to Windows Phone development. This one takes a slightly different approach to others I’ve read by opting for a “cookbook” style where it aims to provide a collection of “recipes” which the reader can apply to their apps.</p> <p>The book starts out well by encouraging developers to work with Expression Blend (which is something most developers would benefit from) and begins with helping the reader understand the available controls before showing how to create simple animations and behaviours.</p> <p>Unfortunately that’s where things start to go downhill as it follows the traditional pattern of introducing a selection of features and functionality and then providing an example of how to use it.</p> <p>The authors assume a level of experience in the reader but unfortunately don’t make it clear what this is. The preface states that the book is aimed at both the hobbyist and the professional developer. As the latter I don’t feel it gave me enough information on the idiosyncrasies of applying the techniques, the book describes, to my work. I also fear that for the former they don’t go far enough to help the beginner understand when each feature should be used or when and what alternatives may be appropriate.</p> <p>With 2 authors and 3 technical reviewers I was also disappointed to see a number of errors in the content. This included author notes which haven’t been completed (“Insert references to...”) as well as information which is factually incorrect. (“The emulator doesn’t support multi-touch.” – It does, you can just only use it if the machine running the emulator supports it,)</p> <p>The biggest disappointment I had with this book though was due to the comparison it draws with a cook book. When I look at a traditional cook book (one for preparing and cooking food) what attracts me is the dishes I can create from following the instructions therein. There are no recipes of that sort in this book. It’s more a collection of techniques. It’s also the pictures which particularly tempt me in a food based cookbook. Unfortunately the screenshots of the apps that are in the book aren’t particularly appealing and ignore lots of the simplest design guidelines and best practices.</p> <p>The book’s subtitles claim it includes "Quick answers to common problems" and "All the recipes you need to start creating apps and making money". <br /> I think it fails in both respects. <br /> There are lots of common problems which the book completely ignores. Presumably because these aren’t easy to demonstrate or tied to a specific control or feature.</p> <p>While the book does provide some help with creating apps, it doesn’t help the inexperienced or uneducated developer create apps which are better than what’s already available, or even identify what a higher quality app would look like. It also doesn’t mention anything which would help developers make money from their apps. There are already too many people creating apps who simply assume that if they build it sales (and money) will come. Except for a very small few this is simply not the case. I would expect a responsibly authored book providing guidance in this area to do a better job of explaining what someone entering the marketplace might expect and how to give themselves the best possible odds of creating something that will meet the needs of the user and the aims of the creator.</p> <p>If you're new to developing for Windows Phone 7 then there are definitely lots of things that you can learn from this book. If you have some experience then it may provide a few introductory pointers to a more design focused approached to your app creation. Beyond that, however, there are many other books which will better help developers understand what can be done on Windows Phone and also how to do it.</p> <p>Disclaimer. I was given a free PDF copy of this book for review purposes.</p> http://www.silverlightshow.net/items/Book-Review-Window-Phone-7-Silverlight-Cookbook.aspx editorial@silverlightshow.net (Matt Lacey ) http://www.silverlightshow.net/items/Book-Review-Window-Phone-7-Silverlight-Cookbook.aspx#comments http://www.silverlightshow.net/items/Book-Review-Window-Phone-7-Silverlight-Cookbook.aspx Tue, 20 Dec 2011 12:15:00 GMT SkyDrive usage through Live SDK on Windows Phone <table width="20"> <tbody> <tr> <td> <div class="fb-like" data-show-faces="true" data-send="false" data-href="http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx" data-font="segoe ui" data-layout="button_count"></div> </td> <td><a href="https://twitter.com/share" class="twitter-share-button" data-via="silverlightshow" data-counturl="http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx" data-count="horizontal" data-text="Reading @samidip's article 'SkyDrive usage through Live SDK on #WindowsPhone' #wpdev" data-url="http://slshow.net/rOpJh9">Tweet</a></td> <td><g:plusone size="medium" href="http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx"></g:plusone> </td> <td> </td> </tr> </tbody> </table> <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; margin-left: 10px; padding-top: 5px;"> <div style="text-align: center;"> <div style="text-align: center;"><strong>This article is also available in print (Word, PDF) and e-reader formats (MOBI, EPUB).</strong></div> <div style="text-align: center;"><strong><strong></strong><a href="http://www.silverlightshow.net/Storage/Sources/SkyDrive%20usage%20through%20Live%20SDK%20on%20WP%20-%20Samidip%20Basu.zip"><strong>Download all formats, including source code</strong><span style="font-weight: normal;"><strong>.</strong></span></a><span style="font-weight: normal;"><strong></strong> </span></strong></div> </div> </div> Guess how many people use Live Services? 500 million plus! And when our applications connect to the same services, they start feeling right at home with what our users are already used to. Microsoft recently opened the <em>Live Connect APIs</em>, along with some SDKs for 3rd party applications on desktop/web/mobile platforms to leverage the cloud offerings from Live Services. <div style="border: 1px solid #dddddd; padding-bottom: 5px; background-color: #f3f3f3; margin-top: 5px; padding-left: 10px; width: 200px; float: right; margin-left: 10px; margin-right: 5px; padding-top: 5px;"> <h3>Don't miss...</h3> <ul style="list-style-type: circle; margin: 0px; padding-left: 20px; font-size: 12px;"> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/video/Windows-Phone-Unit-Testing-Webinar.aspx">Webinar recording: Unit Testing for Windows Phone</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/items/Producing-and-Consuming-OData-in-a-Silverlight-and-Windows-Phone-7-application.aspx">The article series: Producing and Consuming OData in a Silverlight and WP7 application</a> </li> <li style="padding-bottom: 5px;"><a href="http://www.silverlightshow.net/ebooks/odata_cloud.aspx">Samisip's Ebook 'OData & Cloud Augmentation of Windows Phone Apps':</a> </li> </ul> <p style="padding-bottom: 5px; text-align: center;"><a href="http://www.silverlightshow.net/ebooks/odata_cloud.aspx"><img style="width: 107px; height: 150px;" alt="Producing and Consuming OData in a Silverlight and WP7 App Ebook" src="http://www.silverlightshow.net/Storage/Ebooks/odata_cloud.png" /></a></p> <p style="font-size: 12px;">     <a href="http://www.silverlightshow.net/ebooks.aspx">All SilverlightShow Ebooks</a> <img alt="" src="http://www.silverlightshow.net/Storage/arrow-content.jpg" /></p> </div>   <p>In this short article, we take a look at how we could get started using the Live Connect API from our Windows Phone applications and interact with SkyDrive storage through the new Live SDK.</p> <h3><a href="http://www.silverlightshow.net/Storage/Sources/LiveSDKDemo.zip">Download Source Code</a></h3> <p>[Please note that unlike other Demo solutions, you simply cannot hit F5 to run it. For obvious reasons, I have had to strip out references to my personal SkyDrive; so you would have to get yourself a client ID & make a one-word change before running the solution. Steps explained below.]</p> <h2>Introduction</h2> <p>The new Live APIs expose information around the following .. more information @ <a href="http://msdn.microsoft.com/en-us/library/hh243641.aspx" target="_blank">Live Connect Developer Guide</a>:</p> <ul> <li><strong>SkyDrive</strong> -- This is for working with files & media; we can read/write against the user's SkyDrive files/folders/albums. SkyDrive offers the perfect cloud storage for Windows Phone applications to push persistence to the user's SkyDrive or to act as back-up storage. </li> <li><strong>Hotmail</strong> -- These sets of APIs expose the users contacts & calendars for read/writes. </li> <li><strong>Messenger</strong> -- These APIs are for use in instant messaging. We can read user's current status & communicate with user's buddies. </li> <li><strong>Windows Live ID</strong> -- This acts as a sort of Access Control Service that we could use to authenticate users & access their Live profile information. </li> </ul> <p>The Live Connect APIs use standard protocols such as HTTP, OAuth 2.0, JSON and XMPP to make it easy working with them across multiple platforms. To leverage the APIs, we primarily use Representational State Transfer (REST) requests which return information in JSON. </p> <p>While any of the above classes of APIs may be useful from a Windows Phone application, in this article we shall focus on the SkyDrive APIs, which arguably would be the most commonly used. No longer would developers need to spin up storage in cloud to augment their solutions; we can simply leverage the user's SkyDrive which has the additional benefit of user's accessibility & familiarity.</p> <h2>Getting Started</h2> <p>So, let's start integrating the Live Connect SDK into our Windows Phone application:</p> <ul> <li>While the standard technologies of HTTP/REST/JSon make it easy to work with in any platform, there is some additional help in the form of wrapper SDKs for Windows Phone & Windows 8. Let's grab the <a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=28195" target="_blank">Windows Phone Live SDK</a> first. </li> <li>Next, to have Live Connect recognize requests from our Windows Phone App, we need an unique identifier, called the <em>Client ID</em>. So, let's head over to the <a href="https://manage.dev.live.com/Applications/Index" target="_blank">Live Connect App Management site</a> & create a new application to interact with Live Services. </li> <li>The new application will be registered with a Client ID, along with a <em>Client Secret</em> & <em>Redirect Domain</em> (that you type in). The two latter ones are not strictly needed for Windows Phone integration. The end result should be something like this: </li> </ul> <blockquote> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/App%20Config_4.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border-width: 0px; border-style: solid;" title="App Config" alt="App Config" src="http://www.silverlightshow.net/Storage/Users/samidip/App%20Config_thumb_1.png" width="614" height="337" /></a></p> </blockquote> <ul> <li>Live Connect is a combination of several services allowing access to different categories of information. These are organized into what's called <em>Scopes</em>, and explicit declaration & user permission is required for our App to access the categorized information; as a good practice, we should never ask for more than what our App actually needs. For more information, please see <a href="http://msdn.microsoft.com/en-us/library/hh243646.aspx" target="_blank">Scopes & Permissions</a>. </li> <li>Users need to signed in with their Live Credentials & provide consent to utilize their SkyDrive, before we can leverage Live Connect APIs to manipulate files/folders in SkyDrive. While there are several ways to achieve this, in the XAML/C# world of Windows Phone, the easiest is to utilize the built-in <em>Sign-in</em> control in the SDK. Before you use it, make sure to Add Reference to these two libraries: </li> </ul> <blockquote> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Add%20References_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Add References" alt="Add References" src="http://www.silverlightshow.net/Storage/Users/samidip/Add%20References_thumb.png" width="354" height="297" /></a></p> </blockquote> <ul> <li>Next,, if you're in the XAML Designer view & you don't see the Sign-in control in your Toolbox, here's how to add it. The obvious benefit of using the Sign-In control is that we do not need to write the low-level HTTP RESTful GET calls to authenticate & authorize our user; the log-on UI comes up automatically & the client classes hang on to the access tokens passed back from the sign-in control for utilization in future requests. </li> </ul> <blockquote> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Live%20Sign-In%20Control_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Live Sign-In Control" alt="Live Sign-In Control" src="http://www.silverlightshow.net/Storage/Users/samidip/Live%20Sign-In%20Control_thumb.png" width="354" height="255" /></a></p> </blockquote> <h2></h2> <h2></h2> <h2></h2> <h3></h3> <h3></h3> <h2></h2> <h1></h1> <h2>The Demo App</h2> <p>So, let's write a simple Windows Phone application that allows the user to sign in & see/insert files in one's SkyDrive storage. Here's some XAML on our <em>MainPage.xaml</em> to show the sign-in control. Watch the use of scopes to declare what we want access to:</p> <div style="border: 1px solid silver; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; text-align: left;" id="codeSnippetWrapper"> <div style="padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; text-align: left;" id="codeSnippet"> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <Grid x:Name=<span style="color: #006080;">"ContentPanel"</span> Grid.Row=<span style="color: #006080;">"1"</span> Margin=<span style="color: #006080;">"12,0,12,0"</span>></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> <StackPanel Orientation=<span style="color: #006080;">"Vertical"</span> ></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <TextBlock Text=<span style="color: #006080;">"Please sign-in and allow access to your SkyDrive!"</span> Margin=<span style="color: #006080;">"20"</span> TextWrapping=<span style="color: #006080;">"Wrap"</span> Width=<span style="color: #006080;">"450"</span> FontSize=<span style="color: #006080;">"30"</span>/></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <live:SignInButton Name=<span style="color: #006080;">"btnSignin"</span> ClientId=<span style="color: #006080;">"Your_Client_ID"</span> Scopes=<span style="color: #006080;">"wl.signin wl.basic wl.skydrive wl.skydrive_update"</span> </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> RedirectUri=<span style="color: #006080;">"Your_Redirect_URI"</span> Branding=<span style="color: #006080;">"Windows"</span> TextType=<span style="color: #006080;">"SignIn"</span> SessionChanged=<span style="color: #006080;">"btnSignin_SessionChanged"</span> </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> HorizontalAlignment=<span style="color: #006080;">"Center"</span> VerticalAlignment=<span style="color: #006080;">"Top"</span> /></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <TextBlock x:Name=<span style="color: #006080;">"txtLoginResult"</span> HorizontalAlignment=<span style="color: #006080;">"Center"</span> Margin=<span style="color: #006080;">"0,20,0,0"</span> FontSize=<span style="color: #006080;">"30"</span> Style=<span style="color: #006080;">"{StaticResource PhoneTextAccentStyle}"</span>/></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <TextBlock x:Name=<span style="color: #006080;">"txtWelcome"</span> HorizontalAlignment=<span style="color: #006080;">"Center"</span> Margin=<span style="color: #006080;">"0,20,0,0"</span> FontSize=<span style="color: #006080;">"30"</span> Style=<span style="color: #006080;">"{StaticResource PhoneTextAccentStyle}"</span>/></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <Button x:Name=<span style="color: #006080;">"btnShowContent"</span> Content=<span style="color: #006080;">"Show File Content"</span> Width=<span style="color: #006080;">"300"</span> Margin=<span style="color: #006080;">"30"</span> Visibility=<span style="color: #006080;">"Collapsed"</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> Click=<span style="color: #006080;">"btnShowContent_Click"</span>/></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> <Button x:Name=<span style="color: #006080;">"btnAddFile"</span> Content=<span style="color: #006080;">"Add File"</span> Width=<span style="color: #006080;">"300"</span> Margin=<span style="color: #006080;">"30, -20,30,30"</span> Visibility=<span style="color: #006080;">"Collapsed"</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> Click=<span style="color: #006080;">"btnAddFile_Click"</span>/></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> </StackPanel></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> </Grid></pre> <!--CRLF--></div> </div> <p> <br /> The resultant UI before the user signs in as as follows. Also, on first usage of the sign-in button, the user will be prompted to sign-on to Windows Live and provide one-time OAuth access to our application, as demonstrated below:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Sign-In%20Control_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Sign-In Control" alt="Sign-In Control" src="http://www.silverlightshow.net/Storage/Users/samidip/Sign-In%20Control_thumb.png" width="204" height="388" /></a>    <a href="http://www.silverlightshow.net/Storage/Users/samidip/User%20Log-on_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="User Log-on" alt="User Log-on" src="http://www.silverlightshow.net/Storage/Users/samidip/User%20Log-on_thumb.png" width="204" height="388" /></a>   <a href="http://www.silverlightshow.net/Storage/Users/samidip/OAuth%20Access_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="OAuth Access" alt="OAuth Access" src="http://www.silverlightshow.net/Storage/Users/samidip/OAuth%20Access_thumb.png" width="204" height="388" /></a></p> <p>And here's some C# code to handle sign-on attempts. We use the <em>wl.signin</em> to log the user in & <em>wl.basic</em> to greet the user after reading some basic identifying information:</p> <div style="border: 1px solid silver; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; text-align: left;" id="codeSnippetWrapper"> <div style="padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; text-align: left;" id="codeSnippet"> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> btnSignin_SessionChanged(<span style="color: #0000ff;">object</span> sender, LiveConnectSessionChangedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> { </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">if</span> (e.Status == LiveConnectSessionStatus.Connected)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> client = <span style="color: #0000ff;">new</span> LiveConnectClient(e.Session);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> App.Current.LiveSession = e.Session;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #0000ff;">this</span>.txtLoginResult.Text = <span style="color: #006080;">"Signed in."</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> <span style="color: #0000ff;">this</span>.txtWelcome.Visibility = System.Windows.Visibility.Visible;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> <span style="color: #0000ff;">this</span>.btnShowContent.Visibility = System.Windows.Visibility.Visible;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">this</span>.btnAddFile.Visibility = System.Windows.Visibility.Visible;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> client.GetCompleted += <span style="color: #0000ff;">new</span> EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> client.GetAsync(<span style="color: #006080;">"me"</span>, <span style="color: #0000ff;">null</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> <span style="color: #0000ff;">this</span>.txtLoginResult.Text = <span style="color: #006080;">"Not signed in."</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> <span style="color: #0000ff;">this</span>.txtWelcome.Visibility = System.Windows.Visibility.Collapsed;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> client = <span style="color: #0000ff;">null</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> } </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> <span style="color: #0000ff;">void</span> OnGetCompleted(<span style="color: #0000ff;">object</span> sender, LiveOperationCompletedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> <span style="color: #0000ff;">if</span> (e.Error == <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> <span style="color: #0000ff;">if</span> (e.Result.ContainsKey(<span style="color: #006080;">"first_name"</span>) &&</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span> e.Result.ContainsKey(<span style="color: #006080;">"last_name"</span>))</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span> <span style="color: #0000ff;">if</span> (e.Result[<span style="color: #006080;">"first_name"</span>] != <span style="color: #0000ff;">null</span> &&</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span> e.Result[<span style="color: #006080;">"last_name"</span>] != <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum32" style="color: #606060;"> 32:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum33" style="color: #606060;"> 33:</span> <span style="color: #0000ff;">this</span>.txtWelcome.Text =</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum34" style="color: #606060;"> 34:</span> <span style="color: #006080;">"Hello, "</span> +</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum35" style="color: #606060;"> 35:</span> e.Result[<span style="color: #006080;">"first_name"</span>].ToString() + <span style="color: #006080;">" "</span> +</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum36" style="color: #606060;"> 36:</span> e.Result[<span style="color: #006080;">"last_name"</span>].ToString() + <span style="color: #006080;">"!"</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum37" style="color: #606060;"> 37:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum38" style="color: #606060;"> 38:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum39" style="color: #606060;"> 39:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum40" style="color: #606060;"> 40:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum41" style="color: #606060;"> 41:</span> txtWelcome.Text = <span style="color: #006080;">"Hello, signed-in user!"</span>;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum42" style="color: #606060;"> 42:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum43" style="color: #606060;"> 43:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum44" style="color: #606060;"> 44:</span> <span style="color: #0000ff;">else</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum45" style="color: #606060;"> 45:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum46" style="color: #606060;"> 46:</span> txtWelcome.Text = <span style="color: #006080;">"Error calling API: "</span> +</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum47" style="color: #606060;"> 47:</span> e.Error.ToString();</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum48" style="color: #606060;"> 48:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum49" style="color: #606060;"> 49:</span> }</pre> <!--CRLF--></div> </div> <p>Did you notice a couple of fun things? Once connected, we store the instance of the <em>LiveConnectClient</em> as a property on our <em>App</em> object; this allows for reuse throughout the application. Also, the RESTful Live APIs support several shortcuts that include “<em>me</em>” to indicate the current user. And here's the UI we are shooting for, after sign-on:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Signed%20In_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Signed In" alt="Signed In" src="http://www.silverlightshow.net/Storage/Users/samidip/Signed%20In_thumb.png" width="244" height="465" /></a></p> <h2>SkyDrive Files </h2> <p>Now that we have permission to user’s Live Services, let’s dig into SkyDrive. Most of us are used to storing documents & media on SkyDrive, and have the content show up in our Windows Phone, or folders kept in sync between multiple PCs/Macs through <a href="http://explore.live.com/windows-live-mesh?os=other" target="_blank">Live Mesh</a>. With programmatic access to SkyDrive, we have access to a lot of operations, such as:</p> <ul> <li>Create/Read/Update/Delete Folders </li> <li>Do the same with <em>Albums</em>, a special folder to handle media efficiently </li> <li>Traversing Directories </li> <li>Upload/Download Files </li> <li>Read/Update file/folder properties </li> <li>Move/copy files/folders etc. </li> </ul> <p>For much more information & details, please see <a href="http://msdn.microsoft.com/en-us/windowslive/hh528485" target="_blank">SkyDrive Developer Center</a>. For our Demo application, let us do the simple operations of reading files/folders from user’s SkyDrive <em>root</em> & adding files to it. Here’s how we fetch & list all content from the root directory on user’s SkyDrive:</p> <div style="border: 1px solid silver; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; text-align: left;" id="codeSnippetWrapper"> <div style="padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; text-align: left;" id="codeSnippet"> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> SkyDriveContent</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { get; set; }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { get; set; }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: #008000;">// Code in Phone Page.</span></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> List<SkyDriveContent> ContentList = <span style="color: #0000ff;">new</span> List<SkyDriveContent>();</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> PhoneApplicationPage_Loaded(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> LiveConnectClient client = <span style="color: #0000ff;">new</span> LiveConnectClient(App.Current.LiveSession);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> client.GetCompleted += <span style="color: #0000ff;">new</span> EventHandler<LiveOperationCompletedEventArgs>(clientDataFetch_GetCompleted);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> client.GetAsync(<span style="color: #006080;">"/me/skydrive/files"</span>);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> <span style="color: #0000ff;">void</span> clientDataFetch_GetCompleted(<span style="color: #0000ff;">object</span> sender, LiveOperationCompletedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> <span style="color: #0000ff;">if</span> (e.Error == <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span> List<<span style="color: #0000ff;">object</span>> data = (List<<span style="color: #0000ff;">object</span>>)e.Result[<span style="color: #006080;">"data"</span>];</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #0000ff;">foreach</span> (IDictionary<<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>> content <span style="color: #0000ff;">in</span> data)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> { </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum24" style="color: #606060;"> 24:</span> SkyDriveContent skyContent = <span style="color: #0000ff;">new</span> SkyDriveContent();</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum25" style="color: #606060;"> 25:</span> skyContent.Name = (<span style="color: #0000ff;">string</span>)content[<span style="color: #006080;">"name"</span>];</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum26" style="color: #606060;"> 26:</span> ContentList.Add(skyContent); </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum27" style="color: #606060;"> 27:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum28" style="color: #606060;"> 28:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum29" style="color: #606060;"> 29:</span> <span style="color: #0000ff;">this</span>.contentList.ItemsSource = ContentList;</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum30" style="color: #606060;"> 30:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum31" style="color: #606060;"> 31:</span> }</pre> <!--CRLF--></div> </div> <p>And, here’s the resulting UI that we bind the results to, simply showing the content names from SkyDrive root:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Skydrive%20Content_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Skydrive Content" alt="Skydrive Content" src="http://www.silverlightshow.net/Storage/Users/samidip/Skydrive%20Content_thumb.png" width="244" height="465" /></a></p> <p>Did you notice how we used “<em>me/skydrive/files</em>” to fetch all content from user’s SkyDrive root? Every folder/album in SkyDrive has a unique ID, visible when we inspect the folder properties. From this point on, we can easily dive into any folder & traverse the user’s SkyDrive by making requests with <em>Folder_ID/files</em> or <em>Album_ID/files</em>. Having fun?</p> <p>Now, how about putting files in user’s SkyDrive? Sure, we can .. here’s some simple UI & code to add a file to the root of the user’s SkyDrive directory:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/Add%20File_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="Add File" alt="Add File" src="http://www.silverlightshow.net/Storage/Users/samidip/Add%20File_thumb.png" width="244" height="465" /></a></p> <div style="border: 1px solid silver; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'courier new', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; text-align: left;" id="codeSnippetWrapper"> <div style="padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; text-align: left;" id="codeSnippet"> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum1" style="color: #606060;"> 1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> btnSave_Click(<span style="color: #0000ff;">object</span> sender, EventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum2" style="color: #606060;"> 2:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum3" style="color: #606060;"> 3:</span> <span style="color: #0000ff;">string</span> fileName = <span style="color: #0000ff;">this</span>.fileName.Text.Trim();</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: #0000ff;">byte</span>[] byteArray = Encoding.Unicode.GetBytes(<span style="color: #0000ff;">this</span>.fileContent.Text.Trim());</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum5" style="color: #606060;"> 5:</span> MemoryStream fileStream = <span style="color: #0000ff;">new</span> MemoryStream(byteArray);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum6" style="color: #606060;"> 6:</span> </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum7" style="color: #606060;"> 7:</span> LiveConnectClient uploadClient = <span style="color: #0000ff;">new</span> LiveConnectClient(App.Current.LiveSession);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum8" style="color: #606060;"> 8:</span> uploadClient.UploadCompleted += <span style="color: #0000ff;">new</span> EventHandler<LiveOperationCompletedEventArgs>(uploadClient_UploadCompleted);</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum9" style="color: #606060;"> 9:</span> uploadClient.UploadAsync(<span style="color: #006080;">"me/skydrive"</span>, fileName, fileStream );</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum10" style="color: #606060;"> 10:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum11" style="color: #606060;"> 11:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: #0000ff;">void</span> uploadClient_UploadCompleted(<span style="color: #0000ff;">object</span> sender, LiveOperationCompletedEventArgs e)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum13" style="color: #606060;"> 13:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum14" style="color: #606060;"> 14:</span> <span style="color: #0000ff;">if</span> (e.Error == <span style="color: #0000ff;">null</span>)</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum15" style="color: #606060;"> 15:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum16" style="color: #606060;"> 16:</span> Dispatcher.BeginInvoke(() =></pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum17" style="color: #606060;"> 17:</span> {</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum18" style="color: #606060;"> 18:</span> MessageBox.Show(<span style="color: #006080;">"Voila, Saved to the SkyDrive :)"</span>, <span style="color: #006080;">"All Done!"</span>, MessageBoxButton.OK); </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum19" style="color: #606060;"> 19:</span> });</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum20" style="color: #606060;"> 20:</span> }</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum21" style="color: #606060;"> 21:</span>  </pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum22" style="color: #606060;"> 22:</span> <span style="color: #0000ff;">this</span>.NavigationService.GoBack();</pre> <!--CRLF--> <pre style="text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'courier new', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none;"><span id="lnum23" style="color: #606060;"> 23:</span> }</pre> <!--CRLF--></div> </div> <p>So, what did we see? A simple upload location indicator of “<em>me/skydrive</em>” puts the file at the root directory. You can certainly put it in any folder of your choice, as long as you know the ID of the folder. For confirmation, surely authenticate yourself & check if the file addition did work on your SkyDrive. Did for our case <img style="border-style: none;" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://www.silverlightshow.net/Storage/Users/samidip/___wlEmoticon-smile_2.png" />:</p> <p><a href="http://www.silverlightshow.net/Storage/Users/samidip/SkyDrive%20File%20Upload.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px; border-style: solid;" title="SkyDrive File Upload" alt="SkyDrive File Upload" src="http://www.silverlightshow.net/Storage/Users/samidip/SkyDrive%20File%20Upload_thumb.png" width="604" height="144" /></a></p> <h2><sup></sup></h2> <h2>Conclusion & Caveats</h2> <ul> <li>With great power, comes great responsibility! Let us not undermine the end-user’s faith in SkyDrive. </li> <li>More specific details about SkyDrive File/Folder APIs can be found <a href="http://msdn.microsoft.com/en-us/windowslive/hh561740.aspx" target="_blank">HERE</a>. </li> <li>Watch the BUILD session recording on Live Connect <a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/PLAT-134C" target="_blank">HERE</a>. </li> <li>SkyDrive is a fantastic reliable alternative to augment storage for our Windows Phone applications, and user’s immediately see the file/folders we add in their SkyDrive. More importantly, Office sync on Windows Phone, and the dedicated SkyDrive apps on Windows Phone, iPhone & iPad immediately make the files available to the user. The story gets even better with built-in support in Windows 8, but I digress <img style="border-style: none;" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://www.silverlightshow.net/Storage/Users/samidip/___wlEmoticon-smile_2.png" /> </li> <li>Needless to say, SkyDrive access requires network connectivity. So, this should not possibly be our primary means of storage on Windows Phones. </li> </ul> <h2> </h2> <h2>Summary</h2> <p>In this article, we talked about how to leverage the new Live Connect APIs, in particular, the Live SDK in our Windows Phone applications. We saw the usage of the Sign-in control to ask for user’s authentication & seeking permission to use specific resources through the Live API. SkyDrive access is now handy, with full support to traverse, read & manipulate content in user’s SkyDrive directories. So, what are you waiting for? Look up some documentation & enable SkyDrive access from your Windows Phone application, resulting in happy users & happier you!</p> <p>I would appreciate any comments or concerns or how things could be done better. Thanks for reading & happy coding.</p> <p>Cheers <em>SilverlightShow</em>!</p> <h2> </h2> <h2>About the Author</h2> <p><img style="background-image: none; margin: 0px 30px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; float: left; border-width: 0px; border-style: solid;" title="ActualPic" alt="ActualPic" src="http://www.silverlightshow.net/Storage/Users/samidip/__ActualPic_1.jpg" width="144" height="175" />Samidip Basu (<a href="https://twitter.com/#!/samidip">@samidip</a>) is a technologist & gadget-lover working as a Manager & Solutions Lead for Sogeti USA out of the Columbus Unit. With a strong developer background in Microsoft technology stack, he now spends much of his time in spreading the word to discover the full potential of the Windows Phone platform & cloud-backed mobile solutions in general. He passionately runs the Central Ohio Windows Phone User Group (<a href="http://cowpug.org/">http://cowpug.org</a>), labors in M3 Conf (<a href="http://m3conf.com/">http://m3conf.com/</a>) organization and can be found with at-least a couple of hobbyist projects at any time. His spare times call for travel and culinary adventures with the wife. Find out more at <a href="http://samidipbasu.com/">http://samidipbasu.com</a>.</p> http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx editorial@silverlightshow.net (Samidip Basu ) http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx#comments http://www.silverlightshow.net/items/SkyDrive-usage-through-Live-SDK-on-Windows-Phone.aspx Mon, 19 Dec 2011 07:34:25 GMT