Silverlight 2 Beta 2 - ASMX Services & XmlSerializer

It wasn't clear to me from reading the Silverlight SDK docs whether or not you could call ASMX services from Silverlight 2 Beta 2 if calling those services meant involing the XmlSerializer.

Silverlight is using WCF to call services and WCF usually uses the DataContractSerializer. This is a clever serializer but one of the things that it doesn't do ( which I never understood the rationale for ) is serialize XML attributes. It is as element-centric as a serializer can be.

So, I read in the Silverlight SDK docs;

Using XmlSerializer

  • Silverlight 2 Beta 2 supports XmlSerializer. The equivalent serialization support in WCF is described in XML and SOAP Serialization.
  • In Silverlight 2 Beta 2, generating SOAP messages as described in the preceding document is not supported.

and I didn't understand whether those 2 sentences combined to say "Supported" or "Not Supported". Having read it twice, I think what it means is that the XmlSerializer bits are supported but the bits referenced here are not. That's what I think it means but I can't be 100% sure.

And so I built a quick ASMX service as in;

public class Operand
{
  [System.Xml.Serialization.XmlAttribute]
  public int X { get; set; }

  [System.Xml.Serialization.XmlAttribute]
  public int Y { get; set; }
}

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
  public WebService()
  {
  }
  [WebMethod]
  public int Add(Operand op)
  {
    return (op.X + op.Y);
  }
}

and added a reference to it from my Silverlight 2 Beta 2 project and the proxy generation seemed to work ok and, specifically, I could see that the generated proxy code is using the XmlSerializer;

namespace SilverlightApplication3.ProxyCode {
    
    
    [System.ServiceModel.ServiceContractAttribute()]
    public interface WebServiceSoap {
        
        [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/Add", ReplyAction="*")]
        [System.ServiceModel.XmlSerializerFormatAttribute()]
        System.IAsyncResult BeginAdd(SilverlightApplication3.ProxyCode.Operand op, System.AsyncCallback callback, object asyncState);
        
        int EndAdd(System.IAsyncResult result);
    }

and then I called the service using the proxy and it all seemed to work fine. Note that I had to manually add a reference to System.Xml.Serialization.dll in order to get the client to compile but that's fine.

So..."seems to work".


Filed Under: ,

Silverlight 2 and HTML 5 - Being Online/Offline ( Part 2 )

Following up on this post, it seems that there's more to this online/offline malarky in HTML 5 in that this;

http://www.w3.org/TR/2008/WD-html5-20080122/#appcache 

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;

image

The idea being that you write a mail and when you click Send we either;

  1. If we're online, call the webservice.
  2. 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;

image

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;

image

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;

  1. Load up any persisted MailInfo items from isolated storage.
  2. 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.
  3. 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;

  1. The launching HTML page.
  2. 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;

image

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;

image

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;

image

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;

image

but if I put the browser into its "Work Offline" mode and then refresh it I'll get;

image

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.


Filed Under: ,

Silverlight 2 and HTML 5 - Being Online/Offline

One of the things that's coming in IE8 and is already present in FireFox 3 as far as I know is HTML 5's ability to detect whether the browser is online or offline and to provide some offline storage ( alongside cookies ) for the application.

You can find some details about that here;

http://www.w3.org/TR/offline-webapps/

It occurred to me that this might be pretty useful to pick up from Silverlight and so I wrote a little base class for an application which would surface this info.

I didn't go into the "offline storage" idea because I can't really see the point with Silverlight because it already has IsolatedStorage which would work regardless of whether the browser can currently see the network or not.

Here's the class, very simple. If someone knows how I answer my TODO: then please let me know - I'm not "great" at Javascript;

namespace SLOnlineOffline
{
  public enum NetworkStatus
  {
    Online,
    Offline,
    Unknown
  }
  public class NetworkStatusEventArgs : EventArgs
  {
    public NetworkStatus NetworkStatus { get; set; }
  }
  public class NetworkAwareApplication : Application 
  {
    public NetworkAwareApplication()
    {
      HookBrowserOnlineOfflineEvents();
    }
    private void HookBrowserOnlineOfflineEvents()
    {
      // TODO: Figure out how we find out whether the DOM actually _has_
      // an "onoffline" and an "ononline" event. Don't want to get into
      // checking the UserAgent here so someone tell me how to do it please :-)
      HtmlPage.Document.Body.AttachEvent("onoffline", (EventHandler)OnOffline);
      HtmlPage.Document.Body.AttachEvent("ononline", (EventHandler)OnOnline);
    }
    private void OnOffline(object sender, EventArgs args)
    {
      FireNetworkStatusChange(NetworkStatus.Offline);
    }
    private void OnOnline(object sender, EventArgs args)
    {
      FireNetworkStatusChange(NetworkStatus.Online);
    }
    private void FireNetworkStatusChange(NetworkStatus networkStatus)
    {
      if (NetworkStatusChange != null)
      {
        NetworkStatusChange(this, new NetworkStatusEventArgs() { NetworkStatus = networkStatus });
      }
    }
    public NetworkStatus NetworkStatus 
    {
      get
      {
        // Ask the browser...
        NetworkStatus status = NetworkStatus.Unknown;

        try
        {
          ScriptObject navigator = (ScriptObject)HtmlPage.Window.GetProperty("navigator");

          if (navigator != null)
          {
            bool navigatorStatus = (bool)navigator.GetProperty("onLine");

            status = navigatorStatus ? NetworkStatus.Online : NetworkStatus.Offline;
          }
        }
        catch // Gulp.
        {
        }
        return (status);
      }
    }
    public event EventHandler<NetworkStatusEventArgs> NetworkStatusChange;
  }
}

and then I can use that as my base class for my Silverlight application instead of System.Windows.Application so I can author some XAML such as;

<local:NetworkAwareApplication
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SLOnlineOffline.App"
  xmlns:local="clr-namespace:SLOnlineOffline">
  <local:NetworkAwareApplication.Resources>

