Saving data-objects to Isolated Storage in Silverlight

If you are developing an enterprise Silverlight application you will typically need to cache your business entities in the isolated storage. There are two apparent choices for this:

1. Use the powerful Linq-To-XML API from System.Xml.Linq namespace. This method is to be used when you want to have a fine grain control over serialization (e.g. you want to store some properties of the data objects).

2. Use the built-in DataContractSerializer class. This method is very simple and the only thing it requires is that our business objects need to have the [DataContract] and [DataMember] attributes. In this post, I am going to discuss this second method.

In an enterprise LOB (line of business) application, our business objects will typically be retrieved via WCF service and hence will already have the [DataContract] and [DataMember] attributes marked on them. So we can directly use the built-in DataContractSerializer to store them to, and later retrieve them from, the isolated storage. Here’s a generic class to simplify the process:

public static class IsolatedStorageCacheManager<T>
{
    public static void Store(string filename, T obj)
    {
        IsolatedStorageFile appStore = IsolatedStorageFile.GetUserStoreForApplication();
        using (IsolatedStorageFileStream fileStream = appStore.OpenFile(filename, FileMode.Create))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            serializer.WriteObject(fileStream, obj);
        }
    }
    public static T Retrieve(string filename)
    {
        T obj = default(T);
        IsolatedStorageFile appStore = IsolatedStorageFile.GetUserStoreForApplication();
        if (appStore.FileExists(filename))
        {
            using (IsolatedStorageFileStream fileStream = appStore.OpenFile(filename, FileMode.Open))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(T));
                obj = (T)serializer.ReadObject(fileStream);
            }
        }
        return obj;
    }
}

Using the above code is really simple. Just add the class to your project and use it like this:

//for storing and retrieving a single object
Person myPersonObj = GetPerson();
IsolatedStorageCacheManager<Person>.Store("myfile.xml", myPersonObj);
Person myPersonObj2 = IsolatedStorageCacheManager<Person>.Retrieve("myfile.xml");

//for storing and retrieving a collection of objects
List<Person> myPersonList = GetPersonList();
IsolatedStorageCacheManager<List<Person>>.Store("myfile.xml", myPersonList);
List<Person> myPersonList2 = IsolatedStorageCacheManager<List<Person>>.Retrieve("myfile.xml");

Hope you will find this implementation useful.

Deploying a Silverlight Application and WCF Service to IIS

While deploying a Silverlight application on IIS today, I learned several new things. Let me express my observations; This post is going to describe the security settings for WCF service in web.config. To start, I assume that you are using either Windows or Forms authentication and denying all the anonymous users as described in a previous post.

First, make sure to remove the mexHttpBinding endpoint as this requires you to enable anonymous access to the website in IIS. The mexHttpBinding endpoint will look something like:

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

 
BasicHttpBinding

Typically, in your application, you will also be using some custom basicHttpBinding configuration for your WCF service endpoint, like this one:

<endpoint address="" binding="basicHttpBinding"
 contract="SilverlightApplication.Web.WCFService"
 bindingConfiguration="myCustomBasicHttpBinding" />

Using a custom binding allows you to configure buffers and quotas as described in this post. The definition of this custom binding will look something like:

<bindings>
 <basicHttpBinding>
  <binding name="myCustomBasicHttpBinding">
  <security mode="TransportCredentialOnly">
   <transport clientCredentialType="None"/>
  </security>
  </binding>
 </basicHttpBinding>
</bindings>

The <transport clientCredentialType=”None”/> is the main point of interest here. If you are using Forms Authentication, you need to allow anonymous access through IIS and set the clientCredentialType to None. If you want to run your application under Windows Authentication, you should use clientCredentialType="xxxx" where xxxx is the corresponding IIS authentication type. So, to work with Integrated Windows/Basic/Digest/NTLM Authentication, the xxxx should be replaced by Windows/Basic/Digest/Ntlm respectively.

 

Update: Custom Binary Binding

Similar change is required for custom binary binding:

<customBinding>
 <binding name="myCustomBinaryBinding">
  <binaryMessageEncoding >
   <readerQuotas ... />
  </binaryMessageEncoding>
  <httpTransport authenticationScheme="Anonymous" ... />
 </binding>
</customBinding>

Again, the point of interest is the authenticationScheme attribute in the httpTransport element that needs to match the IIS authentication setting (e.g. Anonymous for Forms Authentication, Ntlm/Basic/Digest for Windows Authentication).

This way, the WCF service should work without any problems.

A nice overview of Windows 7

Bart Czernicki presented a very nice overview of Windows 7 here. After installing the new OS on my machine and playing with it for the last 2 weeks, I agree with most of his points. Check it out.