There’s two ways to use storage in Windows Phone 8 apps:
- Isolated Storage
- Windows.Storage
So which one should you use? My recommendation: Windows.Storage.And why? Because Isolated Storage isn’t thread safe.
When the app is small and there’s no 3rd party libraries, you can create a wrapper over the Isolated Storage which uses locking to make sure that only one thread can access the Isolated Storage. But as soon as you add a third party library, you’ll lose control: If the library uses Isolated Storage, it will bypass the locking mechanism you have created inside your storage wrapper.
So, in order to save yourself from random exceptions and strange data losses, prefer Windows.Storage over Isolated Storage.
Sometimes when you try to debug a Windows Phone app through emulator with Visual Studio, you may encounter the following error:
A specified communication resource (port) is already in use by another application

One possible reason for this is that Visual Studio tries to debug an app which isn’t deployedto the emulator.
For example, if you set the startup project like this:

And then through Visual Studio’s Configuration Manager you don’t check the “Deploy” for this particular project:

You will get the error when launching the debugger.
There’s multiple ways to pass data between pages in Windows Phone apps. Most frequently used ways include:
- Query strings
- Application state
- Static properties in App.xaml.cs
One alternative, which I haven’t seen discussed that much, is Application.Resources. Using Application.Resources has these benefits:
- You can store almost anything in there, including complex objects (List<Customer> etc.)
- Application.Resources can be accessed from anywhere. You can split the app into multiple assemblies and all these can access Application.Resources.
- It’s easy to use
Usage
The simple “pattern” for using Application.Resources to pass data between pages looks like this:
- Call Application.Current.Resources.Add (mydata, “mykey”) to add the data
- Navigate to an another page
- Call Application.Current.Resources[“mykey”] to retrieve the data
Example
Store the data before navigation:
var customers = GetCustomers();
Application.Current.Resources.Add("NavigationParam", customers);
NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
Retrieve the data after navigation:
var customers = (List<Customer>) Application.Current.Resources["NavigationParam"];
Helper
This process can be made even easier with a simple helper. With it, you could write the following code to store the data:
var customers = GetCustomers();
ParameterHelper.Store(customers);
And the following code to retrieve it:
var customers = ParameterHelper.Get<List<Customer>>();
Notes
- The data is lost if the application is tombstoned.
- If there already exists data in Application.Resources with key “NavigationParam” and you try to add new data with the same key, an exception is thrown. Always remember to remove the existing data.
Example project
An example project (which includes the ParameterHelper) is available from GitHub (folder windows-phone-application-resources-navigation).
Portable Class Libraries are a great way to share common code between different platforms. But here lies the danger: A portable class library project cannot change the underlying platform.
Here’s a simple explanation of what that means.
Example project
The example application is built for Windows Forms, Windows RT and Windows Phone. The authentication mechanism is identical in every app so that is placed in a Portable Class Library project:
public class WebTool
{
public async Task<string> GetAuthenticationKey()
{
var cookieContainer = new CookieContainer();
var client = new HttpClient(new HttpClientHandler() { CookieContainer = cookieContainer });
// Authenticate with the service
await client.GetStringAsync("http://cookietest.api.domain.com/cookie/get");
// Return the received cookie as authentication key
var cookieHeader = cookieContainer.GetCookieHeader(new Uri("http://cookietest.api.domain.com/"));
return cookieHeader;
}
}
Using this library doesn’t get easier: Each platform can call it with identical code:
var webTool = new WebTool();
var result = await webTool.GetAuthenticationKey();
if (string.IsNullOrWhiteSpace(result))
this.Result.Text = "Didn't receive authentication key!";
else
this.Result.Text = "Authentication key: " + result;
Few minutes and everything is done, so the testing phase begins.
First, Windows Forms:

Then Windows 8:

And last but not least, Windows Phone:

Uh oh.
Cookies and CookieContainer especially are different beasts in different platforms. Portable Class Library cannot hide that fact.
Have you encountered similar issues when dealing with Portable Class Library projects?
No matter what I did, one Windows Phone 7 app always gave the following error when I tried to play some videos with it using the Microsoft Media Platform:
3100 An error has occurred.
What was worse, the same code and the same video worked in an another app.
Turns out, the reason was simple: Capabilities. In particular, the app was missing ID_CAP_MEDIALIBcapability.