UPDATE: Source code posted here.

Now that Silverlight 2 is out to the masses (even in beta form), there are likely a lot of developers looking to wire-up web services with their applications in .NET rather than the Silverlight 1.0 method of Javascript.  I thought I'd give you some quick examples of how to do this using some different methods: ASP.NET Web Services (ASMX), Windows Communication Foundation (WCF), REST service, and talk about cross-domain calls.  These are meant to be examples using very much 'hello world' style services, but demonstrating at least how to execute the call.

If you are an ASP.NET developer, you likely are familiar with ASMX web services and the fact that they generate WSDL for anyone looking at their endpoint.  Basically you write some code, host it some where and anyone can call it.  Most of the time, the caller will be using SOAP to connect unless you also enabled other methods on that service.  When consuming the ASMX service you probably used Add Web Reference in Visual Studio and then did something like this:

SimpleWebServiceSoapClient svc = new SimpleWebServiceSoapClient();
string returnValue = svc.HelloWorld();

Fine and simple.  A few lines of code and you are calling your service getting it back value data.  This is a synchronous call.  Of course there are ways to make async calls with ASMX services, but my point is that most typical implementations of ASMX services aren't like that from what I've seen in casual use.  This is where Silverlight may differ for these developers.  In Silverlight 2, all service calls are asynchronous.  Let's take a look at how this is accomplished.

I'm going to use the same application throughout this sample.  The user interface is quite lame, but that's not what this is about.  I'm using a TextBox, TextBlock, and three Buttons all in a StackPanel layout.  =Hhere's what it looks like:

That represents the Silverlight application.  In the web project hosting the Silverlight app, I have 2 services: "SimpleAsmx" and "WcfService" -- aptly named so that they clearly represent the implementing technology.  They are both simple services that expose a method that takes a single string param and basically outputs it back out.  Again, the service portion is not what I'm concentrating on here -- I'm looking at the calling of the service.

Now that we have our layout and our web services, let's start tying them together.  My project looks like this for reference:

ASMX Web Service

In our Silverlight application, I'm going to choose to 'Add Service Reference' from Visual Studio.  This is the same method of previous 'Add Web Reference' but renamed essentially.  When I do that I click Discover and it finds my ASMX service which I select (and rename to AsmxService):

Once I have done that, Visual Studio has wired up a proxy object for me to use in my code.  In my Silverlight application I wire up the Click event in my ASMX Button to an event handler and start writing code.  The first thing you will notice is that implementing the service isn't the same as previously like noted above.  Using ASMX services in Silverlight still uses SOAP, but it also uses the same model of calling a WCF service, which means you have to define a binding and endpoint.  For our ASMX service our binding will be a BasicHttpBinding and our endpoint is our URI to the .asmx file):

UPDATE 19-MAR: The code below will absolutely work (specifying the binding and endpoint information).  However, you can also choose not to specify the binding/endpoint and it should still work.  For the WCF service code below, if you don't change the wsHttpBinding to basicHttpBinding BEFORE you make the service reference in your Silverlight application, then you will have to update your service reference in your Silverlight app (simply right-click on the service and choose 'update service reference').  Doing this will generate the correct proxy code for basicHttpBinding and enable you to just call the code using proxy.YourService() as a constructor rather than using a binding and endpoint.

