I’ve started a dialog with a few of you about getting Silverlight and service integration working, specifically with ASP.NET web services (and even WCF ones).  A few have downloaded some of my samples, but others have started from scratch.  A few have reported getting some interesting errors, ASYNC_blahblah and NotFound errors specifically.  While this was boggling my mind (as I wasn’t getting them), a reader’s comments pointed me along the lines of something…he mentioned “maybe it is because my web service is ASP.NET 2.0 and not 3.5” – of which that shouldn’t be the case, so I went to test that.

The Situation

Most of the samples you are likely seeing (including mine) are implementing web services within the same project that the Silverlight host is implementing.  What I mean to say is probably you are doing File…New…Silverlight Project and then incorporating the web service into the web site project that comes with that template.  If you do so, you probably aren’t running into problems.  Also note that the target framework of that default web site project is .NET 3.5.  This doesn’t make a difference, but I’m just noting it here.

But what if you have an existing service, or you have an existing web site project that you are running in Visual Studio and running into problems…and l think I know why…let’s investigate by doing this step-by-step.

The Web Service

First open an instance of Visual Studio 2008 and choose to create a new ASP.NET Web Service (I’m calling mine ‘FooService’).  Be sure to select .NET Framework 2.0 for this experiment:

Do nothing more to the service.  We’re just going to use the HelloWorld stub for this experiment.  We know we’re going to simulate a cross-domain situation so create a clientaccesspolicy.xml file at the root of this project.  You can use my snippet to do the default public policy quickly if you’d like, it’s wickedly cool and awesomely awesome.  I recommend it ;-).  Moving on… We are done here.  CTRL+F5 this bad boy to start it running (or select Service.asmx and view in browser) – we just need to get the service running.  Make note of the URL, it is likely http://localhost:XXXXX/FooService/Service.asmx where “XXXXX” is the random port assigned by VS.  Just note that URL.  Obviously if you didn’t call yours FooService, then it will be different.

The Silverlight Application

Start another instance of VS2008 and choose File…New…Project…Silverlight Application.  I’m calling mine FooApp.  Now, if you don’t see any of the Silverlight templates, just change the target framework back to .NET Framework 3.5 if you haven’t done so already.  Accept the default for creating the FooApp_Web project for you, we’ll need a host here anyway under HTTP.

Modify nothing in the Page.xaml file but add a service reference to the Silverlight application by right-clicking on the app and choosing ‘Add Service Reference.’  Put the URL of the ASP.NET 2.0 service (from previous step) in the box and click GO.  You should get it discovered and have ‘ServiceReference1’ as the name:

Just keep the lame name because we’re just playing around remember?  Now, go to Page.xaml.cs and add the following code:

public Page()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
    ServiceReference1.ServiceSoapClient proxy = new FooApp.ServiceReference1.ServiceSoapClient();
    proxy.HelloWorldCompleted += new EventHandler<FooApp.ServiceReference1.HelloWorldCompletedEventArgs>(proxy_HelloWorldCompleted);
    proxy.HelloWorldAsync();
}

void proxy_HelloWorldCompleted(object sender, FooApp.ServiceReference1.HelloWorldCompletedEventArgs e)
{
    try
    {
        TextBlock tb = new TextBlock();
        tb.Text = e.Result;
        LayoutRoot.Children.Add(tb);
    }
    catch (Exception ex)
    {
        string wtf = ex.Message;
    }
}

What we are doing here is calling the service (asynchronously of course) and wiring up the completion event to emit a new TextBlock with the result of the web service.  The Page() constructor just adds a Loaded event so we aren’t doing anything in the constructor to the XAML before it is done loading.

Okay, so we are done.  We have our web service with an appropriate clientaccesspolicy.xml file and it is running.  We have our Silverlight application with a service reference to that and proxy code generated.  We are using that proxy code to call the service, and use the result in a new TextBlock in our root layout element.  Sweet.  Put a breakpoint on the exception catch (should be line 37) and hit F5 (choose yes to enable debugging in web.config).

WTF?

Did you get ‘Async_ExceptionOccurred’ like I did?  Sonofa…  Maybe it is because I’m accessing an ASP.NET 2.0 service? No.  Maybe it is because my app is on port YYYY and my service is on port XXXX?  Nope.  Ah, cross-domain issues?  Try again.

Investigating the Problem

Okay, on to figuring out what is going on. 

If you are a web developer and you aren’t using an HTTP sniffing tool, shame on you.  This should be one of your biggest assets when doing web client development like Flash, Silverlight, AJAX, whatever.  For Microsoft developers there are usually 2 tools (both free) that come to the top: Fiddler and Web Development Helper.  I’m a HUGE fan of WebDevHelper (which I just noticed is on CodePlex now, cool Nikhil!) for 2 reasons.  First, it doesn’t require me to change my proxy settings or anything, which is a pain when using Fiddler and the built-in web server with VS because of the dynamic ports it uses.  Second, it is IN THE BROWSER!  I turn it on and I get an explorer bar at the bottom that shows me everything.  Me likey.

Ok, so using WebDevHelper I turn it on and spot the problem:

Spot it?  Remember our service was created on http://localhost:XXXX/FooService/Service.asmx?  If you read my previous post on cross-domain access (and soon a how-do-I video will be posted on this topic), you’ll note that the client access policy file must be at the ROOT of the service site. 

But Tim, it is!

Well, it is according to the file system, but look at the request Silverlight is making.  The problem here is the web development server in VS.  By default it not only grabs a random port, but also serves things up under a virtual directory (i.e., /FooService/Service.asmx instead of /Service.asmx).  So even though we have our policy file in the root, the web server isn’t treating our app like a root.  Notice the web service project properties:

The core problem was that it couldn’t find the clientaccesspolicy.xml file and thus denying the request to the service.

