<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>- </title><link>http://www.guruumeditation.net:80/</link><description>- </description><item><title>MetroEvenToCommand v2.1</title><link>http://www.guruumeditation.net:80/metroeventocommand-v2.1-2</link><description>&lt;p&gt;Just a quick update of MetroEventToCommand.&lt;/p&gt; &lt;p&gt;Now it has a “HandleEvent” property. When true, it will set the event to Handled (providing the event args support it).&lt;/p&gt; &lt;p&gt;Exemple :&lt;/p&gt; &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:e126f7d5-77b3-4eff-b88f-cfb655db0872" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: xml;"&gt;        &amp;lt;Button Grid.Column="1" Grid.Row="1" Content="Parameter" HorizontalAlignment="Center"&amp;gt;
            &amp;lt;metroEventToCommand:EventToCommandManager.Collection&amp;gt;
                &amp;lt;metroEventToCommand:EventToCommand Command="{Binding Test2Command}" HandleEvent="True"
                     CommandParameter="{Binding SimpleParam}" Event="Click"&amp;gt;
               &amp;lt;/metroEventToCommand:EventToCommand&amp;gt;
            &amp;lt;/metroEventToCommand:EventToCommandManager.Collection&amp;gt;
        &amp;lt;/Button&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the eventarg doesn’t have an Handled property, it will just do nothing.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nuget.org/packages/MetroEventToCommand/"&gt;http://nuget.org/packages/MetroEventToCommand/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That’s all for this time, next posts will be during //build/.&lt;/p&gt;</description><pubDate>Sun, 16 Jun 2013 18:11:40 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/metroeventocommand-v2.1-2</guid></item><item><title>MetroEvenToCommand v2.1</title><link>http://www.guruumeditation.net:80/metroeventocommand-v2.1</link><description>&lt;p&gt;Juste une petite mise à jour de MetroEventToCommand.&lt;/p&gt; &lt;p&gt;Il y a maintenant une propriété “HandleEvent”. Quand elle est à True, ça va mettre l’évènement à Handled (Si l’évènement gère cette propriété).&lt;/p&gt; &lt;p&gt;Exemple :&lt;/p&gt; &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:e126f7d5-77b3-4eff-b88f-cfb655db0872" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: xml;"&gt;        &amp;lt;Button Grid.Column="1" Grid.Row="1" Content="Parameter" HorizontalAlignment="Center"&amp;gt;
            &amp;lt;metroEventToCommand:EventToCommandManager.Collection&amp;gt;
                &amp;lt;metroEventToCommand:EventToCommand Command="{Binding Test2Command}" HandleEvent="True"
                     CommandParameter="{Binding SimpleParam}" Event="Click"&amp;gt;
               &amp;lt;/metroEventToCommand:EventToCommand&amp;gt;
            &amp;lt;/metroEventToCommand:EventToCommandManager.Collection&amp;gt;
        &amp;lt;/Button&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Si l’évènement (Ou, pour être exact, le eventarg de l’évènement) n’a pas de propriété Handled, il ne se passe rien.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nuget.org/packages/MetroEventToCommand/"&gt;http://nuget.org/packages/MetroEventToCommand/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C’est tout pour cette fois, le prochain post est durant le //build/.&lt;/p&gt;</description><pubDate>Sun, 16 Jun 2013 18:11:40 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/metroeventocommand-v2.1</guid></item><item><title>Nokia Developer Champion</title><link>http://www.guruumeditation.net:80/nokia-developer-champion-2</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Got a nice email from Nokia last week : they awarded me the &lt;strong&gt;Nokia Developer Champion&lt;/strong&gt; title !&lt;/p&gt; &lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto" src="http://www.guruumeditation.net/Media/Default/Blog/NDC3.png"&gt;&lt;/p&gt; &lt;p&gt;It was an amazing surprise, thanks to the Nokia team !&lt;/p&gt; &lt;p&gt;So, what is the Nokia Developer Champion (NDC) program ? Well, you can see it as the MVP program for Nokia. It is also awarded for 1 year renewable. &lt;/p&gt; &lt;p&gt;The key benefits are :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Nokia recognition&lt;/li&gt; &lt;li&gt;A device as Welcome Gift (Waiting for the 925)&lt;/li&gt; &lt;li&gt;Nokia Developer Premium membership&lt;/li&gt; &lt;li&gt;Technical support&lt;/li&gt; &lt;li&gt;Support for developer events&lt;/li&gt; &lt;li&gt;Invitations to some Nokia events&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;More information here : &lt;a title="https://www.developer.nokia.com/Community/Champions/" href="https://www.developer.nokia.com/Community/Champions/"&gt;https://www.developer.nokia.com/Community/Champions/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The best OS, the best devices. I feel blessed I can be of some help. Now I have to take up the challenge !&lt;/p&gt;</description><pubDate>Fri, 17 May 2013 13:55:47 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/nokia-developer-champion-2</guid></item><item><title>Nokia Developer Champion</title><link>http://www.guruumeditation.net:80/nokia-developer-champion</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;J’ai reçu un email bien sympathique de Nokia la semaine passée : une invitation pour être &lt;strong&gt;Nokia Developer Champion&lt;/strong&gt; !&lt;/p&gt; &lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto" src="http://www.guruumeditation.net/Media/Default/Blog/NDC3.png"&gt;&lt;/p&gt; &lt;p&gt;Une surprise tout à fait inattendue (pléonasme), un grand merci à l’équipe de Nokia ! &lt;p&gt;Mais qu’est-ce que le programme Nokia Developer Champion (NDC) ? En gros, on peut le voir comme l’équivalent Nokia du programme MVP de Microsoft. On est nommé pour un an, renouvelable. &lt;p&gt;Les avantages sont :  &lt;ul&gt; &lt;li&gt;Reconnaissance de Nokia&lt;/li&gt; &lt;li&gt;Un mobile offert par an (J’attends le 925)&lt;/li&gt; &lt;li&gt;Un an sur le Nokia Developer Premium&lt;/li&gt; &lt;li&gt;Support technique&lt;/li&gt; &lt;li&gt;Aide à l’organisation d’événements développeurs&lt;/li&gt; &lt;li&gt;Invitations à des évènements Nokia&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Plus d’info ici  : &lt;a title="https://www.developer.nokia.com/Community/Champions/" href="https://www.developer.nokia.com/Community/Champions/"&gt;https://www.developer.nokia.com/Community/Champions/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Le meilleur OS, les meilleurs mobiles. Je suis chanceux de pouvoir aider ! Maintenant, il faut assurer ! </description><pubDate>Fri, 17 May 2013 13:55:46 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/nokia-developer-champion</guid></item><item><title>Developping a Lens app for Windows Phone 8</title><link>http://www.guruumeditation.net:80/developping-a-lens-app-for-windows-phone-8</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Some WP devices are known for their excellent camera (*hum* Lumia 920 *hum*), so let&amp;rsquo;s play a bit with a feature introduced with Windows Phone 8 : the camera lenses.&lt;/p&gt;
&lt;p&gt;Basically, it is a software that can be called from the camera Lens page and that will (most probably) process images taken with the camera in a certain way. It can be effect like black/white, panorama composition,etc&amp;hellip;. In fact, it is not especially different from a regular app, though. It still appears on the application list of your phone, and can be launched like any other app.&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;h2&gt;Declaring the app as Lens&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In the app manifest, you must add those two capabilities : &amp;ldquo;&lt;strong&gt;ID_CAP_ISV_CAMERA&lt;/strong&gt;&amp;rdquo; and &amp;ldquo;&lt;strong&gt;ID_CAP_MEDIALIB_PHOTO&lt;/strong&gt;&amp;rdquo; so you can have access to the camera and the Medial Library to save images.&lt;/p&gt;
&lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto;" src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens1.png" /&gt;&lt;/p&gt;
&lt;p&gt;Open now the manifest in XML and, after the &lt;strong&gt;Tokens&lt;/strong&gt; element, declare your app as Lens app with :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:fbaa83e5-bcc5-415f-ab98-9d0c15cb5857" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Extensions&amp;gt;
  &amp;lt;Extension ExtensionName="Camera_Capture_App" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}" TaskID="_default" /&amp;gt;
