Following up on this post, it seems that there’s more to this online/offline malarky in HTML 5 in that this;
talks about Application Caches. As far as I can work out, that’s to do with providing more of a manifest around what pages/resource need to be cached in order to make the application work well when run entirely from the cache offline.
I was wondering how this would work with Silverlight so I thought I’d try an experiment using that base class that I wrote in the previous post.
Let’s say (for argument’s sake) that I want to build a simple email client in Silverlight. So, I want a UI with fields such as TO, CC, Subject, Body and I have some webservice that’ll actually do the emailing for me.
I want to be able to do this whether I am online or offline. Maybe I want a UI something like this;
The idea being that you write a mail and when you click Send we either;
- If we’re online, call the webservice.
- If we’re offline, store the mail in IsolatedStorage and next time we go online we send the mail via the webservice.
I built a quick website and added a simple web service;
[ServiceContract] public interface IMailService { // Assume we know who the mail is from (which we wouldn't :-)) [OperationContract] void SendMail(string to, string cc, string subject, string body); }
and implemented it with a dummy implementation;
public class MailService : IMailService { public void SendMail(string to, string cc, string subject, string body) { // Sorry, lost in the post. } }
and then configured that in my web.config to do the basic http binding;
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="MailServiceBehavior"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="MailServiceBehavior" name="MailService"> <endpoint address="" binding="basicHttpBinding" contract="IMailService"> <identity> <dns value="localhost" /> </identity> </endpoint> </service> </services> </system.serviceModel>
and did a quick “View in Browser” to see if that was working ok.
With that in place, I added a Silverlight project to the website and then added in my NetworkAwareApplication code like I did on the previous post and changed my app.xaml and my app.xaml.cs in order that I am producing a NetworkAwareApplication-derived class for my Application.
I can then go and build a bit of UI. I’m not sure that it’s worth including the XAML here so here’s the picture;
and I data bound the listbox on the left hand side and the various fields of the email on the right hand side. I wrote a few classes to sit behind this which ended up looking something like this;
Ultimately, what happens here is that I have the Page which is bound to an instance of the MailData class which contains the current mail item and a list of queued items. At application start we do;
- Load up any persisted MailInfo items from isolated storage.
- Check if the application is online. If so, try and send any persisted emails to the web service. Any failures just stay in the queue. Any successes come out of the queue.
- When the user presses “Send” we just see if we are online and either send/queue the email respectively.
Now, this application only consists of 2 separate files;
- The launching HTML page.
- The Silverlight XAP.
And there’s no way to instantiate the application without the browser having read both of those files and cached them.
So, the application cache stuff from HTML 5 doesn’t really seem that relevant but, nonetheless, I wrote a little manifest file and referenced it from my HTML. Here’s the manifest file;
CACHE MANIFEST
# v1
# This is a comment.
OnlineExperimentSLTestPage.html
ClientBin/OnlineExperimentSL.xap
ClientBin/img1.jpg
I just added the .jpg file so that I could see if the browser would pro-actively download and cache it ( i.e. to pretend that my Silverlight application was more than just 2 files ).
I referenced that from my HTML;
<html xmlns="http://www.w3.org/1999/xhtml" manifest="manifest.cmf">
and then ran up the page to see a;
so I let it the browser do the offline storage but I’m not sure that it did as I didn’t see the browser pro-actively download the img1.jpg file and nor did I see it download the .cmf file ( I gave it that extension so that I could give it a MIME type of “text/cache-manifest” within IIS ).
So, I’m not sure that stuff’s working for me or maybe I don’t understand it properly.
It doesn’t really matter because I only have 2 files in my application and, by definition, if you are running the application then you’ve got those 2 files in your browser cache unless you clear it so there’s no real need for me to try and provide a manifest with a more complete set of files.
I can run my application;
and I can send that mail and it’ll call the web service. However, if I pull out the network cable then the application will spot that I’m now “offline” and so if I send the mail it goes into the “queue” maintained in isolated storage;
Now, if I go and plug the network cable back in, the browser detects that and sends the mail via the web service.
More interestingly, if I shut down the web server so that the browser can’t get to the webpage and I then refresh the browser I’ll get;
but if I put the browser into its “Work Offline” mode and then refresh it I’ll get;
My next hope would be to restart my web server and plug the cable back in the browser doesn’t seem to realise that we are now online or, at least, it’s not prepared to take me out of “Work Offline” just because it’s noticed the network cable has been plugged back in.
So, I manually uncheck the “Work Offline” option and the queued mail gets sent when my code realises that the network is back.
The usage feels a bit weird. I’m hitting a URL when I know full well that the application isn’t really available but it seems to work reasonably well even though it feels weird.
I was wondering how this might be made to feel a little more normal and I had a brief look at “PRISM” which takes away all the browser chrome and makes it look like your web application is an installed application but the problem I had with that is that it doesn’t seem to do offline working as far as I can tell ( it’s in the wishlist of features ).
So…at the end of a long post I’m not really contributing anything particularly radical here – the conclusion is that I can run a Silverlight application from the browser’s cache and you can make it go online/offline based on the new events in HTML5 and that seems to work reasonably well.
Ultimately, that might partner up a little better with the “application cache” stuff driven by the manifest for HTML5 but I’ve yet to get my browser to play ball on that one 🙂
I put the project files here in case you want to play – bear in mind that the web service proxy will be coded to point to the wrong machine and you’ll need to unpack the website bits into a web project.