The Solution

For *this* scenario, the solution (or one of them, easiest in my opinion) is to change the service properties and just change the /FooService to “/” only.  This will restart the server for that project (browser to Service.asmx again just to make sure) and will then be operating under http://localhost:XXXX/Service.asmx

The next thing we need to do is go back to our Silverlight application and remove the service reference (as it is now invalid because the endpoint is no longer there).  Just select it and delete.  Choose ‘Add Service Reference’ again and point to the newly updated URL.  No need to change/delete the actual code in Page.xaml.cs because it will stay the same as long as you keep the SericeReference1 default name for this example.

Once you have that, F5 your Silverlight application again and you should see:

If we turn on WebDevHelper again we can see the policy file being requested and found, then the service call allowed through:

Again for this scenario (if you are playing around with Silverlight and just messing with services), this may be one of the issues you are running into.  A lot of the time cross-domain policy files may be the issue and that is why an HTTP sniffer is going to be your best friend to see what request is failing and why.  Even though this is an ASMX sample, if you were testing with a WCF service hosted in an ASPNET web site and running under VS2008 web development server, you'd likely run into the same issue.

Hope this helps!

In my previous post about cross-domain policy files I received some comments about whether or not cross-domain access is allowed on Silverlight Streaming.  I think really this is two questions that I'll try to clarify here.

What is Silverlight Streaming?

For those who don't know, Microsoft provides anyone with an account to "stream" Silverlight applications for free.  We'll give you 10GB of space to put your Silverlight applications.  There are some limitations, which you can read about in the service.  The "streaming" name has confused some.  It isn't only a "where can I put media files" location, but is a service to "stream" your entire Silverlight application.  You can have a media player, or a hello world textbox...no matter.  If you haven't checked it out, sign up.

Does Silverlight Streaming support cross domain calls from Silverlight?

This really has to do with the Silverlight Streaming API.  Silverlight Streaming provides an API to manage your applications.  You can perform various activities on your Silverlight Streaming account through this API such as managing your applications, requesting files, etc.

Now I'm not sure why you would want to access the API from a Silverlight application, but I will say that the in order for this to happen (as noted in my post about cross domain access), the service would have to host a policy file at the end point.  Silverlight Streaming currently does not have that policy file.

Can my application hosted in Silverlight Streaming access cross domain services?

This is what I think the question really is in the comments.  Yes.  Provided that the service you are accessing has a clientaccesspolicy.xml file at the root of the site, then yes it could.  I whipped up a quick DataGrid sample and put it on my Silverlight Streaming account.  This is a Silverlight 2 application (xap) that calls the MSN Video POX service via a WebClient call.  I take the information and bind it to a DataGrid.  So this application below is hosted in Silverlight Streaming, calling a 3rd party service (which has a policy file enabled) and embedded within my blog post here.

I hope that makes it a little clear that yes you can do this with your apps.

How did you get a Silverlight 2 application on Silverlight Streaming?

Very easily.  Just a bit after MIX08, the SLS team added support for Silverlight 2 Beta 1 applications.  You can read about it here, but here is the manifest I used for the application you see above:

<SilverlightApp>
   <version>2.0</version>
   <source>StreamingCrossDomain.xap</source>
</SilverlightApp>

I added that manifest.xml and my StreamingCrossDomain.xap file to a zip, uploaded it to my account and done.

Hope this helps!

Je viens en Belgique pour MIX!

MIX Essentials Logo In one of my previous posts I made reference to the MIX Essentials event happening in Belgium later this month (24 APR).  Well, it turns out that I will be there!  I'll be speaking on Silverlight 2 and creating rich applications and am joining the company of Gil Cleeren and Catherine Heller...oh yeah and Ballmer (I tried to catch a ride with him, but couldn't cash in my frequent flyer miles).  My session will provide an overview of everything new in Silverlight 2 and how you can start building your applications using it today.  I'm hoping you all that will be attending will bring some great questions and not throw anything at me (unless it is euros, those are fine). 

I've only had one other trip to Europe ever (to Italy) and am looking forward to going to Belgium.  Everything I know about Belgium is from a recent show on Food TV, so I'm looking forward to some education :-)!  So I'm taking some travel tips from Scott Hanselman and getting things in order (already have the monster cable thanks to my peep Jason Mauer and I, too, highly recommend that one).  I look forward to seeing you there!

Firs, thank you for all that came to the presentation in Anaheim.  The room was full, and hopefully you learned something while there (and hopefully it was along the lines that video in text boxes might not be good design, but is doable :-)).

I got a bunch of really great questions and concerns and hopefully answered all of them that were asked.  I saw many more hands lifted than we could get to, so if you have more questions, feel free to send them to me, or join the forum discussions as well!  The Silverlight community site is a great resource for learning, getting the tools, and participating in the conversation...head there today and bookmark!

I was asked to post the code from my presentation, so I'm doing it here.  You can download the solution here.  You'll need Visual Studio 2008, Silverlight 2 Beta 1 SDK, and the Silverlight tools to successfully run the application.  The only files not included there are the media files from the first demo.  Just add a few WMV files into the web applications /ClientBin directory and change the MediaElement attributes in the LameStuff.xaml file if you want to mess around with it.

The sample loads the final solution we had, but I also included the LameStuff.xaml file from the first demo.  If you want to play around with that, look in the App.xaml.cs file and change lines 29/30 to load the appropriate RootVisual. 

I hope you enjoyed seeing some things and wished we could have gone into another hour of cool stuff, like showing how the DeepZoom technology (what I used in my initial 'powerpoint') is composed.  Please feel free to subscribe to my site as I'll be doing a lot around Silverlight here!

If you aren't a developer, move along.

If you are and have ever done COM/COM+ development.  You are already chuckling.