WP7 App on WP8 Breaking Changes – Part 1 – WebRequest’s Referer Changes

Well, after testing a WP7 app running on WP8 guess what happened…It worked differently on WP8.
The issue as described was : Almost all of the thumbnails stopped showing when the user was logged in.

That was an interesting one. It was obvious it was an MS bug (check out the other one I discovered as well here).

Btw let me say that the MS guys have done an amazing job with WP8! They worked really hard to make the deadlines and try to keep that huge promise that all WP7 apps would automagically run as-is on WP8. Huge effort from their part.

Time to relax back and do some bug-hunting ūüôā

Thumbnails mean WebRequests. The ones that failed were shown by setting the UriSource on a BitmapImage. We need to go ask the BitmapImage what goes wrong with the requests when running inside a WP8 device. So lets setup fiddler so we can check the traffic. Note that my PC and the WP8 device were connected to the same Wifi network.

Below you can see how to setup the proxy on the phone’s wifi connection (tap on it for settings).

Great. Now I was able to compare the requests made from a WP7 and WP8 device.

Long story short, I was able to pinpoint the issue and it had to do with the fact that

On WP8 MS changed the way they handle/send Referer headers in WebRequests for both  BitmapImage and WebClient

Why my problem occurred : As it turns out the thumbnail requests, once logged in, are authenticated and in that case the server uses the Referer in order to authenticate the request. If the referer is different than the one you used to log in (through a WebClient) the request will fail. So when a WP7 app runs in WP7 device both the BitmapImage and the WebClient send the identical referer (Applications/Installl) but when a WP7 app is running on WP8 then BitmapImage sends a different Referer than what the WebClient sent to the server while authenticating resulting in all thumbnails to fail.

Lets setup a small test case to highlight and visualize the issue.

Here is the test we are going to run :

We are going to try it in 3 scenarios so we can see the results. The scenarios are :

  1. A WP7 app running on WP7
  2. A WP7 app running on WP8
  3. A WP8 app running on WP8

And now here are the results in order :

WP7 app running on WP7

Figure 1 : BitmapImage request (WP7 on WP7)

Figure 2 : WebClient request (WP7 on WP7)

WP7 app running on WP8
WP7AppOnWP8_BitmapImage_Req_PROBLEM

Figure 3 : BitmapImage request (WP7 on WP8) changed!

WP7AppOnWP8_WebClient_Req

Figure 4 : WebClient request (WP7 on WP8) as normal

WP8 app running on WP8
WP8AppOnWP8_BitmapImage_Req

Figure 5 : BitmapImage request (WP8 on WP8)

Figure 6 : WebClient request (WP8 on WP8).

The problem should be really obvious by now.

Concern #1 : I pretty much can’t do anything to workaround this issue. Changing the whole app to manually download all thumbnails is not an option.

Concern #2 : what should we do from now on WP8 for new Apps as far as Referer’s are concerned?

Do we need to use Data/Programs from now on?
Does that mean that for new apps on WP8 we will have to now manually inject the Referer ourselves on all webrequests? And so on…

I have create a forum thread on Microsoft’s WP forums on the issue here

OrientationHelper for Windows Phone and Windows 8

This is a small utility to help with WP7,WP8 and Windows Store app development where there is a need to design your UX in order to support multiple screen sizes and orientations.
(Phew i almost said Metro Style..Wait..Damn it)

It is inspired by ‘LayoutAwarePage’ , an utility class included in the templates for Windows Store Apps.

On the Windows Phone side there are 6 orientation states:

  • Landscape
  • LandscapeLeft
  • LandscapeRight
  • Portrait
  • PortraitUp
  • PortraitDown

On the Windows Store side there are 4 view states :

  • Filled
  • Snapped
  • FullScreenLandscape
  • FullScreenPortrait

Before we go into details here is an example of the utility working on the Phone in Portrait mode :
On the left side we have setup our utility to automatically run some arbitrary scale animations ,defined in XAML, based¬†on the current Orientation or ViewState. There’s nothing sophisticated in the screenshots below. Simply showing off the functionality.

Here you can see another one automatically running on the left side in Landscape mode.

Similarly on the Windows 8 side:

(FullScreenPortrait)

(FullScreenLandscape)

(Filled)

(Snapped)

What the designer needs to do is describe the UI (Xaml) for all screens and for all possible orientations/view states in order to provide a good UX. There is no clear pattern/guidelines on how this should be done although¬†LayoutAwarePage gives us a good ‘clean’ solution by taking advantage of a well known proven XAML solution¬†called the VisualStateManager. We are, after all, trying to tackle switching between multiple visual states so VisualStateManager¬†sounds like a natural fit. And it is.

