Tuesday, December 14, 2010

Chrysalis – Application and Session State

In my last few posts I have focused on the tombstoning features of the Chrysalis Windows Phone 7 application framework. In this post I will look at the related role of application and session state, and how these can ensure that data is persisted during tombstoning using the Chrysalis framework. As usual, all the source code is available on the Chrysalis CodePlex site under the “Source Code” tab.

Application and Session State

All examples of state I have discussed so far have been associated with a single page of a Windows Phone 7 application (view state), ensuring that any data entered is persisted during navigation and application tombstoning. In real applications much of the data crosses across multiple pages, and hence multiple views and view models. Application data is data that stores settings and information that is reused between multiple application instances. This includes user settings, user details as well as any downloaded data that rarely changes. Session data on the other hand is data that crosses multiple pages of an application, but is not reused between application instances, such as session keys for web services or some transient state.

When, and how the data is different for each of these types of state,

  • View state – Persisted on navigation to/from the page to the page state bag.
  • Application state – Persisted and restored upon application shutdown/startup and also during tombstoning using isolated storage.
  • Session state – Persisted during tombstoning to the application state bag.

Storing Application and Session State with Chrysalis

When working with data that crosses several pages (and therefore view models) we need a way to ensure that we can store and access the same data from each page. In the ‘Calculator’ sample provided with Chrysalis, this data is stored in the CalculatorSessionState object,

   1: public class CalculatorSessionState
   2: {
   3:     // *** Properties ***
   4:  
   5:     public string Operator { get; set; }
   6:  
   7:     ...
   8: }

This simply stores the current operator (+, –, / or *) that the calculator is using as a string. This is also displayed on the Calculator information page, and is true session state in that navigation back from the calculator page, and then returning will persist the value chosen.


Since we need to access the state from both the CalculatorViewModel and the CalculatorInformationViewModel, we need to be able to create a single instance of this state to share across both of these locations. Chrysalis provides a simple and straightforward way of creating such “singleton” objects by calling one of the ChrysalisService.GetService methods,



   1: public class ChrysalisService
   2: {
   3:     ...
   4:  
   5:     public T GetService<T>() { ... }
   6:     public object GetService(Type serviceType) { ... }
   7:  
   8:     ...
   9: }

This method will return a single instance of the requested type, initializing a new instance if this is the first such request (note that this will call, and requires, a public parameter-less constructor). Now we can call this method in the constructors of the CalculatorViewModel and the CalculatorInformationViewModel and be sure that we have the same instance in each case.


Supporting Tombstoning


So far I have shown how to share state between pages, but what happens when the application is tombstoned (see here if you wish to refresh yourself on what this means)? Since the process is killed, any state will be lost. On restart we have an entirely new process so Chrysalis will create a new instance with default values.


To provide a seamless user experience, we should persist any session state and restore it when the application is reactivated. Chrysalis makes this easy. All you have to do is to ensure that your state object implements the IHasSessionState interface. For example, the full code for CalculatorSessionState is,



   1: public class CalculatorSessionState : IHasSessionState
   2: {
   3:     // *** Properties ***
   4:  
   5:     public string Operator { get; set; }
   6:  
   7:     // *** IHasSessionState Methods ***
   8:  
   9:     void IHasSessionState.Initialize(object state)
  10:     {
  11:         SessionState sessionState = state as SessionState;
  12:  
  13:         if (sessionState == null)
  14:             Operator = "+";
  15:         else
  16:             Operator = sessionState.Operator;
  17:     }
  18:  
  19:     object IHasSessionState.SaveState()
  20:     {
  21:         return new SessionState()
  22:             {
  23:                 Operator = this.Operator
  24:             };
  25:     }
  26:  
  27:     // *** Sub-classes ***
  28:  
  29:     public class SessionState
  30:     {
  31:         public string Operator { get; set; }
  32:     }
  33: }

Now when the class is first initialised, Chrysalis will call the IHasSessionState.Initialize method. If the application has just been launched the ‘state’ parameter will be null and we can initialise with default values. When the application is subsequently tombstoned Chrysalis will call the IHasSessionState.SaveState method, from which we can return some state to persist until later reactivated. When this does occur a new instance of CalculatorSessionState is created, but this time our previously returned state is supplied as the parameter which we can restore.


Summary


We have now seen how Chrysalis can easily allow you to share session state between pages. By using the Chrysalis tombstoning support on the view model and the IHasSessionState interface on any shared state, we should no longer worry about what will happen if our application is tombstoned. Chrysalis will ensure that any state is restored to that before we were tombstoned, and your users will have a seamless experience.


Once again, you can download a zip file of the entire source code for Chrysalis and the associated sample application from the “Source Code” tab at the Chrysalis CodePlex site.