| Comments

In the Silverlight world, there are two types of “cross-domain” things that may leave some banging their head against a wall for a while.  The first involves making network-based calls (WebClient, HttpWebRequest, etc) to services hosted on a domain other than the one that is the site of origin for the XAP.  This is solved by ensuring the service provider enables a clientaccesspolicy.xml file for their service.  More information here: Cross Domain Policy Files with Silverlight.

NOTE: “site of origin” is a term you might see a lot with regard to Silverlight.  This refers to the URI domain of the Silverlight XAP file.  For example: http://apps.mysite.com/sources/coolapp.xap might be a URI that you have for an app.  The site of origin in this is apps.mysite.com (more specifically it is actually the entire URI usually when people refer to this term).  This might help when you read things about cross-domain issues.

The second issues is one of hosting Silverlight applications (XAPs) on your site that are from a different domain.  What I mean here is that your site (www.coolwebapp.com) has an <object> tag for Silverlight plugin that has the Source parameter set to apps.anothersite.com/foo.xap.  This is essentially the cross-domain hosting situation.  What happens in this situation is that the plugin loads but the app does not, presenting in just a big blank space where the app should be.

A recent head-banger sent me a note and I sent him my items to check on how to solve this.  I thought I’d share.  When I see issues with this, I normally tell people to check for one (or more) of three things:

HTML Access

If the Silverlight application is doing anything to work with the HTML DOM of your hosting page, this is the first place to look.  Don’t know if this is happening?  If the Silverlight application uses System.Windows.Browser anywhere it likely does.  By default the tools and templates from Visual Studio generate the bar minimum <object> tag.  There is one property of the plugin, EnableHtmlAccess, that is set (essentially) to true for same-domain applications.  However, for cross-domain applications, you will need to opt-in for this adding this parameter to the <object> tag:

   1: <object data="data:application/x-silverlight-2," type="application/x-silverlight-2">
   2:   <param name="source" value="http://apps.somesite.com/foo.xap"/>
   3:   ...
   4:   ...
   5:   <param name="enableHtmlAccess" value="true" />
   6: </object>

By doing this, you are granting the XAP access to the HTML DOM of the hosting page.  Don’t say I didn’t warn you.

XAP MIME type

When the plugin loads a XAP from another domain, it checks what the MIME type is.  If it is not a valid Silverlight type, it won’t load the app.  This is a security mitigation.

If you are loading a cross-domain XAP, make sure the site delivering the XAP is delivering it with the appropriate MIME type: application/x-silverlight-app.  By default this is set in IIS7/Windows 2008, but not in IIS6/Windows 2003.  You can put this on the server level or the application level…wherever you feel comfortable, just as long as it is delivering it with the XAP. 

Obviously on non-Windows servers, this will not be set at all regardless of the version.  If you are getting a XAP from a Linux/Apache server for instance, the server administrator will want to add the type.  This is simple and you can do it at the global level in the mime.types file.  Or on a per-site basis you can do it by editing the .htaccess (or creating one) in the directory level that will serve the XAP and add:

   1: AddType application/x-silverlight-app xap

If you are using a CDN like Azure or Amazon S3 or something else and they don’t have the type associated, you will need to be creative.  Most CDNs enable you to set the MIME type (or Content-Type) on the file during upload.  For Azure, Silverlight should already be there.  For something like S3, tools like CloudBerry Explorer enable this feature for you (and actually already have a list of types built-in to their tool).

This situation (identifying the MIME type) can be quickly tested using a tool like Fiddler to see what the response and Content-Type are being delivered.  Fiddler is an indispensable tool…go get it, it’s free.

ExternalCallersFromCrossDomain

This is the black hole property right here.  This one is probably a last resort for most.  This property, in the Deployment node of your AppManifest.xaml file controls Javascript and HTML DOM access to scriptable objects defined in the XAP.  Like EnableHtmlAccess, for same-domain situations the setting is irrelevant, but in cross-domain hosted XAPs, the default is the NoAccess option.

