| Comments

The first of my Silverlight videos have posted which cover some networking stuff that I’ve been blogging about already.  If you want to see a walk through of things you might have already read, please take a look at them:

There are more coming and I’m interested in hearing your comments so please give them.  If you have suggestions for things that need to be demonstrated to help others (or yourself), please let me know about them as well!

| Comments

If you are starting to get into integrating web services with Silverlight, you'll notice that you have to have a cross domain policy file in place on the target server, that is to say, the server hosting the service you want to implement.  There are some public web services (Flickr, YouTube, Digg, etc.) that already have these files in place for Flash, but implement in a slightly different way.

When calling a cross-domain service, Silverlight will check for the existence of clientaccesspolicy.xml first.  This is the format defined by Silverlight and provides a pretty flexible way to define who can access what services.  If not found, it will then default to look for crossdomain.xml, which is the file format implemented for Adobe Flash.  It is important to note that this file will also still work for most public web services.

But now perhaps you are the author of the service that your application is going to consume and/or the public will consume.  There are a few things you want to consider.  First, it would be a best practice to put your service layer on a separate domain other than your site (i.e., api.mysite.com).  In fact, this is how most are doing it these days.  These helps separate more distinctly the services from the web site and also separates the cross-domain security concerns away from the content site versus API access.  Once you have done that you'll want to implement your specific clientaccesspolicy.xml file.

When Silverlight 2 was released to beta, I created some quick helper files to assist me with creating this simple policy file (it is simple, but can get complex depending on how granular you want to define your access).  I figured it might be helpful to some who are implementing services as well.  Sure, they aren't going to save the world, but might save you some quick typing.

Visual Studio Code Snippet

The slcap.vsi file is a Visual Studio Community Installer package which contains "slcap.snippet," which is a Visual Studio code snippet format.  This is an XML snippet, so would be used only in the context of an XML file.  Just double-click on the .vsi file to install and it will walk you through the steps.  I recommend just keeping the defaults.  After it is complete, you now have an Intellisense snippet.  To use it and create a new clientaccesspolicy.xml add a new XML file to your web service site/project named clientaccesspolicy.xml.  It will open a blank XML file by default.  Select all text (CTRL+A).  Then hit the keyboard shortcut for launching XML snippets, CTRL+K,X.

NOTE: For some reason XML snippets don't operate like C#/VB ones do where you type the shortcut, then TAB, TAB.  If anyone knows why, let me know :-)

This will bring up the navigator, then simply navigate to the My XML Snippets, then locate the one you just installed:

Once you select it, there are three literal areas to override the defaults if you wanted. 

UPDATE: As Sean probably ran into below (in comments), the above screenshot does not show the required http-request-headers attribute required on the allow-from node of the policy file.  This is, however, updated in the Intellisense files and the code snippet template.  Thanks Sean for pointing out the screenshot is wrong here.

If you are implementing a completely public web service (open to anyone for cross-domain access), then the defaults will suffice.  When done changing the values, hit enter and you are done.  For those who are not keyboard shortcut masters and would be using a mouse to do all this, it might not be terribly faster to be honest (if the TAB,TAB implementation was there for XML snippets, it would eliminate the arrow up/down to navigate to the snippet).

Get the slcap.snippet here.

Visual Studio Intellisense Files

This next step is a super hack that I originally did and decided it might not be a good idea, but I'll include it here anyway :-).  This involves adding Intellisense files to your VS2008 installation and if you aren't comfortable with that, then move along.

First, you'll want to get the XSD I created, which is very simple and I'm sure doesn't fully conform to the final spec, but lacking that spec, it maps to the format well enough.  Copy the clientaccess.xsd file to the C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas location (or wherever VS2008 is installed for you).  Once you've done that you have to add an entry into the catalog.xml file to add the mapping.  Again, not this is my little hack so I created some namespace because there wasn't one defined yet.

Once you have those two files you have Intellisense for your clientaccesspolicy.xml file if you want it.  Following similar steps as above, create the new file.  This time, however, type the root node of <access-policy> but adding the 'xmlns' attribute pointing to the new namespace you just added to the catalog file (note: Intellisense should give you a list to choose from:

Once you have that, then you'll get the rest of the Intellisense for the basic format of the client access policy format.  If you have multiple allow-from/grant-to needs, this Intellisense will support it.

The only lame thing is you have my namespace in there :-).  That is what drives the Intellisense.  Right now you'll want to remove that before deploying the actual file.  Yeah, I know.  But I said this was an early hack of mine didn't I?

Get the Intellisense files here.

What do to with the completed policy file?

Either way, when you are done with the file, it needs to go in the ROOT of the domain.  This is important as it is not the application root, but the root web.  Even if your app is at foo.com/myapp, the policy file needs to be at foo.com/clientaccesspolicy.xml.

Anyhow, maybe these files will help you.  Ideally you won't be using/messing with an access policy file much, but this might save you some clicks and having the docs open next to you :-).

| Comments

In a previous post, I wrote about some samples of calling various types of services from Silverlight 2.  In the code, I was using constructors in my ASMX and WCF services with specifying a binding type and endpoint address.

It was called out to me that in other demonstrations, people did not use this construct.  While the method I demonstrated works (explicitly specifying the binding and endpoint), in some cases it may not be necessary.  One such case would be if you only have one endpoint and it is basicHttpBinding.

The error in my code/instructions was about changing the binding information in web.config.  The information is correct, however I wasn't clear on when/what you needed to do.  For example, the default information in web.config for the Silverlight project created for you uses wsHttpBinding.  If you add a service reference in your Silverlight project PRIOR to changing that binding information, your generated proxy will require you to specify a binding and endpoint as Silverlight doesn't support wsHttpBinding and it would be trying to use that as a default method.

So the appropriate way is to change the binding type in your web.config FIRST.  Then generate the service reference in your Silverlight application and your proxy code generated will then allow you to new up the service using:

WcfServiceClient wcf = new WcfServiceClient();

for both WCF and ASMX services...which is probably more familiar to most web developers implementing services in their applications.

Again, EITHER way is fine.  Providing no information in the constructor will use the default binding/endpoint information for that service, and if it isn't supported, you'll get a nasty exception.  Whether or not it is best practice to always explicitly call it out in your code is up to you.  I'd argue it is.  In looking at the code above do you know what binding/endpoint is being used at the time of the service call?  No.  You could make some reasonable assumptions (hey, I'm in Silverlight and I know I must use basicHttpBinding), but for maintainability, maybe someone else coming to the code doesn't have the same understanding.

To each his own.  Either way, I hope this clarifies and I've updated my post with the note about this as well.

| Comments

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?