&amp;lt;/Extensions&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;One more thing to do, is to add the icon that will appears in the Lens page. You must add 3 icons images in the &lt;strong&gt;Assets&lt;/strong&gt; directory :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lens.Screen-720p.png (173 x 173)&lt;/li&gt;
&lt;li&gt;Lens.Screen-WVGA.png (259 x 259)&lt;/li&gt;
&lt;li&gt;Lens.Screen-WXGA.png (277 x 277)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you deploy the app now and go to the Lens page, you&amp;rsquo;ll see the icon :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;When your app is called from the Lens page, the OS adds &amp;ldquo;&lt;em&gt;?Action=ViewfinderLaunch&amp;rdquo; &lt;/em&gt;to the start uri of your app (example : &amp;ldquo;&lt;em&gt;Mainpage.xaml?Action=ViewfinderLaunch&lt;/em&gt;&amp;rdquo;. That is how you can detect if your app was launched from the Lens page or not.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you want the user to land on different page depending of launched from Lens page or from start menu, you can do it using a custom &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.navigation.urimapperbase(v=vs.105).aspx" target="_blank"&gt;UriMapper&lt;/a&gt;. For instance :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:7d263b1b-6107-4fcb-bad3-d7036a79efbe" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;class CustomUriMapper : UriMapperBase
    {
        public override Uri MapUri(Uri uri)
        {
            string tempUri = uri.ToString();
            if (tempUri.Contains("ViewfinderLaunch"))
            {
                return new Uri("/LensPage.xaml", UriKind.Relative);
            }
            else
            {
                return uri;
            }
        }
    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This mapper will redirect to the page &lt;strong&gt;LensPage.xaml&lt;/strong&gt; if coming from the Lens page. To activate this wrapper, you can put it in the &lt;strong&gt;InitializePhoneApplication&lt;/strong&gt; method in &lt;strong&gt;App.cs&lt;/strong&gt; :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bec7dd7b-25dc-493c-b91d-3125e0f55bb6" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;RootFrame.UriMapper = new CustomUriMapper();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You need now to create a new page in your project called LensPage.xaml.&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;h2&gt;Lens exemple&lt;/h2&gt;
&lt;p&gt;Now we have a Lens, app, but it doesn&amp;rsquo;t to anything&amp;hellip;Let&amp;rsquo;s do something about that.&lt;/p&gt;
&lt;p&gt;The example I&amp;rsquo;ll show here is a Lens app where you can see the camera feed (nothing revolutionary) and can draw on it. Then you can take a snapshot.&lt;/p&gt;
&lt;p&gt;For the drawing part, I&amp;rsquo;ll use the &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.controls.inkpresenter(v=vs.105).aspx" target="_blank"&gt;InkPresenter&lt;/a&gt; control for the drawing, and the &lt;a href="http://nuget.org/packages/WriteableBitmapEx" target="_blank"&gt;WriteableBitmapEx&lt;/a&gt; Nuget package for the image processing.&lt;/p&gt;
&lt;p&gt;My &lt;strong&gt;LensPage.xaml&lt;/strong&gt; will look like this :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:80f41098-495e-4242-873f-9927f441938a" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;phone:PhoneApplicationPage x:Class="DrawLens.LensPage"
                            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                            xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
                            xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
                            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                            FontFamily="{StaticResource PhoneFontFamilyNormal}"
                            FontSize="{StaticResource PhoneFontSizeNormal}"
                            Foreground="{StaticResource PhoneForegroundBrush}"
                            SupportedOrientations="Landscape"
                            Orientation="Landscape"
                            mc:Ignorable="d"
                            shell:SystemTray.IsVisible="True"&amp;gt;

    &amp;lt;!--LayoutRoot is the root grid where all page content is placed--&amp;gt;
    &amp;lt;Grid x:Name="LayoutRoot"
          Background="Transparent"&amp;gt;
        &amp;lt;Grid.ColumnDefinitions&amp;gt;
            &amp;lt;ColumnDefinition Width="Auto"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
            &amp;lt;ColumnDefinition Width="*"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
        &amp;lt;/Grid.ColumnDefinitions&amp;gt;

        &amp;lt;StackPanel Orientation="Vertical"
                    x:Name="ButtonsSP"
                    Visibility="Collapsed"&amp;gt;
            &amp;lt;Button Content="Clear"
                    Margin="10,10"
                    Width="100"
                    Click="Clear_OnClick"&amp;gt;&amp;lt;/Button&amp;gt;
            &amp;lt;Button Content="Save"
                    Width="100"
                    Click="Save_OnClick"&amp;gt;
            &amp;lt;/Button&amp;gt;
        &amp;lt;/StackPanel&amp;gt;
        &amp;lt;TextBlock Text="Processing..."
                   Visibility="Visible"
                   x:Name="ProcessingLabel"&amp;gt;&amp;lt;/TextBlock&amp;gt;
        &amp;lt;InkPresenter Width="640"
                      Height="480"
                      MouseLeftButtonDown="TheInkPresenter_MouseLeftButtonDown"
                      LostMouseCapture="TheInkPresenter_LostMouseCapture"
                      MouseMove="TheInkPresenter_MouseMove"
                      x:Name="TheInkPresenter"
                      Grid.Column="1"&amp;gt;
            &amp;lt;InkPresenter.Background&amp;gt;
                &amp;lt;VideoBrush x:Name="CameraBrush"&amp;gt;&amp;lt;/VideoBrush&amp;gt;
            &amp;lt;/InkPresenter.Background&amp;gt;
        &amp;lt;/InkPresenter&amp;gt;
    &amp;lt;/Grid&amp;gt;

&amp;lt;/phone:PhoneApplicationPage&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So I have two columns. One with the buttons Clear and Save and the other with an InkPresenter that has a video brush. I will stream camera feed to this brush. I will not explain how the InkPresenter is drawing the strokes, it is not the purpose of this article and it is explained in the InkPresenter link above.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;First, when the page is loaded, we initialize the camera and redirect the feed to the InkPresenter videobrush background :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:cc285fed-70a3-484e-97db-bc44655e18b0" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;private PhotoCamera _camera;

public LensPage()
{
  InitializeComponent();

  this.Loaded += LensPage_Loaded;
}

void LensPage_Loaded(object sender, RoutedEventArgs e)
{
  if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
  {
       // Initialize camera, and show buttons only when camera ready
       _camera = new PhotoCamera(CameraType.Primary);
       // Event launched when the camera as taken a picture
       _camera.CaptureImageAvailable += _camera_CaptureImageAvailable;
        CameraBrush.SetSource(_camera);
  }

}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When the user press on the Save button, I capture an image:&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:ee2f7d8d-adc7-443d-9a62-c4619cdcf255" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: text;"&gt;private void Save_OnClick(object sender, RoutedEventArgs e)  
{
  _camera.CaptureImage();
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;When the image is captured, the camera CaptureImageAvailable event is launched. There you get the bitmap stream.&lt;/p&gt;
&lt;p&gt;I will make a bitmap from that stream. Then I&amp;rsquo;ll take all the strokes data of the InkPresenter and redraw those strokes on the bitmap (The DrawLineBresenham method in the code is based on the WritebeableBitmapEx one and allow to draw lines thicker than 1 pixel. See source code at the end of the post). As the InkPresenter size is different than the size of the image, I compute the magnification ratio by dividing the image size by the InkPresenter size.&lt;/p&gt;
&lt;p&gt;After drawing all the strokes, I save the bitmap to the Media Library.&lt;/p&gt;
&lt;p&gt;Enough words, enter code :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:445f3a14-5fea-4db2-b84f-cef0fb2a9f04" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;/// &amp;lt;summary&amp;gt;
/// Called when image is available
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
void _camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
{
    Dispatcher.BeginInvoke(() =&amp;gt; CreateAndSave(e.ImageStream));
}
/// &amp;lt;summary&amp;gt;
/// Process the image
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="stream"&amp;gt;&amp;lt;/param&amp;gt;
private void CreateAndSave(Stream stream)
{
    // Get bitmap from stream
    var _bitmap = new WriteableBitmap(1, 1);

    _bitmap = _bitmap.FromStream(stream);

    var width = _bitmap.PixelWidth;

    var height = _bitmap.PixelHeight;

    // Get ration between the inkpresenter size and the bitmap size
    var ratiox = width / TheInkPresenter.Width;

    var ratioy = height / TheInkPresenter.Height;

    // Draw each strokes on the bitmap
    foreach (var stroke in TheInkPresenter.Strokes)
    {
        var x1 = stroke.StylusPoints[0].X * ratiox;
        var y1 = stroke.StylusPoints[0].Y * ratioy;

        foreach (var point in stroke.StylusPoints.Skip(1))
        {
            var x2 = point.X * ratiox;

            var y2 = point.Y * ratioy;

            DrawLineBresenham(_bitmap, (int)x1, (int)y1, (int)x2, (int)y2, Colors.Red, (int)ratiox, (int)ratioy);

            x1 = x2;
            y1 = y2;
        }
    }
    // Save into library
    _bitmap.SaveToMediaLibrary("DrawLensGenerated.jpg");


    MessageBox.Show("Image saved !");
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A pic of the lens in action :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens4.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;And the result image :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens5.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The source code is &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/Lens/DrawLens.zip" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 09 May 2013 13:13:19 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/developping-a-lens-app-for-windows-phone-8</guid></item><item><title>Développer une application Lens pour Windows Phone 8</title><link>http://www.guruumeditation.net:80/developper-une-application-lens-pour-windows-phone-8</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Certains WP sont connus pour leur excellente cam&amp;eacute;ra (*hum* Lumia 920 *hum*), alors jouons un peu avec un petit truc sympa qui est apparu avec Windows Phone 8 : les camera lenses.&lt;/p&gt;
&lt;p&gt;En gros, c&amp;rsquo;est une application qui peut &amp;ecirc;tre appel&amp;eacute;e depuis la page des camera lenses et qui (pas oblig&amp;eacute;, mais bon&amp;hellip;) va retravailler les photos prises. Cela peut &amp;ecirc;tre une composition d'image (Photosynth est un exemple), ou juste une modification de l&amp;rsquo;image (par exemple filtre noir/blanc, ),etc&amp;hellip;. En fait, ce n&amp;rsquo;est pas fort diff&amp;eacute;rent d&amp;rsquo;une application normale car une camera lens peut &amp;ecirc;tre lanc&amp;eacute;e depuis le menu d&amp;eacute;marrer comme n&amp;rsquo;importer quelle application.&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;h2&gt;&lt;b&gt;D&amp;eacute;clarer l&amp;rsquo;application comme &lt;/b&gt;Lens&lt;/h2&gt;
&lt;p&gt;Pour d&amp;eacute;clarer l&amp;rsquo;application comme lens, il faut commencer par lui ajouter les capacit&amp;eacute;s &amp;ldquo;&lt;b&gt;ID_CAP_ISV_CAMERA&lt;/b&gt;&amp;rdquo; et &amp;ldquo;&lt;b&gt;ID_CAP_MEDIALIB_PHOTO&lt;/b&gt;&amp;rdquo; afin d&amp;rsquo;avoir acc&amp;egrave;s &amp;agrave; la camera, et &amp;agrave; Media Library pour sauver l&amp;rsquo;image.&lt;/p&gt;
&lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto;" src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens1.png" /&gt;&lt;/p&gt;
&lt;p&gt;Ouvrez maintenant le manifeste en XML et, apr&amp;egrave;s l&amp;rsquo;&amp;eacute;l&amp;eacute;ment &lt;b&gt;Tokens&lt;/b&gt; d&amp;eacute;clarer votre application comme lens en ajoutant :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:fbaa83e5-bcc5-415f-ab98-9d0c15cb5857" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Extensions&amp;gt;
  &amp;lt;Extension ExtensionName="Camera_Capture_App" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}" TaskID="_default" /&amp;gt;
&amp;lt;/Extensions&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Encore une chose &amp;agrave; faire : ajouter les ic&amp;ocirc;nes qui apparaitrons dans la page des lens. Il faut ajouter 3 icones dans le r&amp;eacute;pertoire &lt;b&gt;Assets&lt;/b&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lens.Screen-720p.png (173 x 173)&lt;/li&gt;
&lt;li&gt;Lens.Screen-WVGA.png (259 x 259)&lt;/li&gt;
&lt;li&gt;Lens.Screen-WXGA.png (277 x 277)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si vous d&amp;eacute;ployez l&amp;rsquo;application et que vous allez sur la page lens, vous verrez votre ic&amp;ocirc;ne apparaitre :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Quand votre application est appel&amp;eacute;e depuis la page lens, l&amp;rsquo;OS ajoute &amp;ldquo;&lt;i&gt;?Action=ViewfinderLaunch&amp;rdquo; &lt;/i&gt;&amp;agrave; l&amp;rsquo;uri de votre page de d&amp;eacute;part. (exemple : &amp;ldquo;&lt;i&gt;Mainpage.xaml?Action=ViewfinderLaunch&lt;/i&gt;&amp;rdquo;. C&amp;rsquo;est gr&amp;acirc;ce &amp;agrave; &amp;ccedil;a que vous pouvez savoir d&amp;rsquo;o&amp;ugrave; l&amp;rsquo;application &amp;agrave; &amp;eacute;t&amp;eacute; lanc&amp;eacute;e.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si vous voulez que l&amp;rsquo;utilisateur arrive sur une page diff&amp;eacute;rente suivant la fa&amp;ccedil;on dont il a lanc&amp;eacute; l&amp;rsquo;application, vous pouvez le faire via un &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.navigation.urimapperbase(v=vs.105).aspx" target="_blank"&gt;UriMapper&lt;/a&gt;. Par exemple :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:7d263b1b-6107-4fcb-bad3-d7036a79efbe" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;class CustomUriMapper : UriMapperBase
    {
        public override Uri MapUri(Uri uri)
        {
            string tempUri = uri.ToString();
            if (tempUri.Contains("ViewfinderLaunch"))
            {
                return new Uri("/LensPage.xaml", UriKind.Relative);
            }
            else
            {
                return uri;
            }
        }
    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ce mapper va rediriger vers la page &lt;b&gt;LensPage.xaml&lt;/b&gt; si l&amp;rsquo;application &amp;agrave; &amp;eacute;t&amp;eacute; lanc&amp;eacute;e depuis la page lens. Pour utiliser ce mapper, vous pouvez ajouter cette ligne dans la m&amp;eacute;thode &lt;b&gt;InitializePhoneApplication&lt;/b&gt; de &lt;b&gt;App.cs&lt;/b&gt; :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bec7dd7b-25dc-493c-b91d-3125e0f55bb6" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;RootFrame.UriMapper = new CustomUriMapper();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il faut bien &amp;eacute;videmment rajouter la page LensPage.xaml au projet.&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;h2&gt;&lt;b&gt;Un exemple de &lt;/b&gt;lens&lt;/h2&gt;
&lt;p&gt;Nous avons maintenant une application Lens qui ne fait rien&amp;hellip;Attaquons-nous &amp;agrave; ce probl&amp;egrave;me.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;exemple que je vais montrer ici est une application lens ou vous pouvez voir le flux cam&amp;eacute;ra (rien d&amp;rsquo;extraordinaire) et vous pouvez dessiner dessus. Apr&amp;egrave;s vous pouvez sauver l&amp;rsquo;image.&lt;/p&gt;
&lt;p&gt;Pour la parie dessin, j&amp;rsquo;utilise le contr&amp;ocirc;le &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.controls.inkpresenter(v=vs.105).aspx" target="_blank"&gt;InkPresenter&lt;/a&gt; et le package nuget &lt;a href="http://nuget.org/packages/WriteableBitmapEx" target="_blank"&gt;WriteableBitmapEx&lt;/a&gt; pour le traitement de l&amp;rsquo;image.&lt;/p&gt;
&lt;p&gt;Ma &lt;b&gt;LensPage.xaml&lt;/b&gt; ressemble &amp;agrave; ceci :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:80f41098-495e-4242-873f-9927f441938a" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;phone:PhoneApplicationPage x:Class="DrawLens.LensPage"
                            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                            xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
                            xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
                            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                            FontFamily="{StaticResource PhoneFontFamilyNormal}"
                            FontSize="{StaticResource PhoneFontSizeNormal}"
                            Foreground="{StaticResource PhoneForegroundBrush}"
                            SupportedOrientations="Landscape"
                            Orientation="Landscape"
                            mc:Ignorable="d"
                            shell:SystemTray.IsVisible="True"&amp;gt;

    &amp;lt;!--LayoutRoot is the root grid where all page content is placed--&amp;gt;
    &amp;lt;Grid x:Name="LayoutRoot"
          Background="Transparent"&amp;gt;
        &amp;lt;Grid.ColumnDefinitions&amp;gt;
            &amp;lt;ColumnDefinition Width="Auto"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
            &amp;lt;ColumnDefinition Width="*"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
        &amp;lt;/Grid.ColumnDefinitions&amp;gt;

        &amp;lt;StackPanel Orientation="Vertical"
                    x:Name="ButtonsSP"
                    Visibility="Collapsed"&amp;gt;
            &amp;lt;Button Content="Clear"
                    Margin="10,10"
                    Width="100"
                    Click="Clear_OnClick"&amp;gt;&amp;lt;/Button&amp;gt;
            &amp;lt;Button Content="Save"
                    Width="100"
                    Click="Save_OnClick"&amp;gt;
            &amp;lt;/Button&amp;gt;
        &amp;lt;/StackPanel&amp;gt;
        &amp;lt;TextBlock Text="Processing..."
                   Visibility="Visible"
                   x:Name="ProcessingLabel"&amp;gt;&amp;lt;/TextBlock&amp;gt;
        &amp;lt;InkPresenter Width="640"
                      Height="480"
                      MouseLeftButtonDown="TheInkPresenter_MouseLeftButtonDown"
                      LostMouseCapture="TheInkPresenter_LostMouseCapture"
                      MouseMove="TheInkPresenter_MouseMove"
                      x:Name="TheInkPresenter"
                      Grid.Column="1"&amp;gt;
            &amp;lt;InkPresenter.Background&amp;gt;
                &amp;lt;VideoBrush x:Name="CameraBrush"&amp;gt;&amp;lt;/VideoBrush&amp;gt;
            &amp;lt;/InkPresenter.Background&amp;gt;
        &amp;lt;/InkPresenter&amp;gt;
    &amp;lt;/Grid&amp;gt;

&amp;lt;/phone:PhoneApplicationPage&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc deux colonnes. Une avec les boutons Clear et Save, et l&amp;rsquo;autre avec un contr&amp;ocirc;le InkPresenter. Ce contr&amp;ocirc;le &amp;agrave; une VideoBrush comme image de fond. Je vais rediriger le flux vid&amp;eacute;o vers ce VideoBrush. Je ne parlerais pas du contr&amp;ocirc;le InkPresenter et de comment l&amp;rsquo;utiliser, ce n&amp;rsquo;est pas le but de l&amp;rsquo;article et tout est expliqu&amp;eacute; dans le lien que j&amp;rsquo;ai donn&amp;eacute; pr&amp;eacute;c&amp;eacute;demment.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Premi&amp;egrave;rement, quand la page est charg&amp;eacute;, j&amp;rsquo;initialise la camera et je redirige le flux vers le VideoBrush de fond du InkPresenter videobrush :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:cc285fed-70a3-484e-97db-bc44655e18b0" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;private PhotoCamera _camera;

public LensPage()
{
  InitializeComponent();

  this.Loaded += LensPage_Loaded;
}

void LensPage_Loaded(object sender, RoutedEventArgs e)
{
  if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
  {
       // Initialize camera, and show buttons only when camera ready
       _camera = new PhotoCamera(CameraType.Primary);
       // Event launched when the camera as taken a picture
       _camera.CaptureImageAvailable += _camera_CaptureImageAvailable;
        CameraBrush.SetSource(_camera);
  }

}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Quand l&amp;rsquo;utilisateur presse le bouton Save, je capture une photo:&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:ee2f7d8d-adc7-443d-9a62-c4619cdcf255" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: text;"&gt;private void Save_OnClick(object sender, RoutedEventArgs e)  
{
  _camera.CaptureImage();
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Quand l&amp;rsquo;image est capture, l&amp;rsquo;&amp;eacute;v&amp;egrave;nement CaptureImageAvailable est lanc&amp;eacute; par l&amp;rsquo;objet camera. C&amp;rsquo;est l&amp;agrave; qu&amp;rsquo;on r&amp;eacute;cup&amp;egrave;re un Stream de l&amp;rsquo;image.&lt;/p&gt;
&lt;p&gt;Je vais cr&amp;eacute;er un Bitmap de ce Stream. Puis je rajoute un &amp;agrave; un les Strokes qui ont &amp;eacute;t&amp;eacute;s trac&amp;eacute;es sur le InkPresenter. (La m&amp;eacute;thode DrawLineBresenham utilis&amp;eacute;e dans le code est une version maison de celle de WritebeableBitmapEx qui permet de dessiner des lignes de plus de 1 pixel d&amp;rsquo;&amp;eacute;paisseur. Voir le code source&amp;nbsp; donn&amp;eacute; en fin d&amp;rsquo;article). Comme la taille du InkPresenter est diff&amp;eacute;rente de la taille de l&amp;rsquo;image prise, je calcule un ratio d&amp;rsquo;agrandissement en divisant la taille de l&amp;rsquo;image par celle du InkPresenter.&lt;/p&gt;
&lt;p&gt;Apr&amp;egrave;s avoir redessin&amp;eacute; les Strokes, je sauve l&amp;rsquo;image dans la Media Library.&lt;/p&gt;
&lt;p&gt;Assez de discours, place au code :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:445f3a14-5fea-4db2-b84f-cef0fb2a9f04" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;/// &amp;lt;summary&amp;gt;
/// Called when image is available
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
void _camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
{
    Dispatcher.BeginInvoke(() =&amp;gt; CreateAndSave(e.ImageStream));
}
/// &amp;lt;summary&amp;gt;
/// Process the image
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="stream"&amp;gt;&amp;lt;/param&amp;gt;
private void CreateAndSave(Stream stream)
{
    // Get bitmap from stream
    var _bitmap = new WriteableBitmap(1, 1);

    _bitmap = _bitmap.FromStream(stream);

    var width = _bitmap.PixelWidth;

    var height = _bitmap.PixelHeight;

    // Get ration between the inkpresenter size and the bitmap size
    var ratiox = width / TheInkPresenter.Width;

    var ratioy = height / TheInkPresenter.Height;

    // Draw each strokes on the bitmap
    foreach (var stroke in TheInkPresenter.Strokes)
    {
        var x1 = stroke.StylusPoints[0].X * ratiox;
        var y1 = stroke.StylusPoints[0].Y * ratioy;

        foreach (var point in stroke.StylusPoints.Skip(1))
        {
            var x2 = point.X * ratiox;

            var y2 = point.Y * ratioy;

            DrawLineBresenham(_bitmap, (int)x1, (int)y1, (int)x2, (int)y2, Colors.Red, (int)ratiox, (int)ratioy);

            x1 = x2;
            y1 = y2;
        }
    }
    // Save into library
    _bitmap.SaveToMediaLibrary("DrawLensGenerated.jpg");


    MessageBox.Show("Image saved !");
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Une image de l&amp;rsquo;application en action :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens4.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Et le r&amp;eacute;sultat :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/Lens/Lens5.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Le code source est &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/Lens/DrawLens.zip" target="_blank"&gt;ici&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 09 May 2013 13:13:00 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/developper-une-application-lens-pour-windows-phone-8</guid></item><item><title>Awaitable WCF calls with TaskCompletionSource</title><link>http://www.guruumeditation.net:80/awaitable-wcf-calls-with-taskcompletionsource</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;A nice little gem of the TPL is the &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd449174.aspx" target="_blank"&gt;TaskCompletionSource&amp;lt;T&amp;gt;.&lt;/a&gt;&lt;/strong&gt; It creates a Task&amp;lt;T&amp;gt; you can control from outside the task.&lt;/p&gt; &lt;p&gt;Example :&lt;/p&gt; &lt;p&gt;I create a new &lt;strong&gt;TaskCompetionSource&amp;lt;bool&amp;gt;&lt;/strong&gt; :&lt;/p&gt; &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:29349db9-d9aa-4726-b98e-cdedbc28271b" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;var tcs = new TaskCompletionSource&amp;lt;CompositeType&amp;gt;();&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I get the Task&amp;lt;bool&amp;gt; from it :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:9a01800d-3059-4d4d-b919-6eb7a93a39e3" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.Task&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I can set the Task result this way :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:37589d67-558a-4467-b9b1-b2aadea9ddec" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.TrySetResult(true);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can set an exception like this :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:7b12afec-9ca5-4a43-9b80-aaf1d0b8992a" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: diff;"&gt;tcs.TrySetException(new Exception("This is an error"));&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or cancel it:&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bce1f569-e749-464c-b8e3-455f87c16cbc" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.TrySetCanceled();&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;OK…So what ?&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It doesn’t sound very interesting, does it?
&lt;p&gt;Well it can become quite useful with WCF if you can’t have awaitable calls (Like on Windows Phone, for instance).&lt;/p&gt;
&lt;p&gt;You can make any of those WCF calls awaitable like this :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:405c1fe9-ca3a-46c8-8575-1ba743b900f1" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;private Task&amp;lt;CompositeType&amp;gt; CallService()
        {

            var tcs = new TaskCompletionSource&amp;lt;CompositeType&amp;gt;();

            var client = new ServiceReference1.Service1Client();

            client.GetDataUsingDataContractCompleted += (o, args) =&amp;gt;
                                                            {
                                                                if (args.Error != null)
                                                                {
                                                                    tcs.TrySetException(args.Error);
                                                                    return;
                                                                }
                                                                if (args.Cancelled)
                                                                {
                                                                    tcs.TrySetCanceled();
                                                                    return;
                                                                }

                                                                tcs.TrySetResult(args.Result);
                                                            };

            client.GetDataUsingDataContractAsync(new CompositeType());

            return tcs.Task;
        }&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What I do is creating a TaskCompletionSource of the service return type.&lt;/p&gt;
&lt;p&gt;In the service callback event, I set the TaskCompletionSource depending on the service result.&lt;/p&gt;
&lt;p&gt;Now I just have to call the service, and to return the TaskCompletion Task.&lt;/p&gt;
&lt;p&gt;That method created is awaitable, so you can call it that way :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:8454610f-110a-4c7d-bc0f-ec16177a07fe" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;var result = await CallService();&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et voilà, now you can make WCF awaitable calls ! And it works with any call that has this callback event pattern.&lt;/p&gt;</description><pubDate>Fri, 03 May 2013 07:10:55 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/awaitable-wcf-calls-with-taskcompletionsource</guid></item><item><title>Appels WCF Awaitable avec TaskCompletionSource</title><link>http://www.guruumeditation.net:80/appels-wcf-awaitable-avec-taskcompletionsource</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Un petit joyau de la TPL est &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd449174.aspx" target="_blank"&gt;TaskCompletionSource&amp;lt;T&amp;gt;.&lt;/a&gt;&lt;/strong&gt; Cela crée une Task&amp;lt;T&amp;gt; qui peut être contrôlée en dehors de cette tâche. &lt;p&gt;Exemple : &lt;p&gt;Je crée un &lt;strong&gt;TaskCompetionSource&amp;lt;bool&amp;gt;&lt;/strong&gt; :  &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:29349db9-d9aa-4726-b98e-cdedbc28271b" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;var tcs = new TaskCompletionSource&amp;lt;CompositeType&amp;gt;();&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Je peux avoir la tâche Task&amp;lt;bool&amp;gt; associée :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:9a01800d-3059-4d4d-b919-6eb7a93a39e3" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.Task&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Je peux définir le résultat de la tâche de cette façon :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:37589d67-558a-4467-b9b1-b2aadea9ddec" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.TrySetResult(true);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Je peux lui faire lancer une exception :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:7b12afec-9ca5-4a43-9b80-aaf1d0b8992a" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: diff;"&gt;tcs.TrySetException(new Exception("This is an error"));&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou l’annuler:&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bce1f569-e749-464c-b8e3-455f87c16cbc" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;tcs.TrySetCanceled();&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;OK…Et alors ?&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Vu comme ça, ça ne semple pas trop excitant…
&lt;p&gt;Mais ça peut devenir intéressant si vous avez des appels services WCF qui ne sont pas awaitable (Comme sur Windows Phone, par exemple)
&lt;p&gt;Voici une façon de rendre ces appels awaitable :

&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:405c1fe9-ca3a-46c8-8575-1ba743b900f1" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;private Task&amp;lt;CompositeType&amp;gt; CallService()
        {

            var tcs = new TaskCompletionSource&amp;lt;CompositeType&amp;gt;();

            var client = new ServiceReference1.Service1Client();

            client.GetDataUsingDataContractCompleted += (o, args) =&amp;gt;
                                                            {
                                                                if (args.Error != null)
                                                                {
                                                                    tcs.TrySetException(args.Error);
                                                                    return;
                                                                }
                                                                if (args.Cancelled)
                                                                {
                                                                    tcs.TrySetCanceled();
                                                                    return;
                                                                }

                                                                tcs.TrySetResult(args.Result);
                                                            };

            client.GetDataUsingDataContractAsync(new CompositeType());

            return tcs.Task;
        }&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Je crée d’abord un TaskCompletionSource&amp;lt;T&amp;gt; du type de retour du service.
&lt;p&gt;Dans l’événement callback du service, je la défini l’état de la TaskCompletionSource en fonction du résultat de l’appel.
&lt;p&gt;Maintenant, je n’ai plus qu’à appeler le service lui-même et renvoyer la Task&amp;lt;T&amp;gt; liée à la TaskCompletionSource.
&lt;p&gt;La méthode ainsi crée est, vous pouvez donc l’appeler comme ça :

&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:8454610f-110a-4c7d-bc0f-ec16177a07fe" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;var result = await CallService();&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et voilà, vous pouvez maintenant faire des appels WCF awaitable ! Cette méthode marche aussi avec n’importe quel appel qui à ce pattern de de callback par évènement.
</description><pubDate>Fri, 03 May 2013 07:10:54 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/appels-wcf-awaitable-avec-taskcompletionsource</guid></item><item><title>Windows Phone 8 Push Notifications Callback</title><link>http://www.guruumeditation.net:80/windows-phone-8-push-notifications-callback-fr</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #ff0000;" color="#ff0000"&gt;Attention: Le team WP m&amp;rsquo;a pr&amp;eacute;venue qu&amp;rsquo;ils ont l&amp;rsquo;intention de rentre les callback obsol&amp;egrave;tes. Je ne peux donner aucune date, mais leur utilisation est d&amp;eacute;courag&amp;eacute;e par Microsoft.&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Alors pourquoi cet article? Tout simplement parce que je l&amp;rsquo;avais d&amp;eacute;j&amp;agrave; presque fini quand j&amp;rsquo;ai contact&amp;eacute; MS pour un d&amp;eacute;tail et qu&amp;rsquo;ils m&amp;rsquo;ont annonc&amp;eacute; qu&amp;rsquo;ils ont l&amp;rsquo;intention d&amp;rsquo;abandonner les callback. Et je ne voulais pas perdre le travail d&amp;eacute;j&amp;agrave; accompli&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Une option pas tr&amp;egrave;s connue (ni fort utilis&amp;eacute;e, de ce fait&amp;hellip;) des notifications push authentifi&amp;eacute;es et la possibilit&amp;eacute; d&amp;rsquo;avoir un callback qui est appel&amp;eacute; lorsque que le serveur WPNS d&amp;eacute;tecte que l&amp;rsquo;appareil est d&amp;eacute;connect&amp;eacute; (Perte de r&amp;eacute;seau, par exemple).&lt;/p&gt;
&lt;p&gt;Quand le WPNS d&amp;eacute;tecte la d&amp;eacute;connection, il envoie (Apr&amp;egrave;s un timeout qui peut &amp;ecirc;tre choisi) une requ&amp;ecirc;te POST vers un URL sp&amp;eacute;cifique, avec un payload sp&amp;eacute;cifique, le tout d&amp;eacute;termin&amp;eacute; lorsque vous avez registr&amp;eacute; le callback.&lt;/p&gt;
&lt;h2&gt;Registrer le callback&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Pour registrer un callback sur un channel, il faut juste envoyer une requ&amp;ecirc;te au WPNS. Requ&amp;ecirc;te similaire &amp;agrave; une notification push, except&amp;eacute; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dans le header "&lt;strong&gt;X-CallbackURI&lt;/strong&gt;&amp;rdquo;, il faut mettre l&amp;rsquo;URL de channel auquel le callback va se rapporter, avec &amp;ldquo;&lt;strong&gt;/callback&lt;/strong&gt;&amp;rdquo; &amp;agrave; la fin.&lt;/li&gt;
&lt;li&gt;Dans le header &amp;ldquo;&lt;strong&gt;X-CallbackTimeout&lt;/strong&gt;&amp;rdquo; vous pouvez mettre un timeout (en minute) apr&amp;egrave;s lequel le callback sera appell&amp;eacute;. (Optionnel, par d&amp;eacute;faut le timeout est de 90 minutes. Le maximum est de 24h).&lt;/li&gt;
&lt;li&gt;Dans le body de la requ&amp;ecirc;te, vous pouvez mettre un payload, qui sera envoy&amp;eacute; au callback. Ce payload est limit&amp;eacute; &amp;agrave; 1k.&lt;/li&gt;
&lt;li&gt;Le payload est soit du texte, soit du binaire.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Un exemple&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Voila la classe qui repr&amp;eacute;sente le payload que je veux envoyer:&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:18b0fd70-1883-45cd-a1ea-fcb8fc059d12" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;public class PhoneInfo
{
  public int ID { get; set; }

  public string DeviceID { get; set; }

  public string DeviceModel { get; set; }

  public DateTime InactiveTime { get; set; }

}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Et voila un exemple de registration de callback utilisant &lt;a href="http://json.codeplex.com/" target="_blank"&gt;JSON.NET&lt;/a&gt; pour la s&amp;eacute;rialisation :&lt;/p&gt;
&lt;p&gt;(remarque : channel est de type Uri et est le channel de notification. La registration se passe id&amp;eacute;alement lorsque le t&amp;eacute;l&amp;eacute;phone envoie le channel vers un web service pour commencer &amp;agrave; recevoir les notifications)&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:4640aff5-83f6-4124-b13a-cc7433ff1a12" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, Thumbprint, false)[0];

store.Close();


try
{
  // Serialize an object to JSON
  var infojsonstring = JsonConvert.SerializeObject(info);

  // Encode JSON to a byte array
  var encoding = new UTF8Encoding();

  var infojsonbytes = encoding.GetBytes(infojsonstring);

  // The cloud service must append "/callback" to the notification channel URI.  
  var callbackURI = channel.OriginalString + "/callback";

  // The URI to post the set callback request to.
  // CHANGE WITH YOUR URL
  var callbackUri = string.Format("http://{0}/MvcApplication/api/Notifications/CallbackMethod", Website);

  // Create a web request to send the register callback request to the Push Notification Service.
  var webRequest = (HttpWebRequest)WebRequest.Create(callbackURI);

  // Add the certificate because it is authenticated push notification
  webRequest.ClientCertificates.Add(certificate);

  // A mandatory custom header that specifies the URI to post the callback message to when any registered event with the associated subscription triggers.
  webRequest.Headers.Add("X-CallbackURI", callbackUri);

  // Set timeout to 1 minute
  webRequest.Headers.Add("X-CallbackTimeout", "1");

  // HTTP POST is the only allowed method to send the notification.
  webRequest.Method = "POST";

  // Sets the web request content length.
  webRequest.ContentLength = infojsonbytes.Length;

  // Set the content type according to the type of callback message being sent.
  webRequest.ContentType = "application/*";

  // Set the body
  using (Stream requestStream = webRequest.GetRequestStream())
  {
    requestStream.Write(infojsonbytes, 0, infojsonbytes.Length);
  }

  // Get the response. This example gets the web response synchronously, but a cloud service can get it asynchronously as well.
  var response = (HttpWebResponse)webRequest.GetResponse();

  // Ensure that the 'HTTP 200 OK' response is received from the Push Notification Service.
  Debug.Assert(response.StatusCode == HttpStatusCode.OK);

}
catch (Exception e)
{
  Console.WriteLine(e);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Exemple de Callback&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Je vais utiliser ASP.NET MVC 4 Web API (On peut pas trouver plus long ?) pour le callback. Comme les Web API sont REST, c&amp;rsquo;est parfait pour un callback.&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:6acc0a1b-1b4c-4076-b38b-28aa6f38dacf" class="wlWriterSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;[HttpPost]
public void CallbackMethod(HttpRequestMessage request)
{
  try
  {
    // Read body
    var readtask = ControllerContext.Request.Content.ReadAsStringAsync();

    readtask.Wait();

    if (readtask.IsFaulted)
      throw readtask.Exception;

    // Deserialize
    var info = JsonConvert.DeserializeObject&amp;lt;PhoneInfo&amp;gt;(readtask.Result);

    // Check if null
    if (info == null)
      throw new NullReferenceException("Info is null");

    // Do your stuff

  }
  catch (Exception e)
  {
    // Manage exception
  }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Remarques&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cela ne fonctionne qu&amp;rsquo;avec des channels s&amp;eacute;curis&amp;eacute;s (Voir ce &lt;a href="http://www.guruumeditation.net/Contents/Item/Preview/1119" target="_blank"&gt;post&lt;/a&gt; sur les notifications authentifi&amp;eacute;es)&lt;/li&gt;
&lt;li&gt;Si vous registrez un callback plusieurs fois sur un m&amp;ecirc;me channel, seul le dernier sera actif.&lt;/li&gt;
&lt;li&gt;Quand le t&amp;eacute;l&amp;eacute;phone se reconnecte, il faut de nouveau registrer le callback.&lt;/li&gt;
&lt;li&gt;Vous pouvez connaitre l&amp;rsquo;&amp;eacute;tat du channel et envoyant une notification et en regardant la valeur du header &amp;ldquo;&lt;strong&gt;X-DeviceConnectionStatus&lt;/strong&gt;&amp;rdquo; dans la r&amp;eacute;ponse. Si la valeur est &amp;ldquo;TempDisconnected&amp;rdquo;, le callback sera lanc&amp;eacute; (apr&amp;egrave;s le timeout)&lt;/li&gt;
&lt;li&gt;La fa&amp;ccedil;on la plus facile de tester est de mettre le timeout &amp;agrave; une minute et simuler une perte de r&amp;eacute;seau avec le Simulation Dashboard :&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto;" src="http://www.guruumeditation.net/Media/Default/Blog/WP8NotificationCallback/Callback1.png" /&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Dommage que le WPNS ne transmet pas le header Content-Type au callback, &amp;ccedil;a aurait &amp;eacute;t&amp;eacute; plus simple pour &amp;eacute;crire des callbacks comme :&lt;/p&gt;
&lt;pre&gt;&lt;strong&gt;public void CallbackMethod(PhoneInfo info)&lt;/strong&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai cr&amp;eacute;e un projet exemple, t&amp;eacute;l&amp;eacute;chargeable &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/WP8NotificationCallback/WP8PushNotificationsCallback.zip" target="_blank"&gt;ici&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ce que vous devez faire : changer le certificat pour les notification authentifi&amp;eacute;es, l&amp;rsquo;URL de votre web service et l&amp;rsquo;URL du callback. Comme le callback est appel&amp;eacute; par WPNS, il doit , bien &amp;eacute;videmment, &amp;ecirc;tre appelable depuis internet.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Un grand merci &amp;agrave; l&amp;rsquo;&amp;eacute;quipe WP pour son aide, en particulier Adam, Karan and Scott&lt;/p&gt;</description><pubDate>Tue, 16 Apr 2013 09:42:00 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/windows-phone-8-push-notifications-callback-fr</guid></item><item><title>Windows Phone 8 Push Notifications Callback</title><link>http://www.guruumeditation.net:80/windows-phone-8-push-notifications-callback</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span color="#ff0000" style="color: #ff0000;"&gt;WARNING : The WP team warned me that they plan to deprecated this feature. I cannot give any timeframe, but the usage is discouraged by Microsoft.&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So why did I made this article ? Well because it was written before I contacted the WP team for some details and they told me it will be deprecated. And I didn&amp;rsquo;t want to lose the work I&amp;rsquo;ve already done.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A little known (and little used) feature of the authenticated push notifications on WP is the ability to have a callback called when the push notification channel of a device get disconnected (In case of loss of network, for instance).&lt;/p&gt;
&lt;p&gt;So when the WPNS detects your device is disconnected, it will send a POST request (after a timeout you can set) to a specific URL you registered as callback, with a payload you gave it during the registration.&lt;/p&gt;
&lt;h2&gt;Registering the callback&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To register a callback, you have to send a request to the WPNS, similar as a regular push request except :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the "&lt;strong&gt;X-CallbackURI&lt;/strong&gt;&amp;rdquo; header, you must set the notification channel you want to add callback to, with &amp;ldquo;&lt;strong&gt;/callback&lt;/strong&gt;&amp;rdquo; at the end.&lt;/li&gt;
&lt;li&gt;In the &amp;ldquo;&lt;strong&gt;X-CallbackTimeout&lt;/strong&gt;&amp;rdquo; header, you can enter a timeout (in minutes) to set how many minutes after the disconnection the callback will be called (The default is 90 minutes. The maximum is 24 hours).&lt;/li&gt;
&lt;li&gt;In the request body, you can put the payload it will be forwarded to the callback. The only limitation is the payload can be 1k maximum.&lt;/li&gt;
&lt;li&gt;The payload is either text or binary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say the payload I want to send to the call back is this class :&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:18b0fd70-1883-45cd-a1ea-fcb8fc059d12" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;public class PhoneInfo
{
  public int ID { get; set; }

  public string DeviceID { get; set; }

  public string DeviceModel { get; set; }

  public DateTime InactiveTime { get; set; }

}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is how to set everything up, using &lt;a href="http://json.codeplex.com/" target="_blank"&gt;JSON.NET&lt;/a&gt; for the serialization :&lt;/p&gt;
&lt;p&gt;(Note : channel is of type Uri. It is most convenient to make the callback registration in your web service when the device sends you the channel it is registered to).&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:4640aff5-83f6-4124-b13a-cc7433ff1a12" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, Thumbprint, false)[0];

store.Close();


try
{
  // Serialize an object to JSON
  var infojsonstring = JsonConvert.SerializeObject(info);

  // Encode JSON to a byte array
  var encoding = new UTF8Encoding();

  var infojsonbytes = encoding.GetBytes(infojsonstring);

  // The cloud service must append "/callback" to the notification channel URI.  
  var callbackURI = channel.OriginalString + "/callback";

  // The URI to post the set callback request to.
  // CHANGE WITH YOUR URL
  var callbackUri = string.Format("http://{0}/MvcApplication/api/Notifications/CallbackMethod", Website);

  // Create a web request to send the register callback request to the Push Notification Service.
  var webRequest = (HttpWebRequest)WebRequest.Create(callbackURI);

  // Add the certificate because it is authenticated push notification
  webRequest.ClientCertificates.Add(certificate);

  // A mandatory custom header that specifies the URI to post the callback message to when any registered event with the associated subscription triggers.
  webRequest.Headers.Add("X-CallbackURI", callbackUri);

  // Set timeout to 1 minute
  webRequest.Headers.Add("X-CallbackTimeout", "1");

  // HTTP POST is the only allowed method to send the notification.
  webRequest.Method = "POST";

  // Sets the web request content length.
  webRequest.ContentLength = infojsonbytes.Length;

  // Set the content type according to the type of callback message being sent.
  webRequest.ContentType = "application/*";

  // Set the body
  using (Stream requestStream = webRequest.GetRequestStream())
  {
    requestStream.Write(infojsonbytes, 0, infojsonbytes.Length);
  }

  // Get the response. This example gets the web response synchronously, but a cloud service can get it asynchronously as well.
  var response = (HttpWebResponse)webRequest.GetResponse();

  // Ensure that the 'HTTP 200 OK' response is received from the Push Notification Service.
  Debug.Assert(response.StatusCode == HttpStatusCode.OK);

}
catch (Exception e)
{
  Console.WriteLine(e);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;Callback example&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I will use ASP.NET MVC 4 Web API (Could this name be longer ?) as callback. Web API are REST Api, so it fits perfectly for a callback&lt;/p&gt;
&lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:6acc0a1b-1b4c-4076-b38b-28aa6f38dacf" class="wlWriterEditableSmartContent" style="float: none; margin: 0px; display: inline; padding: 0px;"&gt;
&lt;pre class="brush: c#;"&gt;[HttpPost]
public void CallbackMethod(HttpRequestMessage request)
{
  try
  {
    // Read body
    var readtask = ControllerContext.Request.Content.ReadAsStringAsync();

    readtask.Wait();

    if (readtask.IsFaulted)
      throw readtask.Exception;

    // Deserialize
    var info = JsonConvert.DeserializeObject&amp;lt;PhoneInfo&amp;gt;(readtask.Result);

    // Check if null
    if (info == null)
      throw new NullReferenceException("Info is null");

    // Do your stuff

  }
  catch (Exception e)
  {
    // Manage exception
  }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Some remarks&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It only works with authenticated push notifications (See this &lt;a href="http://www.guruumeditation.net/Contents/Item/Preview/1117" target="_blank"&gt;blog post&lt;/a&gt; on how to set that up)&lt;/li&gt;
&lt;li&gt;If you set the callback several times, only the last one will be taken into account&lt;/li&gt;
&lt;li&gt;When the device is active again, you should re-register the callback&lt;/li&gt;
&lt;li&gt;You can know the channel current status by sending a notification and check the value of the &amp;ldquo;&lt;strong&gt;X-DeviceConnectionStatus&lt;/strong&gt;&amp;rdquo; header in the response. If the value is &amp;ldquo;TempDisconnected&amp;rdquo;, the callback will be called after the timeout.&lt;/li&gt;
&lt;li&gt;Easiest way to test is to set the timeout to 1 minute, and simulate a loss of network using the Simulation Dashboard :&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto;" src="http://www.guruumeditation.net/Media/Default/Blog/WP8NotificationCallback/Callback1.png" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;ul&gt;&lt;!--EndFragment--&gt;&lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Too bad you can&amp;rsquo;t tell the WPNS to forward the Content-Type header to the callback, it would have be easier to write Web API like this :&lt;/p&gt;
&lt;pre&gt;&lt;strong&gt;public void CallbackMethod(PhoneInfo info)&lt;/strong&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I made a sample project you can download &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/WP8NotificationCallback/WP8PushNotificationsCallback.zip" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What you have to change is your certificate (for the authenticated push notification), the URL of the web service registering the callback and the callback URL. As the callback is called by the WPNS, your callback URL must be, of course, accessible from internet.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Special thanks to the WP team for its help, especially Adam, Karan and Scott&lt;/p&gt;</description><pubDate>Tue, 16 Apr 2013 09:42:00 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/windows-phone-8-push-notifications-callback</guid></item><item><title>One more year !</title><link>http://www.guruumeditation.net:80/one-more-year</link><description>&lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;a href="http://mvp.microsoft.com/fr-fr/mvp/Olivier%20Matis-4039633" target="_blank"&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto" src="http://www.guruumeditation.net/Media/Default/Blog/MVP_BlueOnly.png"&gt;&lt;/a&gt; &lt;p&gt;Good news beginning of this month! Most important, I got this April 1st (and it’s not a joke ): &lt;p&gt;&lt;em&gt;Je tiens à nouveau à t’adresser personnellement toutes mes félicitations pour ton renouvellement au programme&amp;nbsp; Microsoft® Most Valuable Professional! &lt;/em&gt; &lt;p&gt;&lt;em&gt;Je suis ravie de passer une nouvelle année à tes côtés, et tiens à te remercier de tes nombreuses contributions communautaires, et de l'aide que tu apportes tout au long de l'année aux utilisateurs des produits Microsoft.&lt;/em&gt; &lt;p&gt;Yes! MVP one more year! Thanks to everybody that supported me! &lt;p&gt;&lt;img src="http://www.guruumeditation.net//Media/Default/Blog/Build-2013.png" width="838" height="465"&gt;&lt;/p&gt; &lt;p&gt;The other news is the &lt;a href="http://www.buildwindows.com/" target="_blank"&gt;//build/&lt;/a&gt; conference. It was a surprise announcement. And a surprising  date also, in June. Same time as TechEd Europe. Lucky me, I was just skipping this one…&amp;nbsp; &lt;p&gt;I managed to get a ticket. The first //build/ was amazing. The second one was good, but was also a bit disappointment because I hoped we’ll get more interaction with MS teams since it was on campus.  &lt;p&gt;So, what will be the giveaway this time? My ideas: a new 7” (or 8”) Windows Blue tablet or a new Nokia device (Or even a Surface Phone?) or maybe a Durango (XBox 720) dev kit? We’ll see!  </description><pubDate>Thu, 04 Apr 2013 09:09:11 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/one-more-year</guid></item><item><title>Un an de plus !</title><link>http://www.guruumeditation.net:80/un-an-de-plus</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://mvp.microsoft.com/fr-fr/mvp/Olivier%20Matis-4039633" target="_blank"&gt;&lt;img style="float: none; margin-left: auto; display: block; margin-right: auto" src="http://www.guruumeditation.net/Media/Default/Blog/MVP_BlueOnly.png"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;De bonnes nouvelles ce début de mois ! La plus importante, j’ai reçu cet email le 1er avril (sans blagues!):&lt;/p&gt; &lt;p&gt;&lt;em&gt;Je tiens à nouveau à t’adresser personnellement toutes mes félicitations pour ton renouvellement au programme&amp;nbsp; Microsoft® Most Valuable Professional! &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Je suis ravie de passer une nouvelle année à tes côtés, et tiens à te remercier de tes nombreuses contributions communautaires, et de l'aide que tu apportes tout au long de l'année aux utilisateurs des produits Microsoft.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Yes! MVP un an de plus! Merci à tous ceux qui m’ont soutenus !&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net//Media/Default/Blog/Build-2013.png" width="838" height="465"&gt;&lt;/p&gt; &lt;p&gt;L’autre nouvelle est la conférence &lt;a href="http://www.buildwindows.com/" target="_blank"&gt;//build/&lt;/a&gt;. Elle a été annoncée par surprise. Et à une date surprenante aussi : fin juin. En même temps que le techEd Europe, heureusement que j’avais décidé de passer mon tour cette fois-ci!&lt;/p&gt; &lt;p&gt;J’ai réussi à avoir un ticket. Le premier //build/ était fantastique. Le second était bon, mais un peu décevant parce que j’espérais plus d’interaction avec les équipes MS vu qu’on était sur le campus.&lt;/p&gt; &lt;p&gt;La grande question…le cadeau ? Mes idées : une nouvelle tablette Windows Blue 7” (ou 8”) ou un nouveau Nokia (Rêvons : un Surface Phone?) ou bien peut-être une kit développeur Durango (XBox 720)? On verra!&lt;/p&gt;</description><pubDate>Thu, 04 Apr 2013 09:09:11 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/un-an-de-plus</guid></item><item><title>Async/Await with WCF</title><link>http://www.guruumeditation.net:80/async-await-with-wcf</link><description>&lt;p&gt;A nice little feature of .NET 4.5 is you can use async await with WCF ! The services doesn’t need to be in .NET 4.5, only the client as it is in the proxy.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;When you add your service reference be sure to check if the task bases asynchronous operations will be generated by the proxy.&lt;/p&gt; &lt;p&gt;Click on advanced&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/AsyncWPF/WCF-Async1.png"&gt;&lt;/p&gt; &lt;p&gt;And check what kind of asynchronous operation will be generated.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/AsyncWPF/WCF-Async2.png"&gt;&lt;/p&gt; &lt;p&gt;So you can call your WCF that way :&lt;/p&gt; &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:a7755329-ca0c-4c3f-9d9f-cfb67303cc1c" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;
private async Task&amp;lt;string&amp;gt; TestAsyncWCF()
{
        var service = new ServiceReference1.Service1Client();

        var response =  await service.GetDataAsync(10);

        Debug.WriteLine(response);

        return response.ToUpper();
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Goodbye callbacks, it was nice knowing you…&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note : it doesn’t work with WP8&lt;/p&gt;</description><pubDate>Sun, 31 Mar 2013 18:53:04 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/async-await-with-wcf</guid></item><item><title>Async/Await avec WCF</title><link>http://www.guruumeditation.net:80/async-await-avec-wcf</link><description>&lt;p&gt;Un petit truc sympa de .NET 4.5 est qu’on peut utiliser async await avec WCF ! Les services n’ont pas besoin d’être en .NET 4.5, seulement le client, vu que ça se passe dans le proxy.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Quand vous ajoutez la référence à votre service, vérifiez si les opérations asynchrones générées sont de type Task.&lt;/p&gt; &lt;p&gt;Clicquer sur advanced&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/AsyncWPF/WCF-Async1.png"&gt;&lt;/p&gt; &lt;p&gt;Et regardez quel type d’opération asynchrone sera générée.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/AsyncWPF/WCF-Async2.png"&gt;&lt;/p&gt; &lt;p&gt;Après, vous pouvez appeler les services comme ça :&lt;/p&gt; &lt;div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:a7755329-ca0c-4c3f-9d9f-cfb67303cc1c" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre class="brush: c#;"&gt;private async Task&amp;lt;string&amp;gt; TestAsyncWCF()
{
        var service = new ServiceReference1.Service1Client();

        var response =  await service.GetDataAsync(10);

        Debug.WriteLine(response);

        return response.ToUpper();
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Au revoir callbacks, content de vous avoir connu…&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note : ça ne marche pas avec WP8&lt;/p&gt;</description><pubDate>Sun, 31 Mar 2013 18:53:04 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/async-await-avec-wcf</guid></item><item><title>Belgian super hackathon</title><link>http://www.guruumeditation.net:80/belgian-super-hackathon</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Around Belgium the 27th of March ? Enjoy developping Windows 8 app ? Want to win a ticket to Teched Europe 2013 in Madrid ?&lt;/p&gt; &lt;p&gt;Is it a dream ? No, it is :&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net//Media/Default/Blog/banner_superhackathon_no-s_920x220.jpg" width="824" height="195"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;4 cities ! &lt;strong&gt;No excuses !&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I’ll be at the Brussels one, day and night. See you there !&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx" href="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx"&gt;http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 18 Mar 2013 11:22:23 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/belgian-super-hackathon</guid></item><item><title>Super hackathon Belgique</title><link>http://www.guruumeditation.net:80/super-hackathon-belgique</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;En Belgique le 27 mars ? Tu aimes développer pour Windows 8 ? Tu voudrais gagner un ticket pour le Teched Europe 2013 à Madrid ?&lt;/p&gt; &lt;p&gt;Est-ce un rêve ? Non, c’est :&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net//Media/Default/Blog/banner_superhackathon_no-s_920x220.jpg" width="824" height="195"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;4 villes! &lt;strong&gt;Aucunes excuses !&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Je serais à Bruxelles, le jour et la nuit. A bientôt !&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx" href="http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx"&gt;http://www.microsoft.com/belux/msdn/apps/windows/superhack.aspx&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 18 Mar 2013 11:22:23 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/super-hackathon-belgique</guid></item><item><title>2013 MVP Summit</title><link>http://www.guruumeditation.net:80/2013-mvp-summit-2</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Last week (Feb 18th to Feb 21st) the 2013 MVP Summit was held in Redmond and Bellevue. It was the 20th anniversary of the MVP program and we were around 1400 MVPs from all around the world. We were introduced to MVPs that were amongst the first to be awarded. 20 years as MVP, hard to imagine for me, as it is only my first year!  &lt;p align="center"&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7615.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7615.jpg" width="700" height="466"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;What can you except at the Summit? Well…Information (Under NDA most of the time), networking (With PG or other MVPs) and, very important, FUN! We had great interaction with the teams, so we can provide them face to face feedbacks.  &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7629.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7629.jpg" width="400" height="267"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7634.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7634.jpg" width="400" height="267"&gt;&lt;/a&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Reception on the first day…&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Brazil was in the place !&lt;/em&gt; &lt;p&gt;It is a great time, hanging around with the MS team and all those MVPs. I felt like walking amongst the gods (Like a fellow MVP told me)!  &lt;p&gt;Basically the sessions are held on the Bellevue Hyatt conference center, or in the Microsoft Campus. All the C# sessions were on the Hyatt. Quite convenient, as I was staying there. But too bad I didn’t had time to go to the Campus. I was there during the Build 2012, and I hope I’ll have the chance to go there again next Summit. Alway nice to visit THE place where everything is created. &lt;p&gt;Most of sessions are NDA, so I can’t tell anything except some BIG things are coming for C# and Windows Phone. Stay tuned for the official announcements.  &lt;p&gt;During the Summit Party, at Century Field, we had chance to network and also do some sport (A healthy mind in a healthy body)  &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7667.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7667.jpg" width="400" height="600"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7706.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7706.jpg" width="400" height="267"&gt;&lt;/a&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Firework @ Century Field&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The Field itself, with the activities&lt;/em&gt; &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7724.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7724.jpg" width="400" height="267"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7741.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7741.jpg" width="400" height="267"&gt;&lt;/a&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Live karaoke&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; In case you didn’t know…MVPs are here!&lt;/em&gt; &lt;p&gt;I would like to say a big hello to some fellas I met over there: Jonathan, Samuel, Kevin, Jason, Joost, Rob, Martine,etc…. You know who you are! And a though also for Loïc who, at the last moment, couldn’t join us. Hope to see you all next year!  &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;More info/photos on the &lt;a href="http://blogs.msdn.com/b/mvpawardprogram/" target="_blank"&gt;official MVP Award blog&lt;/a&gt; or the &lt;a href="http://www.2013mvpsummit.com/" target="_blank"&gt;2013 MVP Summit website&lt;/a&gt; or the &lt;a href="http://www.facebook.com/groups/frogzatmvpsummit2011/" target="_blank"&gt;facebook group of the french speaking MVPs at the Summit&lt;/a&gt;&lt;/p&gt;         &lt;p&gt;I will put more pics/video on mu flickr account later&lt;/p&gt;</description><pubDate>Mon, 04 Mar 2013 20:57:11 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/2013-mvp-summit-2</guid></item><item><title>2013 MVP Summit</title><link>http://www.guruumeditation.net:80/2013-mvp-summit</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;La semaine passée (Du18 au 21février) se tenait, à Redmond et Bellevue le MVP Summit 2013. C’était le 20eme anniversaire du programme, et nous étions environs 1400 MVPs venu des 4 coins du monde. Nous avons eu l’occasion de féliciter des MVP qui faisaient partie de la première fournée. 20 ans comme MVP, ça en jette…&lt;/p&gt; &lt;p align="center"&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7615.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7615.jpg" width="700" height="466"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Qu’est-ce qu’on peut attendre du Summit ? Et bien…Des informations (Bien souvent sous NDA), du networking (avec les PG ou d’autres MVPs) et, tout aussi important, du fun ! Nous avons eu l’occasion d’avoir des échanges intéressants avec les teams. C’est important de pouvoir leur donner du feedback en personne.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7629.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7629.jpg" width="400" height="267"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7634.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7634.jpg" width="400" height="267"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Réception le premier jour&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Le brésil est dans la place !&lt;/em&gt;&lt;/p&gt; &lt;p&gt;C’est vraiment très sympa, de se retrouver avec tous ces MVPs et les teams MS. On se sent près des dieux (comme me l’a dit un autre MVP ;) )!&lt;/p&gt; &lt;p&gt;Les sessions ont mieux au Hyatt Bellevue, ou sur le campus de Microsoft. Toutes mes sessions étaient au Hyatt. Pratique, vu que je logeais là, mais je n’ai donc pas pu aller au Campus. J’y étais déjà pour le Build 2012 mais j’aurai aimé revenir (C’est quand même le centre du monde !). Pour l’année prochaine…&lt;/p&gt; &lt;p&gt;Les plupart des sessions étant NDA, je ne peux rien dire sinon qu’il y a du lourd qui arrive pour VS, C# et Windows Phone. Il n’y a plus qu’à attendre l’annonce officielle.&lt;/p&gt; &lt;p&gt;Pendant la traditionnelle fête, au Century Field, nous avons eu l’occasion de (encore) faire du networking, ainsi qu’un peu de sport (Un esprit sain dans un corps sain)&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7667.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7667.jpg" width="400" height="600"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7706.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7706.jpg" width="400" height="267"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Feux d’artifices @ Century Field&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Le terrain, avec les activités&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7724.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7724.jpg" width="400" height="267"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7741.jpg" target="_blank"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/2013MVPSummit/IMG_7741.jpg" width="400" height="267"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Live karaoke&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Au cas ou vous ne le saviez pas…Les MVPs sont là !&lt;/em&gt;&lt;/p&gt; &lt;p&gt;J’en profite pour faire un petit “hello” à tous ceux que j’ai rencontré au Summit : Jonathan, Samuel, Kevin, Jason, Joost, Rob, Martine,etc…. Vous vous reconnaitrez ! Une pensée aussi pour Loïc qui, au dernier moment, n’a pas pu nous rejoindre.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Plus d’infos/photos sur le &lt;a href="http://blogs.msdn.com/b/mvpawardprogram/" target="_blank"&gt;blog officiel MVP Award&lt;/a&gt; ou sur le site &lt;a href="http://www.2013mvpsummit.com/" target="_blank"&gt;2013 MVP Summit&lt;/a&gt; ou encore &lt;a href="http://www.facebook.com/groups/frogzatmvpsummit2011/" target="_blank"&gt;la page facebook des MVPs francophones au Summit&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Je mettrais plus de photos/vidéos sur mon compte FlickR plus tard.&lt;/p&gt;</description><pubDate>Mon, 04 Mar 2013 20:57:11 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/2013-mvp-summit</guid></item><item><title>Windows Phone authenticated push notifications</title><link>http://www.guruumeditation.net:80/windows-phone-authenticated-push-notifications</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;There are 2 limitation of the basic push notifications on windows phone : &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Limited to 500 notifications per day per subscription (which should be ok for most of us)  &lt;li&gt;Notification is not encrypted&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;If you want to lift those limitations, you need to use authenticated push notifications. &lt;/p&gt; &lt;p&gt;There are 5 steps to follow :&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Buy a certificate  &lt;li&gt;Install the certificate on the server that will send the notifications  &lt;li&gt;Send the certificate to the Windows Phone Dev Center  &lt;li&gt;Register a secure channel (Client side)  &lt;li&gt;Send a secure notification (server side)&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Let’s detail it one by one. (I will use the sample from my &lt;a href="http://www.guruumeditation.net/raw-notifications-on-windows-phone-8" target="_blank"&gt;Raw Notification article&lt;/a&gt; as support, but it can be used with any type of notification)&lt;/p&gt; &lt;h2&gt;Buy a certificate&lt;/h2&gt; &lt;p&gt;You need to buy a certificate from selected vendor. The list is &lt;a href="http://msdn.microsoft.com/en-US/library/gg521150.aspx" target="_blank"&gt;here&lt;/a&gt; (I personally went with GoDaddy). You need to buy from them, as their root certificate are pre-installed on all phones.&lt;/p&gt; &lt;h2&gt;Send the certificate to the Windows Phone Dev Center&lt;/h2&gt; &lt;p&gt;Log in and go to your &lt;strong&gt;dashboard&lt;/strong&gt;. Then go to &lt;strong&gt;Account/Certificate&lt;/strong&gt;. You can upload it there.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated1.png" width="815" height="444"&gt;&lt;/p&gt; &lt;p&gt;Once you uploaded it, it is valid for 4 months. Once you register an app using it, you can link the app to the certificate (When submitting an app, go to &lt;strong&gt;App info&lt;/strong&gt;, expand &lt;strong&gt;More Options&lt;/strong&gt; and you can select your certificate in the &lt;strong&gt;MPNS&lt;/strong&gt; combobox). It will then become permanent.&lt;/p&gt; &lt;h2&gt;Install the certificate on your server&lt;/h2&gt; &lt;p&gt;Launch &lt;strong&gt;MMC&lt;/strong&gt;, go to &lt;strong&gt;File/Add Remove Snap-In&lt;/strong&gt; and add the &lt;strong&gt;Certificate (Local Machine)&lt;/strong&gt; one (It is better to install it machine-wide).&lt;/p&gt; &lt;p&gt;Then in &lt;strong&gt;Personnal/Certificates&lt;/strong&gt;, right click and choose &lt;strong&gt;All Tasks/Import&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;Import the private key with it. I am not totally sure if it is needed, but I made the private key exportable.&lt;/p&gt; &lt;h2&gt;Register a secure channel (Client side)&lt;/h2&gt; &lt;p&gt;That is very simple. When registering the channel, pass a second parameter. This parameter is the CN name of your certificate. Example :&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;channel = new HttpNotificationChannel(_channelName, "www.equinoxe-consulting.net");&lt;/pre&gt;
&lt;p&gt;Now your notification channel should start with HTTPS and have “unthrottled” in it.&lt;/p&gt;
&lt;h2&gt;Send a secure notification (Server side)&lt;/h2&gt;
&lt;p&gt;It is the same as sending a notification except you send the certificate (with its private key) with the notification request.&lt;/p&gt;
&lt;p&gt;Example getting the certificate from the store &lt;/p&gt;&lt;pre class="brush: csharp;"&gt;var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
&lt;/pre&gt;&lt;pre class="brush: csharp;"&gt;// Change with your certificate thumbprint
var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, "F8132A5AAB52469A0B8962FE1E01E2CB0AB64137", false)[0];

store.Close();&lt;/pre&gt;
&lt;p&gt;Once you have it, you send it with the request using the method &lt;strong&gt;ClientsCertificates.Add()&lt;/strong&gt; :&lt;/p&gt;&lt;pre class="brush: csharp;"&gt; var sendNotificationRequest = (HttpWebRequest)WebRequest.Create(uri);

sendNotificationRequest.Method = "POST";

// add the certificate
sendNotificationRequest.ClientCertificates.Add(certificate);

// Set the notification payload to send.
var notificationMessage = Encoding.Default.GetBytes(rawMessage);

// Set the web request content length.
sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers.Add("X-NotificationClass", "3");


using (var requestStream = sendNotificationRequest.GetRequestStream())
{   
   requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}

// Send the notification and get the response.
var response = (HttpWebResponse)sendNotificationRequest.GetResponse();&lt;/pre&gt;
&lt;p&gt;And it’s done! The client should receive a notification. And since the channel uri is using HTTPS and has “unthrottled” in it, it is a secure one.&lt;/p&gt;
&lt;h2&gt;Troubleshouting&lt;/h2&gt;
&lt;p&gt;I spent lot of time on a stupid thing.&lt;/p&gt;
&lt;p&gt;When I tried to send the notification request from the server, I had an HTTPRequestException:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;The request was aborted: Could not create SSL/TLS secure channel&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not much information…So I checked in the Windows Event Viewer and I saw this :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated2.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Lucida Console"&gt;&lt;strong&gt;Have error in event viewer schannel, event id 36888 the following fatal alert was generated 80. the internal error state is 301&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;OK…are we getting closer ?&lt;/p&gt;
&lt;p&gt;After some time I realized that, in debug, when I tried to get the certificate private key with the PrivateKey property I got a &lt;code&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;strong&gt;System.Security.Cryptography.CryptographicException &lt;/strong&gt;&lt;font face="Segoe UI"&gt;with a message saying that the provider is not correct.&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;That is where I though about the security permissions…&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;There is a nice util where you can check/modify the permissions on the certificates : &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=19801" target="_blank"&gt;WinHTTPCertCfg&lt;/a&gt;&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;You can check the permissions that way (in an admin command line) :&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml;"&gt;WinHttpCertCfg.exe -l -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net"&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;Then I got this :&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated3.png"&gt;&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;The user my web service was using (.NET v4.5) has no right on the certificate. To add it :&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml;"&gt;WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net" -a ".NET v4.5"&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;And then everything went ok…&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;I made a sample app (well it is the authenticated version of the Raw Notification sample) &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/WP8SecureRawNotifications.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;As with the original sample, you have to change the WCF service IP with your own on the client app and let the emulator connect to your host (check &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105).aspx" target="_blank"&gt;here&lt;/a&gt;). You also have to change the certificate CN and Thumbprint with your own.&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;&lt;/font&gt;&lt;/code&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;font face="Segoe UI"&gt;&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;</description><pubDate>Thu, 07 Feb 2013 14:38:26 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/windows-phone-authenticated-push-notifications</guid></item><item><title>Windows Phone notifications push authentifiées</title><link>http://www.guruumeditation.net:80/windows-phone-notifications-push-authentifiees</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Les notifications push de Windows Phone ont deux grandes limitations :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Maximum 500 notifications par jour par souscription (Ce qui, en g&amp;eacute;n&amp;eacute;ral, est suffisant)&lt;/li&gt;
&lt;li&gt;Les notifications ne sont pas encrypt&amp;eacute;es&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pour supprimer ces limitations, il faut passer aux notifications push authentifi&amp;eacute;es.&lt;/p&gt;
&lt;p&gt;Pour y arriver, il y a 5 &amp;eacute;tapes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Acheter un certificat&lt;/li&gt;
&lt;li&gt;Installer le certificat sur le serveur qui va envoyer les notifications&lt;/li&gt;
&lt;li&gt;Installer le certificat sur son compte dans le Windows Phone Dev Center&lt;/li&gt;
&lt;li&gt;Registrer un channel s&amp;eacute;curis&amp;eacute; (C&amp;ocirc;t&amp;eacute; client)&lt;/li&gt;
&lt;li&gt;Envoyer une notification s&amp;eacute;curis&amp;eacute;e (C&amp;ocirc;t&amp;eacute; serveur)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Voyons &amp;ccedil;a en d&amp;eacute;tail. (Je vais utiliser mon article pr&amp;eacute;c&amp;eacute;dent sur les &lt;a href="http://www.guruumeditation.net/raw-notifications-sur-windows-phone-8" target="_blank"&gt;notifications raw&lt;/a&gt; comme support, mais c&amp;rsquo;est valable pour tous types de notifications)&lt;/p&gt;
&lt;h2&gt;Acheter un certificat&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Vous devez acheter un certificat chez un vendeur dont le certificat root est pr&amp;eacute;install&amp;eacute; par d&amp;eacute;faut sur tous les Windows Phone. La liste est &lt;a href="http://msdn.microsoft.com/en-US/library/gg521150.aspx"&gt;ici&lt;/a&gt;. (Perso je suis chez GoDaddy).&lt;/p&gt;
&lt;h2&gt;Installer le certificat sur le Windows Phone Dev Center&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Dans le Dev Center, allez sur votre &lt;b&gt;dashboard&lt;/b&gt;. Apr&amp;egrave;s, il faut aller sur &lt;b&gt;Account/Certificate&lt;/b&gt;. Vous pouvez alors uploader le certificat.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated1.png" width="815" height="444" /&gt;&lt;/p&gt;
&lt;p&gt;Une fois upload&amp;eacute;, le certificat est valide pour 4 mois. Une fois que vous avez soumis une application qui utilise ce certificat, celui-ci devient valide ind&amp;eacute;finiment. Pour lier une app &amp;agrave; un certificat, quand vous soumettez l&amp;rsquo;app, allez dans &lt;b&gt;App info&lt;/b&gt; et, dans la partie &lt;b&gt;More Options&lt;/b&gt; vous pouvez s&amp;eacute;lectionner le certificat dans le combobox &lt;b&gt;MPNS.&lt;/b&gt;&lt;/p&gt;
&lt;h2&gt;Installer le certificate sur votre serveur&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Lancer &lt;b&gt;MMC&lt;/b&gt;, puis &lt;b&gt;File/Add Remove Snap-In&lt;/b&gt; et ajouter &lt;b&gt;Certificate (Local Machine)&lt;/b&gt;&amp;nbsp; (Il vaut mieux installer le certificat dans le magasin machine que dans celui de l&amp;rsquo;utilisateur)&lt;/p&gt;
&lt;p&gt;Apr&amp;egrave;s dans &lt;b&gt;Personnal/Certificates&lt;/b&gt;, clique droit et choisir&amp;nbsp; &lt;b&gt;All Tasks/Import&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Importer la cl&amp;eacute; priv&amp;eacute;e avec. Je ne suis pas s&amp;ucirc;r que ce soit n&amp;eacute;cessaire, mais j&amp;rsquo;ai aussi s&amp;eacute;lectionn&amp;eacute; &amp;laquo; rendre la cl&amp;eacute; exportable &amp;raquo;.&lt;/p&gt;
&lt;h2&gt;Registrer un channel s&amp;eacute;curis&amp;eacute; (C&amp;ocirc;t&amp;eacute; client)&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Simple. Il suffit, lors de la cr&amp;eacute;ation du channel, de passer le param&amp;egrave;tre CN du certificat. Exemple :&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;That is very simple. When registering the channel, pass a second parameter. This parameter is the CN name of your certificate. Example :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;channel = new HttpNotificationChannel(_channelName, "www.equinoxe-consulting.net");&lt;/pre&gt;
&lt;p&gt;L&amp;rsquo;URI du channel devrait commencer par HTTPS et avoir &amp;ldquo;unthrottled&amp;rdquo; dedans.&lt;/p&gt;
&lt;h2&gt;Envoyer une notification s&amp;eacute;curis&amp;eacute;e (C&amp;ocirc;t&amp;eacute; serveur)&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En gros, c&amp;rsquo;est la m&amp;ecirc;me chose que l&amp;rsquo;envoi d&amp;rsquo;une notification &amp;ldquo;normale&amp;rdquo;, except&amp;eacute; qu&amp;rsquo;il faut envoyer le certificat (avec sa cl&amp;eacute; priv&amp;eacute;e) avec la requ&amp;ecirc;te.&lt;/p&gt;
&lt;p&gt;Un exemple de r&amp;eacute;cup&amp;eacute;ration du certificat :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
&lt;/pre&gt;
&lt;pre class="brush: csharp;"&gt;// Change with your certificate thumbprint
var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, "F8132A5AAB52469A0B8962FE1E01E2CB0AB64137", false)[0];

store.Close();&lt;/pre&gt;
&lt;p&gt;Une fois que vous l&amp;rsquo;avez, il faut l&amp;rsquo;envoyer avec la requ&amp;ecirc;te au moyen de la m&amp;eacute;thode &lt;b&gt;ClientsCertificates.Add()&lt;/b&gt; :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt; var sendNotificationRequest = (HttpWebRequest)WebRequest.Create(uri);

sendNotificationRequest.Method = "POST";

// add the certificate
sendNotificationRequest.ClientCertificates.Add(certificate);

// Set the notification payload to send.
var notificationMessage = Encoding.Default.GetBytes(rawMessage);

// Set the web request content length.
sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers.Add("X-NotificationClass", "3");


using (var requestStream = sendNotificationRequest.GetRequestStream())
{   
   requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}

// Send the notification and get the response.
var response = (HttpWebResponse)sendNotificationRequest.GetResponse();&lt;/pre&gt;
&lt;p&gt;C&amp;rsquo;est fait! Le client doit recevoir la notification. Et, si le channel commence bien par HTTPS, c&amp;rsquo;est qu&amp;rsquo;il est bien s&amp;eacute;curis&amp;eacute;.&lt;/p&gt;
&lt;h2&gt;Un probl&amp;egrave;me possible&amp;hellip;&lt;/h2&gt;
&lt;p&gt;J&amp;rsquo;ai pass&amp;eacute; pas mal de temps sur un truc stupide.&lt;/p&gt;
&lt;p&gt;Quand j&amp;rsquo;essayais d&amp;rsquo;envoyer une requ&amp;ecirc;te, j&amp;rsquo;obtenais une HTTPRequestException:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;strong&gt;The request was aborted: Could not create SSL/TLS secure channel&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pas super parlant&amp;hellip;J&amp;rsquo;ouvre le Event Viewer et je vois ceci :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated2.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'Lucida Console';" face="Lucida Console"&gt;&lt;strong&gt;Have error in event viewer schannel, event id 36888 the following fatal alert was generated 80. the internal error state is 301&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;OK&amp;hellip;mais encore ?&lt;/p&gt;
&lt;p&gt;Apr&amp;egrave;s avoir cherch&amp;eacute; en vain, j&amp;rsquo;ai remarqu&amp;eacute; que, en d&amp;eacute;bug, quand j&amp;rsquo;essayais de voir la cl&amp;eacute; priv&amp;eacute;e du certificat j&amp;rsquo;avais :&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;strong&gt;System.Security.Cryptography.CryptographicException &lt;/strong&gt;&lt;span style="font-family: 'Segoe UI';" face="Segoe UI"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;avec un message disant que le provider n&amp;rsquo;est pas correct&amp;hellip;&lt;/p&gt;
&lt;p&gt;Soudainement j&amp;rsquo;ai pens&amp;eacute; aux permissions (oui, aucun rapport avec un provider&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Il y a un outil pratique pour voir/modifier les permissions sur les certificats : &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=19801"&gt;WinHTTPCertCfg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez voir les permissions avec (En ligne de commande administrateur) :&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;WinHttpCertCfg.exe -l -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net"&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;span style="font-family: 'Segoe UI';" face="Segoe UI"&gt;R&amp;eacute;sultat :&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style="font-family: 'Segoe UI';" face="Segoe UI"&gt;&lt;img src="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/Authenticated3.png" /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Le compte utilise par le web service (.NET v4.5) n&amp;rsquo;a pas de droit d&amp;rsquo;acc&amp;eacute;der &amp;agrave; la cl&amp;eacute; priv&amp;eacute;e. Pour ajouter ce droit :&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net" -a ".NET v4.5"&lt;/pre&gt;
&lt;p&gt;Et voil&amp;agrave; comment perdre une matin&amp;eacute;e&amp;hellip;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai fait une application exemple (En fait juste une version modifi&amp;eacute;e de mon exemple Raw Notification) &lt;a href="http://www.guruumeditation.net/Media/Default/Blog/WP8RawNotificationsAuthenticated/WP8SecureRawNotifications.zip"&gt;ici&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comme pour la version originale, il faut changer l&amp;rsquo;adresse IP du service par celui de votre serveur, et laisser l&amp;rsquo;&amp;eacute;mulateur se connecter &amp;agrave; votre serveur (Voir &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105).aspx"&gt;ici&lt;/a&gt;) Il faut en plus changer le nom CN et le Thumbprint du certificat par le v&amp;ocirc;tre.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description><pubDate>Thu, 07 Feb 2013 14:38:26 GMT</pubDate><guid isPermaLink="true">http://www.guruumeditation.net:80/windows-phone-notifications-push-authentifiees</guid></item></channel></rss>