To enable this you’ll need to manually edit the AppManifest.xaml file to add the ExternalCallersFromCrossDomain attribute.  There are two properties: NoAccess (default) and ScriptableOnly.  You’d want to *add* the attribute and set it to ScriptOnly.

   1: <Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" 
   2:             ExternalCallersFromCrossDomain="CrossDomainAccess" .../>

REMEMBER: This is is only if you need to.  Read the documentation to see if this applies to your scenario.

Summary

Sometimes debugging this stuff can be tricky. Having the tools and knowledge makes this easier to track down. Not all situations involve multiple of the above and if none of them fix it, then you might have another issue. Hopefully this helps provide some places to look.


This work is licensed under a Creative Commons Attribution By license.

| Comments

Now that Silverlight 2 has been released, one of the features (or should I say fixes) that is included is the ability for non-secure applications to call secure services.  Previously this was not allowed and we referred to it as “cross-scheme violation.”  That means that a particular protocol scheme (file, http, https) could not access another.  Prior to release this meant that a XAP hosted in an HTTP context could not call a secure service.  Now we no longer have that restriction with the release.  There are some things you have to do, so let me take a brief moment to demonstrate.

First, let’s assume this environment:

We have our application that is served from our web server via HTTP.  so our site is hosting the app on http://foo.com/MyApp.XAP.  Our service is hosted on a secure endpoint which represents our segmented API. 

NOTE: For sake of simplicity and lack of “real” hardware to actually segment out a totally representative environment.  Translated: I only have one SSL certificate and wanted to keep hosting simple…the important note is that we have two separate domains.

And what we have created here is a double-whammy – a cross-domain, secure service request.  So even though when you look at the diagram above, you might ask isn’t the client machine making the request?  Yes, but from an application with a different source-of-origin, which is what creates this scenario.  Let’s continue, shall we?

Prior to release, this simply wasn’t enabled yet.  Now that it is enabled, we can have our MyApp.xap application call our secure service (in this example is a SOAP service hosted in ASP.NET).  In Silverlight 2, the service owner still has to opt-in for this to occur.  We make use of the clientaccesspolicy.xml file which is leveraged for cross-domain scenarios (more information about cross-domain and policy files can be found here including a code snippet for Visual Studio to generate them).  In our case here we need that to support our cross-domain scenario anyway, but we’re also going to leverage it to enable non-secure callers to our service. 

Let me make that clear:  even if your secure service was hosted on the same domain as your non-secure caller, you would still need a policy file in place to enable non-secure callers.

What does the clientaccesspolicy.xml file look like then?  Here’s what we’re using for our application:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <access-policy>
   3:   <cross-domain-access>
   4:     <policy>
   5:       <allow-from http-request-headers="SOAPAction">
   6:         <domain uri="http://*"/>
   7:         <domain uri="https://*" />
   8:       </allow-from>
   9:       <grant-to>
  10:         <resource include-subpaths="false" path="/"/>
  11:       </grant-to>
  12:     </policy>
  13:   </cross-domain-access>
  14: </access-policy>