The basic idea is , similar to creating Custom Controls, to declare all views for all supported orientations/view states inside the same XAML file (what if the UI is composite though?) and use VisualStates, one for each specific orientation/view state, to¬†describe the UI changes needed to transition between View designs. We will then let VisualStateManager¬†do it’s work by asking it programmatically to switch between states when the platform notifies us of a change¬†in orientation/view state.

What the developer needs to do is manually listen for orientation/view state changes for all visible screens
and call VisualStateManager to transition the current screen to the current view state.

This programmatic part of the developer seems like a lot of manual work that could be done automatically.
There’s gonna be a lot of code-behind spread around listening for the same event and dealing manually
with VisualState changing (or manually enabling/disabling controls, running animations etc etc if we didnt
use VisualStateManager)
Unfortunately no one can help the poor designer (developer?) that has to rewrite/redesign the whole UI
again and again. It has to happen.

LayoutAwarePage solves it by creating a Page base class for Metro style apps.
This utility is instead an attached property and supports Pages, user controls and custom controls. Haven’t made a sample with custom controls¬†but it should be the same as user controls.
What if though i want to create a reusable custom control/user control and i want to have IT define how it should look on different orientations/view states instead of forcing the consumer/user of the control to do it.
Sometimes ,me as a user of a control, might need to tweak more stuff “inside” the control to make it look right. Lets say for example that i have a control that defines two¬†buttons side by side ,stretched,¬†that fill my Landscape view across nicely. I would have liked if the control itself switched them to be stacked (one on top of the other) when in Portrait mode. I can’t do that though unless the control supported that. Note that it would be best if the control supported that but didn’t enforce it.I the user would like to have control over when and if the control is allowed to auto-adapt by itself or i will solve it outside or the control. The utility supports this scenario by letting me decide whether or not to set the attached property OrientationHelper.IsActive on the control that enables it’s orientation/view state support if of course the control has defined the¬†appropriate¬†VisualStates.

The solution seemed transferable to Windows Phone as well and so the utility comes in 3 assemblies supporting WP7/WP8/WIN8.

What we need to do in order to use it is
1) set the attached property OrientationHelper.IsActive=”true” on a Page, UserControl or CustomControl
2) Define one VisualStateGroup on the orientation-aware control named “PageOrientationStates” for WP
and “ApplicationViewStates” for Win8.
3) Define one VisualState for each supported Orientation/ViewState. The VisualState name should match exactly the name of the¬†Orientation/ViewState. For example i would name “Filled” the VisualState that is meant¬†to design my UI when in Filled state.

Setting the attached property :
In this case the UserControl set’s it for demo purposes .It’s overridable.

Defining the VisualStates (For Win8) :

Quick tip : VisualStateGroups and VisualStateManager , i found, work *only* when defined/attached on the
RootElement of your Page or UserControl. Which means it wont work if you declare a control inside a Page, declare VisualStates on it and try to call VSM on that specific control.

Here’s the code for the OrientationHelper.

using System;
using System.Collections.Generic;
using System.Linq;

#if WINDOWS_PHONE
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Orientation = Microsoft.Phone.Controls.PageOrientation;
#else
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Orientation = Windows.UI.ViewManagement.ApplicationViewState;
#endif

namespace OrientationHelper
{
    public static class OrientationHelper
    {
#if WINDOWS_PHONE
        private const String VisualStateGroupName = "PageOrientationStates";
#else
        private const String VisualStateGroupName = "ApplicationViewStates";
#endif

        #region IsActive DP

        public static readonly DependencyProperty IsActiveProperty =
            DependencyProperty.RegisterAttached("IsActive", typeof (bool), typeof (OrientationHelper),
                                                new PropertyMetadata(default(bool), OnIsActivePropertyChanged));

        public static void SetIsActive(UIElement element, bool value)
        {
            element.SetValue(IsActiveProperty, value);
        }

        public static bool GetIsActive(UIElement element)
        {
            return (bool) element.GetValue(IsActiveProperty);
        }

        private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as Control;
            if (control == null)
                return;

            SetupOrientationAwareControl(control, (bool)e.NewValue);

#if WINDOWS_PHONE
            //The control itself can be a page.In every case we need to retry until the containing page is loaded.
            control.Loaded += OnControlLoaded;
#endif

        }

        #endregion

#if WINDOWS_PHONE
        //Note: On the phone side Orientation is Page-specific so we keep the orientation aware controls
        //on the page itself using a Dependency Property
        #region OrientationAwareControls Private DP

        private static readonly DependencyProperty OrientationAwareControlsProperty =
            DependencyProperty.RegisterAttached("OrientationAwareControls", typeof (IList),
                                                typeof (OrientationHelper), null);

