Silverlight deployment: deploying to multiple environments

Today I got an interesting question, namely they were using services in their silverlight application, but each time they needed to deploy they unzipped the .xap file to change the ServiceReferences.ClientConfig configuration to use their production server. of course this meant re-zipping back to .xap, and possible mistakes during deployment. So on several occasions a QA .xap was deployed in production.

So how can you avoid this? Well, I think the best way is to move the changing configuration to outside the .xap file. For example we can deploy a simple file to the web server where the silverlight application is deployed and add the server address in it:

<servers>

  <server type="movieServer"

          uri="http://PRODUCTION_SERVER/MovieService.svc"

  />

</servers>

 

For each deployment environment you would keep a separate file, making sure that future deployments cannot overwrite it by accident (for example by setting ACL’s on the file).

Next, when the silverlight application starts we download this file from the server using the WebClient class:

Dim WithEvents wc As New WebClient

 

Private Sub GetTheServers()

  wc.DownloadStringAsync(New Uri("servers.xml", UriKind.Relative))

End Sub

 

Once we receive the DownloadStringCompleted event we parse the server’s address out of the received xml:

Dim movieServerAddress As String

Private Sub wc_DownloadStringCompleted(ByVal sender As Object,

             ByVal e As System.Net.DownloadStringCompletedEventArgs)

             Handles wc.DownloadStringCompleted

  Dim doc = XDocument.Parse(e.Result)

  Dim movieServerQuery = From server In doc...<server> _

                         Where server.@type = "movieServer" _

                         Select server.@uri

 

  movieServerAddress = movieServerQuery.Single()

End Sub

 

When we need to call the service (for example a WCF service) we simply use the stored movieServerAddress:

Private Sub LoadTheMovies(ByVal sender As System.Object,

                          ByVal e As System.Windows.RoutedEventArgs)

  proxy = New MovieServiceReference.MovieServiceClient( _

            New BasicHttpBinding(), 
            New EndpointAddress(movieServerAddress))

  proxy.GetListOfMoviesAsync()

End Sub

 

You could avoid downloading the servers.xml file multiple times by storing it in Isolated storage. So the first time isolated storage wouldn’t have this information yet, so you would call GetTheServers. Then you could parse its contents and store the information in isolated storage. Next time you would find it in isolated storage, saving the round-trip to download it…