Now that this is in place, we’re done.  Notice the two (2) domain nodes there?  I couldn’t have just put “*” in there as we require you to explicitly allow non-secure callers in this scenario.  And once you do that, if you didn’t add the secure callers (https://*) then you’d leave them out.  So although it looks a little weird (as if to say Tim, in my mind that reads “*”), it is correct.  That’s right, there isn’t anything more you need to do.  Our code would look the same.  When we add a service reference to our Silverlight application, you’ll see that the ServicesReferences.clientconfig makes note of the secure transport:

   1: <configuration>
   2:     <system.serviceModel>
   3:         <bindings>
   4:             <basicHttpBinding>
   5:                 <binding name="fooSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
   6:                     <security mode="Transport" />
   7:                 </binding>
   8:             </basicHttpBinding>
   9:         </bindings>
  10:         <client>
  11:             <endpoint address="https://www.timheuer.com/foo.asmx" binding="basicHttpBinding"
  12:                 bindingConfiguration="fooSoap" contract="Bar.fooSoap" name="fooSoap" />
  13:         </client>
  14:     </system.serviceModel>
  15: </configuration>

Here’s the rest of the code I’m using in XAML:

   1: <UserControl x:Class="XDomain.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     Width="300" Height="300">
   5:     <Grid x:Name="LayoutRoot" Background="White">
   6:         <StackPanel>
   7:             <TextBox x:Name="MyName" FontSize="24" />
   8:             <Button Content="Repeat" FontSize="24" Width="150" Height="50" 
   9:                     Click="Button_Click" />
  10:             <TextBlock FontSize="24" x:Name="RepeatedName" />
  11:         </StackPanel>
  12:     </Grid>
  13: </UserControl>

and the code for the event handler on the button:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12:  
  13: namespace XDomain
  14: {
  15:     public partial class Page : UserControl
  16:     {
  17:         public Page()
  18:         {
  19:             InitializeComponent();
  20:         }
  21:  
  22:         private void Button_Click(object sender, RoutedEventArgs e)
  23:         {
  24:             Bar.fooSoapClient foo = new XDomain.Bar.fooSoapClient();
  25:             foo.SayMyNameCompleted += (sdr, args) =>
  26:                 {
  27:                     RepeatedName.Text = args.Result;
  28:                 };
  29:             foo.SayMyNameAsync(MyName.Text);
  30:         }
  31:     }
  32: }

So there you have it.  Add a simple policy file and you are enabled!  I hope this helps!  You can download a copy of this VS project here: XDomain.zip

| Comments

An important note for those using Sockets in Silverlight 2.  In beta 1, Sockets were limited to site-of-origin (meaning you could only connect back to the same host that served up the Silverlight application).  This has changed in beta 2 to allow your Silverlight application to connect to any server exposing some Socket connections.

One important note, however, is that a policy implementation has been added.  This policy implementation affects not only cross-domain Socket calls, but site-of-origin ones as well.  So if you are using Sockets, you must have a policy implementation in place.

The policy implementation is done via a similar file mechanism as HTTP-based cross-domain requests.  The policy file looks similar and here is a basic example:

<?xml version="1.0" encoding ="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="file:///" />
      </allow-from>
      <grant-to>
        <socket-resource port="4502-4506" protocol="tcp" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>
Notice how you can restrict the ports here (note: Sockets in general in Silverlight are limited to ports 4502-4534).

This policy information must be made available on a TCP port request on port 943.  Any Socket request will first look for that policy information to respond on this port 934 request.  If successful, the remaining communication will be allowed.  If not, the communication will fail.

UPDATE: I accidentally typed "934" originally as the port -- it is 943.

There is no code change you need to have in your current Socket implementation other than implementing a Socket policy server to respond to the policy request.  I’ll be covering the basics of sockets on a video over on the Silverlight community site which will demonstrate and provide code on doing this implementation.  Stay tuned for that one.

Hope this helps.

| Comments

We were all jumping for joy when Silverlight 2 beta 1 was released and the ability to connect to services was more readily/easily available to us.  For discoverable services that provided a WSDL we were quickly able to implement them using the Add Service Reference capability in Visual Studio 2008.  Beta 2 brings a few changes to the world of services that you should know about.  I’ll do my best to recap some of them here.

Generating a WCF Service

In beta 1 when we created a WCF service for use in Silverlight, we used the “WCF Service” template in Visual Studio (assuming you used Visual Studio).  This was fine and created a standard WCF service for us.  There were a few changes that we had to make to ensure that our Silverlight application could consume it in an acceptable manner.  First, we had to change the binding configuration in ASP.NET web.config from wsHttpBinding to basicHttpBinding as Silverlight only supports that binding type right now.  Secondly, we might have had to add capabilities to enable ASP.NET compatibility support depending on what we were doing with the service.  In beta 2, this process gets a bit simpler for services specifically built for Silverlight.  After you install the tools for Visual Studio, you now get a new item type:

It is important to note that the WCF Service template is still a perfectly acceptable one to choose, you just have to ensure to make those changes accordingly.  The new Silverlight-enabled WCF Service basically does those for us as well as add the ASP.NET compatibility attributes for us in the code.  Additionally, the traditional interface/implementation is simplified into a single class.  Again, the other ways are still valid, but for services specifically built for Silverlight, this might be an easier route to get them done.

Cross-domain policy file updates

Cross-domain restrictions still apply within beta 2 and the same rules apply.  There is one subtle change that is required to your clientaccesspolicy.xml file that is required.  In the allow-from node of the policy file, the attribute http-request-headers is now required.  If your service is an open/public one then specifying “*” is probably acceptable (you’ll have to be the judge of that.  If you only wanted to allow specific headers (besides the blacklisted ones) you can provide those in a comma-separated list and can use wildcards as well.  For example you could use X-MyApp-* if you wanted.

Another thing to note about the support for Adobe’s crossdomain.xml policy file is one thing we found in interpretation of the policy template.  Previously Flash was a Macromedia product and as such that file is adorned with a DOCTYPE that represents a schema with macromedia in it.  Well, Adobe has changed the schema a little bit and also updated the DOCTYPE to reflect Adobe as the authority.  Right now, Silverlight still expects to validate the macromedia declaration.

ServiceReferences.ClientConfig

In beta 1, when you performed the Add Service Reference operation a file named ServiceReferences.ClientConfig was created and had some configuration information in it.  This file, however, wasn’t really used.  In beta 2, this configuration file can be shipped with your XAP and used as configuration.  It provides a subset of WCF configuration.  Refined details of those settings are in the SDK, but I thought it might be helpful to know.

Change to WebClient

In beta 1, WebClient was the easiest library to use in accessing non-discoverable services.  One challenge was that it only supported GET verb requests.  In beta 2 WebClient has changed to enable POST verb actions as well.  the UploadStringAsync function will send the request but the endpoint URI must be a URI that accepts the POST verb.

In addition, WebClient is now callable on a background thread in addition to the UI thread.  This may come in handy for some situations.

I see these as small but helpful changes.  Most are based on feedback we received from beta 1 customers and community, so thank you for that feedback.  I hope this helps!

| Comments

So you want to read an RSS/Atom feed on the interwebs and saw the SyndicationFeed class you could use in Silverlight to give a nice RIA display of the syndicated data.  Great, no problem right, just wire up an WebClient, point it to the RSS feed on something like http://silverlight.net or something and boom, done.  Wait, what’s this 404 Not Found error?  In most cases this is going to be a result of a cross-domain issue.  If you haven’t started working with services yet, Silverlight requires a cross-domain policy file to be in place to access remote data not on the same site-of-origin of the Silverlight application.

If you want to learn more about this in further detail you can read this and view this.

Crap.  So now what do you do?  You don’t have a server that would enable you to write a proxy service and you don’t really have the time to do that.  Aha, enter some free services for you!

Popfly

First, depending on what you are trying to do with the data, give Popfly a look.  Popfly contains several templates for importing syndicated information and displaying it in different visualizations.  For instance in about 4 clicks I can import an RSS feed, connect it to a visualizer and have this:

Popfly is no longer available as a service from Microsoft.

Feedburner and Yahoo! Pipes

Pipes is similar to Popfly but doesn’t really provide a breadth of possibilities of visualizations and ease of mashup of way different types of sources, but for this purpose I think it works well.  In Pipes, you can create an input feed and map it to an output, even merging various sources together.  The end result can be a new RSS feed for you.  And Yahoo Pipes already has a cross-domain policy file in place for Flash (which Silverlight supports).  You have to change your endpoint URI a little bit and it wasn’t clear until I searched, but for example, here is a RSS feed URL you could use for combining my blog and the Silverlight community blogs in one.

Feedburner is a syndication service that does a lot of statistics of your feed, helps you manage subscriber data and can save you some bandwidth as well.   It does RSS really well (and enclosure support, etc).  Best of all, it also supports cross-domain policies via the Flash format (again, which Silverlight supports). 

So if you find a feed that is on a site without cross-domain policy support, you can create a new Feedburner feed, Yahoo Pipe or Popfly mashup and be good to go!

A subtle workaround for getting data from sites that aren’t providing the policy files :-)

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.