        private static void SetOrientationAwareControls(DependencyObject element, IList value)
        {
            element.SetValue(OrientationAwareControlsProperty, value);
        }

        private static IList GetOrientationAwareControls(DependencyObject element)
        {
            return (IList) element.GetValue(OrientationAwareControlsProperty);
        }

        #endregion
#else
        //Note: On the Windows 8 side Orientation is global
        private static IList<WeakReference> orientationAwareControls;
#endif

        private static void SetupOrientationAwareControl(Control control, bool isActive)
        {
#if WINDOWS_PHONE
            var page = FindParentPage(control);
            if (page == null)
                return;
            if (isActive)
            {
                //Add the orientation aware control to the list stored on the Page
                if (GetOrientationAwareControls(page) == null)
                {
                    SetOrientationAwareControls(page, new List());
                    //Start listening for changes
                    page.OrientationChanged += PageOnOrientationChanged;
                }
                if (!GetOrientationAwareControls(page).Contains(control))
                    GetOrientationAwareControls(page).Add(control);
                UpdateOrientationAwareControls(new[] { control }, page.Orientation); //Update this control only

            }
            else
            {
                var orientationAwareControls = GetOrientationAwareControls(page);
                if (orientationAwareControls != null)
                {
                    if (orientationAwareControls.Contains(control))
                    {
                        orientationAwareControls.Remove(control);
                        control.Loaded -= OnControlLoaded;
                    }
                    //Do cleanup for this page if there are no more controls
                    if (!orientationAwareControls.Any())
                    {
                        SetOrientationAwareControls(page, null);
                        page.OrientationChanged -= PageOnOrientationChanged;
                    }
                }
            }
#else
            if (isActive)
            {
                if (orientationAwareControls == null)
                    orientationAwareControls = new List();

                if (!GetOrientationAwareControls().Contains(control))
                {
                    orientationAwareControls.Add(new WeakReference(control));
                    // Note: On the Windows 8 side, probably due to aggressive optimizations,
                    // if the control is not named then when changing orientations/view states any
                    // WeakReference to that control will show it as GCed!
                    // Disclaimer : I ONLY TESTED ON THE SIMULATOR!!
                    if (string.IsNullOrEmpty(control.Name))
                    {
                        control.Name = Guid.NewGuid().ToString();
                    }
                    control.Loaded += OnControlLoaded;

                    if (control.Parent != null)
                    {
                        UpdateOrientationAwareControls(new[] { control }, ApplicationView.Value);
                    }
                }
                if (GetOrientationAwareControls().Any())
                {
                    //TODO: Handle Window changes (Closed)
                    Window.Current.SizeChanged += OnWindowSizeChanged;
                }

            }
            else
            {
                if (GetOrientationAwareControls().Contains(control))
                {
                    var controlWeakRef = orientationAwareControls.Single(weak => control.Equals(weak.Target));
                    orientationAwareControls.Remove(controlWeakRef);
                    control.Loaded -= OnControlLoaded;
                }
                if (!GetOrientationAwareControls().Any())
                {
                    orientationAwareControls = null;
                    Window.Current.SizeChanged -= OnWindowSizeChanged;
                }
            }
#endif
        }

        private static void OnControlLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            var control = sender as Control;
#if WINDOWS_PHONE
            SetupOrientationAwareControl(control, GetIsActive(control));
#else
            UpdateOrientationAwareControls(new[] { control }, ApplicationView.Value);
#endif
        }

#if WINDOWS_PHONE

        private static PhoneApplicationPage FindParentPage(FrameworkElement el)
        {
            FrameworkElement parent = el;
            while(parent != null)
            {
                if (parent is PhoneApplicationPage)
                    return parent as PhoneApplicationPage;
                parent = parent.Parent as FrameworkElement;
            }
            return null;
        }

        private static void PageOnOrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            var page = sender as PhoneApplicationPage;
            UpdateOrientationAwareControls(GetOrientationAwareControls(page), page.Orientation); //Update all controls
        }
#else
        private static void OnWindowSizeChanged(object sender, WindowSizeChangedEventArgs windowSizeChangedEventArgs)
        {
            UpdateOrientationAwareControls(GetOrientationAwareControls(), ApplicationView.Value);
        }
        private static IEnumerable<Control> GetOrientationAwareControls()
        {
            if(orientationAwareControls == null || !orientationAwareControls.Any())
                return Enumerable.Empty();

            IList<Control> aliveControls = new List<Control>();
            foreach (var controlWeakRef in orientationAwareControls.ToList())
            {
                if (controlWeakRef.IsAlive)
                    aliveControls.Add(controlWeakRef.Target as Control);
                else
                    orientationAwareControls.Remove(controlWeakRef);
            }
            return aliveControls;
        }