  </local:NetworkAwareApplication.Resources>
</local:NetworkAwareApplication>

and then the code behind that app.xaml looks like this;

namespace SLOnlineOffline
{
  public partial class App : NetworkAwareApplication
  {

so we're producing a NetworkAwareApplication rather than a plain old Application and then I can write a little UI for my Page;

<UserControl x:Class="SLOnlineOffline.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>
      <Button
      Content="Hello" 
        Click="OnClick"/>
    <TextBlock
      x:Name="txtStatus"
      Text="Not Set" Grid.Row="1"/>
  </Grid>
</UserControl>

and a little code behind that;

namespace SLOnlineOffline
{
  public partial class Page : UserControl
  {
    public Page()
    {
      InitializeComponent();

      Application.NetworkStatusChange += OnNetworkStatusChange;
    }
    void OnNetworkStatusChange(object sender, NetworkStatusEventArgs e)
    {
      txtStatus.Text = string.Format(
        "Automatically determined new status is {0}", e.NetworkStatus);
    }
    void OnClick(object sender, EventArgs args)
    {
      txtStatus.Text = string.Format(
        "Manually checked status is {0}",
        Application.NetworkStatus.ToString());
    }
    NetworkAwareApplication Application
    {
      get
      {
        return ((NetworkAwareApplication)System.Windows.Application.Current);
      }
    }
  }
}

and then I've got a Silverlight application that I can view in FireFox 3 ( I don't have IE8 installed just yet ) and I can unplug my network cable and the Browser knows that it's gone offline and I can plug my network cable back in and the browser knows that it's back online and all seems well and this information filters through into my Silverlight application.


Filed Under: ,

Dell Hybrid

Dell's got a (reasonably) nice looking little machine that might make a nice Media Center.

I run ( Vista ) Media Center under my TV on a Shuttle box ( search the blog for Shuttle you'll find the specs ) every day and it works extremely well. For me, Media Center is one of the bits of Vista that it's very easy to point at and say "This is way better than it was on XP".

However, I think it's true to say that I spec'd the Shuttle for XP and not for Vista. Whilst it runs Vista well enough it doesn't quite zing when it comes to the Media Center UI ( I think I turned off a bunch of transitions way back ) and I was using one of these Sony boxes in a shop the other week and it highlighted to me that my performance with Media Center could be better.

Hence...the look at the Dell Hybrid.

I'm not sure it'll quite work for me though as;

  1. I'm not sure whether the integrated graphics will cut it or not.
  2. It looks to accept no internal cards so I'm not sure how I'd get a TV tuner into it. I guess I could find one of those USB tuners but I've never tried one and don't know if you can get a dual-DVB-T tuner that way. Additionally, I already have a perfectly good card so that'd be a bit of a waste.
  3. Cooling. I wonder how warm/noisy it is? Kind of hard to tell from a website :-)

Perhaps I'll hang fire for a while and see if something better crops up.


Filed Under:

Using Excel as an XML Editor

In a couple of instances recently I've had cause to take data that exists in an Excel spreadsheet and save it out as XML and, whilst it's slightly off-topic, I thought I'd share as I find it "enjoyable" :-)

I don't mean as a .XLSX file but, rather, as an XML file according to my own schema.

Let's say I sketch out some XML file format by running VS and coming up with something like;

<videos>
  <video title="Using Excel for XML Editing"
         author="Mike Taulty"
         duration="120"/>
</videos>

I can then get Visual Studio to infer a schema from this giving me something like;

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="videos">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="video" minOccurs="1" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="title" type="xs:string" use="required" />
            <xs:attribute name="author" type="xs:string" use="required" />
            <xs:attribute name="duration" type="xs:unsignedByte" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

I know that's a very imprecise science (schema inference) but I don't really mind here although I did tweak it just to add the minOccurs and maxOccurs facets on there.

Now, I can drop into Excel and create a new spreadsheet and on the Developer tab I can associate my schema with the sheet by clicking "Source";

image

and adding an XML map;

image

and then dragging and dropping items from that map to the spreadsheet;

image

to the spreadsheet cells that I want to associate with that schema and "BOOM!" ;-) I get;

image

and then I can just edit my XML;

image

and then click Export from the Developer Tab;

image

and save the resulting XML. Cool! Nice and easy way to create XML. As an aside, you can also import data this way ( with the import button ) and I recently found that to be really useful because I wanted to gather all the details of the videos that we have published on the UK MSDN site into an Excel spreadsheet for discussion.

I was about to write some C# code to do this when I realised that I could just do Import from Excel, point it at the live RSS feed and it would just magically drop that into a spreadsheet for me with the XML association. Very neat.

By the way - if you're missing the Developer tab in Excel you need to go to the Office Button, hit the "Excel Options" button;

image

and then go and select to show the developer tab;

image


Filed Under:

Silverlight 2 Videos on Silverlight.net

Nice to see that the videos that Mike and I made on Silverlight 2 are now on Silverlight.net up here;

http://silverlight.net/Learn/videocat.aspx?cat=10


Filed Under:

Added (Updated) ADO.NET Data Services Videos to C9

I produced a new set of short videos around ADO.NET Data Services and dropped them on to Channel 9. You can find them here;

http://channel9.msdn.com/tags/UK

and that list will grow as time goes in ( specifically, it'll grow if I can get the publishing system to publish my next 4 videos for me as it's not playing ball at the time of writing :-) ).

Don't Steal My Focus

I've been encoding videos today with Expression Encoder 2.

I load up a batch of videos and set them transcoding. This takes ages and burns CPU cycles like nobody's business - at times like this you wish the age of quad-core, eight-core and so on was already mainstream.

I get quad-core effects by using the 2 cores on my laptop and the 2 cores on my desktop :-)