BasicHttpBinding bind = new BasicHttpBinding();
EndpointAddress endpoint = new EndpointAddress(http://localhost/SimpleAsmx.asmx);

Now that we have those lines, we can new up our service, noticing that the constructor accepts a binding/endpoint for us, so we pass those in:

SimpleAsmxSoapClient asmx = new SimpleAsmxSoapClient(bind, endpoint);

The next step is to call our service.  Remember, we are doing things asynchronously.  So first, we wire up the async handler for when the service is called:

asmx.HelloWorldWithAsmxCompleted += 
   new EventHandler<HelloWorldWithAsmxCompletedEventArgs>(asmx_HelloWorldWithAsmxCompleted);

After that we can now call the service.  The resulting full code looks something like this:

private void AsmxServiceButton_Click(object sender, RoutedEventArgs e)
{
    BasicHttpBinding bind = new BasicHttpBinding();
    EndpointAddress endpoint = new EndpointAddress("http://localhost/SimpleAsmx.asmx");

    SimpleAsmxSoapClient asmx = new SimpleAsmxSoapClient(bind, endpoint);
    asmx.HelloWorldWithAsmxCompleted += 
       new EventHandler<HelloWorldWithAsmxCompletedEventArgs>(asmx_HelloWorldWithAsmxCompleted);
    asmx.HelloWorldWithAsmxAsync(StringToEmit.Text);
}

The event handler for our Completed event looks like this:

void asmx_HelloWorldWithAsmxCompleted(object sender, HelloWorldWithAsmxCompletedEventArgs e)
{
    OutputString.Text = string.Format("Output from ASMX: {0}", e.Result.ToString());
}

Basically when the event completes, the arguments provide us a Result object that represents the return type, in this case a String.  I can then put that string in my TextBlock as output.  And there you have it...we've called a simple ASMX web service.

WCF Services

Calling a WCF service isn't much different (in fact any different).  There is a couple config differences that you have to be aware of which I'll point out here.  But since ASMX services in Silverlight are implemented using the WCF constructs.  Here's the full implemented service with event handler using the same concept:

private void WcfServiceButton_Click(object sender, RoutedEventArgs e)
{
    BasicHttpBinding bind = new BasicHttpBinding();
    EndpointAddress endpoint = new EndpointAddress("http://localhost/WcfService.svc");

    WcfServiceClient wcf = new WcfServiceClient(bind, endpoint);
    wcf.HelloWorldFromWcfCompleted += 
      new EventHandler<HelloWorldFromWcfCompletedEventArgs>(wcf_HelloWorldFromWcfCompleted);
    try
    {
        wcf.HelloWorldFromWcfAsync(StringToEmit.Text);
    }
    catch (Exception ex)
    {
        OutputString.Text = ex.Message;
    }
}

void wcf_HelloWorldFromWcfCompleted(object sender, HelloWorldFromWcfCompletedEventArgs e)
{
    try
    {
        OutputString.Text = string.Format("Output from WCF: {0}", e.Result.ToString());
    }
    catch (Exception ex)
    {
        OutputString.Text = ex.Message;
    }
}

I mentioned a config change that you have to do.  When you add a WCF service to an ASP.NET application, it alters the web.config to add some binding information.  By default it adds an endpoint configuration but adds it like this:

<endpoint address="" binding="wsHttpBinding" contract="IWcfService">

Silverlight communicates using the BasicHttpBinding for WCF, so you have to change it to this (or add another endpoint with this binding):

<endpoint address="" binding="basicHttpBinding" contract="IWcfService">

And then you are done and the code should work.

REST S

Now let's talk about REST.  What is REST?  Representational State Transformation...read about it here.  REST basically takes advantage of existing HTTP verbs (GET, PUT, POST, DELETE) and enables access to actions based on those.  Because of this there is no real "contract" as you may be expecting, or WSDL definitions.  You execute a verb and you'll get a response, usually in XML.  Because there is not contract essentially, the 'Add Service Reference' won't work well for you.  Instead in Silverlight you'll want to use WebClient or HttpWebRequest.  What's the difference?  Here's the timheuer version.  WebClient is a simpler implementation doing GET requests really easily and get a response stream.  HttpWebRequest is great for when you need a bit more granular control over the request, need to send headers or other customizations.  For my sample here, I'm using WebClient because that is all I need.

First a note on remote web services, aka cross-domain services.  In Silverlight 1.0 you couldn't directly access cross-domain services.  In Silverlight 2, we are enabling support for doing that.  The approach we've taken so far is one where we have put the control of the access to the service to the owner of the service.  What that means is that you can't call *any* service on the web, but rather ones that have enabled permission to sites (or everyone) to call their services via rich internet applications.  Flash has enabled the same procedure for a while.  They use a policy access file called crossdomain.xml.  You can read more about this format at crossdomainxml.org.  Silverlight 2 currently supports the exact same policy file.  In addition, Silverlight has a policy file format, but in the end, both are supported, which is cool.  So if you have a web service on a domain separate from your Silverlight application, you'll have to create the policy file at the endpoint root of your web service to enable rich internet platforms to support it.

Once that policy file is in place you are good to go.  For demonstrating REST I am choosing to show you one that is a public API and has a policy file...Flickr.  My sample basically calls Flickr's REST API to search for photos based on a tag and then the result is to add Image elements to my Silverlight DOM in a StackPanel.  Here's what it looks like (after the wire-up button is hooked up).  In my click event handler it looks like this:

WebClient rest = new WebClient();
rest.DownloadStringCompleted += new DownloadStringCompletedEventHandler(rest_DownloadStringCompleted);
 rest.DownloadStringAsync(new Uri(flickrApi));

The "flickrApi" variable represents the REST api call to search photos for Flickr.

The async callback basically gets the Flickr REST response (XML) and parses it using LINQ, then adding a new Image element to the Silverlight tree:

string data = e.Result;
string url = string.Empty;

FlickrImages.Children.Clear();

XDocument doc = XDocument.Parse(e.Result);
var photos = from results in doc.Descendants("photo")
            select new
            {
                id = results.Attribute("id").Value.ToString(),
                farm = results.Attribute("farm").Value.ToString(),
                server = results.Attribute("server").Value.ToString(),
                secret = results.Attribute("secret").Value.ToString()
            };

foreach (var photo in photos)
{
    url = string.Format("http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg", 
      photo.farm, photo.server, photo.id, photo.secret);
    Image img = new Image();
    img.Stretch = Stretch.Fill;
    img.Margin = new Thickness(10);
    img.Source = new BitmapImage(new Uri(url));
    FlickrImages.Children.Add(img);
}

The result of which is 5 pictures added to my Silverlight application, and looks horrible like this:

So that's it, web services (hopefully) made simple.  I hope this helps.  What did I miss?

I just saw two links that I simply have to promote as they are very helpful to people doing Silverlight development and one specifically with ASP.NET.

The first is a site on silverlight.net (you should bookmark this site as a resource and subscribe to all the feeds), there is now a Silverlight 2 Beta 1 control sample page, which hosts all the new Silverlight controls on the site.  It shows some different usage of all the controls:

Silverlight Controls Sample

Very cool to see all the controls implemented in one section, play around with them and see different styles in some as well.

The second link is awesome because when I read it I laughed out loud.  The reason wasn't because of the post, but because of a conversation I had with Pete Brown over email.  It is best described simply by showing you the email (privacy information blurred to protect the innocent):

Alas, Cameron Albert created an <asp:Silverlight> override control that enables using the control and supplying a splash screen XAML file and event handler.  This is great!  It enables you to still use the server control with ease but adds some customized functionality so that you can enhance the user load experience.  Essentially it boils down to:

<lg:Silverlight ID="silverlight1" runat="server" Source="~/ClientBin/Perenthia.xap" 
                Version="2.0" Width="800" Height="500" SplashScreenSource="~/Common/Xaml/Splash.xaml" 
                OnSourceDownloadProgressChanged="onSourceDownloadProgressChanged" />

Anyhow, I couldn't help but laugh when I saw that -- but it is a great post and control!  Great job Cameron!

UPDATE: The supported method for Silverlight 2 release is shown here: http://silverlight.net/learn/learnvideo.aspx?video=69800.  You basically have to make it an assembly resource.

Since the beginning of Silverlight you've been able to embed fonts within a Silverlight application.  The challenge in version 1.0 was that you essentially had to use a downloader and some SetFontSource methods on a TextBlock (for example) to do it.  I wrote about this a while back when using my own handwriting as a font within Silverlight. 

It looked something like this:

this.downloader = control.createObject("downloader");  
this.downloader.addEventListener("completed",
Silverlight.createDelegate(this, this.handleFontDownloaded));
this.downloader.open("GET", "timheuer.ttf");
this.downloader.send();

handleFontDownloaded: function(sender, eventArgs)
{
this.header.setFontSource(sender);
this.itemtext.setFontSource(sender);
this.header.fontFamily = "Tim Heuer Normal";
this.itemtext.fontFamily = "Tim Heuer Normal";
}

It isn't incredibly ideal for all situations.  It works, and in some scenarios might be valid and fine.

For most, I think we'll want an easier implementation and something that feels a bit more natural.  Well, in Silverlight 2, we now have it.  Let's take a look at the above sample and how we could do that for Silverlight 2:

<TextBlock x:Name="Header" FontFamily="timheuer.ttf#Tim Heuer Normal" /> <TextBlock x:Name="ItemText" FontFamily="timheuer.ttf#Tim Heuer Normal" />

Okay, so what is happening here?  What happened to the script?  There is none (obviously).  What is happening here is that Silverlight now does the lifting for you.  Let's break this down a bit more.

First, the FontFamily is set to "timheuer.ttf" in this example, which is my handwriting font in TrueType format.  This font is located next to the applications XAP file which is in ClientBin.  It could be located anywhere in the same application domain and you could use an absolute URL here as well.  For our purposes, we have a file on a web server.

When we set that in the FontFamily to a file, Silverlight essentially creates the downloader for us in an efficient manner.  The font file is requested based on the URI provided and downloaded via a GET request.  Once downloaded it parses out the second part (the "#") to look within that font file for the named font.  So essentially the format is:

<file>#<named-font>

where # is the delimiter in this format.  That's it, you are done.  No script needed.  If you choose to package several font assets within your application you can put them in a single archive file as well and the same syntax would apply:

<TextBlock x:Name="Header" FontFamily="timheuer.zip#Tim Heuer Normal" />

The same execution happens.  Silverlight gets the archive file and then looks at the font file contents in the archive to find the first named font to use.  The archive doesn't have to only have font files either...which is cool at times.

Hope this helps!

For about a year now I've been using Amazon S3 services.  Mostly I'm using it for image storage for my blog and web site.  I decided to stop using Flickr for screenshot stuff and keep it to 'photographs' when I can.  I signed up for an S3 account and have been using it for screenshot type stuff since then.  If you don't know, S3 is a service that basically enables 'object' storage in the cloud.  An object can be anything really, but I'm treating it like a remote host for images.

The one thing Amazon doesn't provide themselves is a tool to manage your account...it is really an API only.  There are plenty out there that have implemented user interfaces around S3 services.  My two favorites are the S3 plugin for Firefox and BucketExplorerI use the Firefox one more than anything for uploading just because it was faster for what I needed.

UPDATE: While I still use the Firefox extension and always have it installed, I find myself using CloudBerry Explorer a LOT more.  It is the most full-featured (free) Amazon S3 tool I've seen and I love it.  They keep adding little subtle things to that make my process even easier!  Check it out today!

But the problem is that neither of the tools really incorporated *why* I was using S3 for me, which was primarily with my blog.  So a year ago I grabbed some of the sample code from the S3 developer site and whipped up a quick-and-dirty plugin for Windows Live Writer that I've been using.  I already had my Flickr4Writer plugin that I used for Flickr, but like I mentioned, I was using S3 for other image hosting now.  I was lazy though and only did a read version that inserted an image.  I was still relying on the other tools to upload, change permissions, etc. -- my workflow sucked.

Well as a part of The Code Trip, we set goals to release projects on CodePlex.  I decided to put this project out on CodePlex as far as I had it.  I immediately had a partner in Aaron Lerch.  He jumped in and within a day basically put in the remaining features that were lacking.

The result is the S3 Browser for Windows Live Writer project:

The initial 0.91 beta release is available on the project now.  Please give it a spin if you are a Live Writer and Amazon S3 user!

When working with Silverlight 2, most will be working with managed code (c#, vb, etc.).  But likely people are working with Silverlight as an additive value to their web application, providing some enhanced user experience to an application.  there may be times where you will still need to call back into the hosting html context.  For then, you'll want to be familiar with two objects HtmlDocument and HtmlPage. 

Both of these objects provide access to the page context hosting your silverlight control.  If you need to seek things in the HTML DOM, you could use the HtmlDocument class.  For example, let's say I need to change the innerHTML property of some <div> element:

using System.Web.Browser;

HtmlDocument doc = HtmlPage.Document;
doc.GetElementById("mydiv").SetProperty("innerHTML", "<b>hello world</b>");

Also, i might want to interact with existing client-side functions, perhaps from client-side frameworks or other library utilities you might have developed on your own.  If I have a function on my page called "foo()" I would invoke it like this:

using System.Web.Browser;

HtmlPage.Window.CreateInstance("foo");

And if I had parameters in a function, like "foo2(theAlert)," I would invoke it like this:

using System.Web.Browser;

HtmlPage.Window.CreateInstance("foo2", new string[] { "tim heuer" });

This may not be the norm with your Silverlight project, but I hope this helps clear some things up!  I am including the "using" statements in my c# samples so you know where in the namespace the class library exists.