#endif

        private static void UpdateOrientationAwareControls(IEnumerable controls, Orientation orientation)
        {
            if (controls == null || !controls.Any())
                return;

            foreach (var control in controls)
            {
                VisualStateManager.GoToState(control, GetVisualStateName(orientation), true);
            }
        }

        private static String GetVisualStateName(Orientation orientation)
        {
            return orientation.ToString();
        }
    }
}

Here’s the whole solution : OrientationHelper.zip

Feel free to comment if you found it useful or found any issue.

Au revoir

A .NET Dev’s baby steps trying to share native code between Win8 and WP8

This is a walkthrough of what i had to do to setup native code sharing between Windows 8 and Windows Phone 8 (using the leaked WP8 SDK). My knowledge of the native world is quite limited and there might be other better ways of doing it. Feel free to comment if you know more about the subject and help out this poor .NET dev ūüôā

First we create our Native C++ WinRT Component :

Add New Windows Runtime Component Project

Then we create our Native C++ Phone Runtime Component :

Next we delete from both projects the autogenerated files. From the WinRT project delete the files named Class1.cpp and Class1.h and from the PhoneRT project delete the files named NativeSharedPhoneRT.cpp and NativeSharedPhoneRT.h.

What we need next is a simple class that we will want to share between the two projects. Lets call it MySharedClass. We will create it only on the WinRT side and we will link to it from the PhoneRT side.

I am expecting that i can use preprocessor flags in the same manner that we used to do between Silvelight/WPF and Windows Phone. So the next question is “how do i define my preprocessor directives in C++ projects”?
These simple steps worked for me :

  1. Open the properties of the NativeSharedWinRT project and go to “Configuration Properties -> C/C++ -> Command Line
  2. Enter “/D “_WinRT”” (without the outside quotes) in ¬†“Additional Options” and click Apply.

Screenshot below :

(Note: the only reason i named the directive with an underscore is because the debug directive in one of the templates was named _DEBUG.Thought it might be a convention or something)
As¬†jalfdjalf¬†pointed out directives starting with underscores are reserved (makes sense) so its OK to name our own as we¬†wish (i.e PhoneRT, WinRT).Btw i used PhoneRT instead of the more “official” WinPRT for the phone because its¬†a lot more¬†distinguishable¬†from WinRT.

Do the same thing for the NativeSharedPhoneRT project but add this “/D “_PhoneRT”” ¬†instead in the Additonal Options.
Great. Now we have setup our preprocessor directives for both our shared projects. Time to create the shared class. Go to the NativeSharedWinRT project and add an empty MySharedClass.cpp file and an empty MySharedClass.h file. Then go to the NativeSharedPhoneRT project, click “Add existing item” and navigate inside the NativeSharedWinRT folder to locate the newly created files and select those. These files are now linked and the project structure should look like this :

(Note: I tried linking the pch.cpp and pch.h files as well but VS and the compiler didnt like that for
some reason so i kept them unlinked in order to move one)

Ok so far. Now lets add code to our shared class and see how we can start sharing.
Below is only a screenshot of what the code inside our files should be but you will be able to
download the source code and copy paste directly (see download link at end of post).

Notice how opening the header file from inside the WinRT project that the _WinRT directive is active but not the _PhoneRT one just as we wanted. SharedMethodAsync is a WinRT-Style asynchronous method exposed to both WinRT and PhoneRT.

I had planned to also show off how projections worked in the WinRT world but i couldn’t get it to work easily.The plan was to expose a WinRT type like IMap or IIterable and see how they¬†show up projected in C#.

Here is our .cpp file (opened from inside the NativeSharedPhoneRT project) :

Now its time to create our C# clients (one for WinRT and one for PhoneRT) that will consume our shared native libraries.
First is the WinRT C# Client :

Once created click “Add Reference” on it and select the NativeSharedWinRT project.

Big pause here! Can you say “where’s my P/Invoke dude?” ¬†ūüôā
Now that’s what i call¬†seamless.
Small note.Never forget that the interop cost is ALWAYS there when going back and forth from native <-> managed.Keep in mind that usually there is an interop cost when going native <-> managed and
that applies to WinRT as well although Microsoft has done a lot of work to minimize it.

Then is our PhoneRT C# Client :

Once created click “Add Reference” on it and select the NativeSharedPhoneRT project.

This is how the project structure should look now :

Finally lets see what the code looks like from both client projects.
This is what we get from the Phone Client :

and here is what we get from the Win8 Client :

And that’s it! That was certainly fun ūüôā

Source code for this post is here