Anyway, I'd left it running for maybe 8-10 hours and it was nearly done on all the videos when Outlook popped up its reminders window and I tried to dismiss it by hitting ESC.

Unfortunately, the ESC went to the wrong window. It went to the Expression Encoder 2 window which promptly cancelled the job and, even worse, deleted all the files that it had transcoded as part of that job so far.

Bad marks all around;

  1. Bad marks to that Outlook reminders window for being so "needy".
  2. Bad marks to Windows for letting that Outlook reminders window annoy me.
  3. Very bad marks to Expression Encoder for assuming that pressing ESC on their UI means;
    1. Stop the current encoding job
    2. Delete all the outputs produced so far by the current encoding job

Ouch.

I've tried to modify my ForegroundLockTimeout in my register to stop windows stealing focus - not 100% sure if this still has an effect on Vista though.


Filed Under:

Experiments in Building a Silverlight Photo Control ( Part 4 )

Following on from this post, I wanted to see what would happen if I opened my solution in Expression Blend 2.5 June Preview and tried to style my control a little.

So, I opened it in Blend.

I got a bit stuck straight away because when I tried to display my page.xaml Blend threw up an error;

image

From the stack trace, this looked suspiciously like some of my code running to load images when it really shouldn't be inside of a design time environment like Blend.

So, I added a little member function to my control;

    private bool IsInDesignMode
    {
      get
      {
        return (DesignerProperties.GetIsInDesignMode(this));
      }
    }

and called it from a few places to stop the control trying to load images and so on if it's in design mode rather than run-time mode and Blend sprung into life;

image

Now...to try and set about styling the control. First off, I created an empty template for my control;

image

Then I took the Grid that's given to me;

image

and replaced it with a StackPanel, some Buttons, an Image and a couple of other bits and pieces to create my UI. I made sure to name this things in accordance with the naming expected by my control. I managed to get as far as this;

image

Which gives me this delightful look and feel ;-)

image

With a sort of "border path" that I "drew" in Expression Design but then I got stuck in that I get exceptions from Blend if I try and change the template on those buttons that I've got. That is, just picking one of those buttons and doing "Edit Empty Template" gives me;

image

I wasn't entirely sure what to do about that but I found that if I went into the XAML and just set up a Template for the buttons manually and then just put something basic into that template then once I revisited that in Blend it would now edit that template.

So, I managed to get a fairly ugly looking thing :-) but at least it looks different from where I started;

image

And, with that, I'm giving up for a while :-)

If you want the project, then I shared the whole thing here for download. It includes the web project, the images, everything so you should be able to just press F5. Most of the size of the ZIP file is the 5 images which are taken from Windows.


Filed Under: ,

SQL Bits III

I've managed to submit a session for SQL Bits III in Hatfield on Saturday the 13th September. If I manage to make the vote then I'll be talking about ADO.NET Data Services as a way of ( productively ) exposing CRUD access to your data over RESTful web services and probably doing a bit of explanation around RESTful whilst I'm there along with talking about consuming those services with AJAX and .NET clients.

I spoke at the last SQL Bits and it's a cool conference - if you're interested in coming along then check out;

http://www.sqlbits.com/

and if you're interested in coming along to my session then you need to vote for it on this page ( otherwise it may well not happen! );

http://www.sqlbits.com/information/publicsessions.aspx


Filed Under:
More Posts Next page »