[Code] Saving an Image as Transient Data

October 3, 2010

If you’ve been developing Windows Phone 7 applications, you’re probably aware of tombstoning and information that should be handled during this process. An important factor is the storing of data to provide a seamless experience and give the illusion that the app has always been running. This data is commonly known as transient data and is essentially information that will not persist outside the app’s life cycle. A useful example of transient data could be that of a user filling out a form and completing various textboxes. The app is then tombstoned and the user eventually returns to the app by pressing the ‘back’ button. By default, when the application is reloaded, the textboxes will be empty since a new instance is created. To provide the illusion that the same instance is running, and to improve the user experience, the app should refill all the data that had been entered prior to the tombstoning. That data should be stored in the PhoneApplicationPage.State property.

This property does have a limit of 2MB per page and 4mb for the whole application, so it’s best to store items only when needed. It is also important to remember that this property can only be accessed within the OnNavigatedTo and OnNavigatedFrom methods. To find out more on using the State property and storing transient data, you can read the tutorials on Application Life-Cycle found in the Windows Phone 7 Training Kit (RTM Refresh) and check out the MSDN ‘How to’ documentation. On a side note, the alternative to transient data is persistent data and is information that will be required between app life cycles such as user settings, saved game information, app data etc… For WP7 development, persistent data should be stored in the app’s Isolated Storage or on a remote server.

The problem

In an application I’m working on, I need to save an image as transient data. Seeing as the State property accepts type object as it’s value, I tried to directly pass the image stream to see what would happen. Turns out, when base.OnNavigatedFrom(e) got called, three exceptions were thrown:

A first chance exception of type 'System.Security.SecurityException' occurred in System.Runtime.Serialization.dll A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll A first chance exception of type 'System.Security.SecurityException' occurred in System.Runtime.Serialization.dll

In release mode this resulted in the navigation stack becoming corrupted and therefore the user was unable to press the ‘back’ button to return to the app after it had been tombstoned. Drilling in a little deeper, it seemed that Visual Studio would catch this in the Application_UnhandledException event handler. The stacktrace provided by the exception object was:

at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode) at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serial

At the removal of the image stream, this exception was never thrown so it seems that there is a serialization problem when directly providing a stream.

A solution

If the Stream format was causing a problem, I thought a better way would to simply pass in a byte array. Bytes are serializable and easy to work with, so the following code demonstrates how to convert the image stream into a byte array.