(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

WCF Integration in Silverlight 2 Beta 1

(1 votes)
3 comments   /   aggregated from POKE 53280,0: Pete Brown's Blog on Mar 19, 2008   /   original article
Categories:   General

In preparation for my Silverlight for Business Applications webcast today, I decided to look more deeply into how Silverlight works with services. I originally concentrated a lot on security, and had a much larger post on how to secure your services, but ran into some issues there. More on that below.

WCF Service Requirements for Silverlight

In Silverlight 2 Beta 1, WCF services must be set up to use basicHttpBinding. Basic HTTP Binding sets up a SOAP 1.1 endpoint in your service. To enable that, before setting the service reference in your Silverlight application, change the service's web.config from the default wsHttpBinding to basicHttpBinding:

<system.serviceModel>
...
    <services>
        <service behaviorConfiguration="ServiceBehavior" name="Service">
            <endpoint address="" 
              binding="basicHttpBinding" 
              contract="IService">
                <identity>
                    <dns value="localhost"/>
                identity>
            endpoint>
            <endpoint address="mex" 
              binding="mexHttpBinding" contract="IMetadataExchange"/>
        service>
    services>
system.serviceModel>

 

If you forget to do that before adding a service reference, no big deal. Just refresh your service reference in your Silverlight project. If that doesn't work, remove and re-add the reference.

Enabling Exception Information in WCF

During debugging, you may want to get exception information back from WCF. In order to enable that, change the includeExceptionDetailsInFaults setting in the service's web.config to true:

<behaviors>
    <serviceBehaviors>
        <behavior name="TestServiceBehavior">
            <serviceMetadata httpGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
        behavior>
    serviceBehaviors>
behaviors>

Adding the Silverlight Service Reference

Once your WCF service is running, you can add a reference from your Silverlight project. To do that, right click the Silverlight project and choose "Add Service Reference". Be sure to change the namespace to something useful, as this is the namespace that will be appended to the Silverlight application's namespace.

image

To avoid dealing with cross-domain configuration right at the moment, I added the service to the test web project. This ensures that the service and the Silverlight app are served from the same server and port.

image

Cross-Domain Support

If you want to enable your service to work cross-domain, there are two files you will want to concern yourself with:

crossdomain.xml

This file comes from back in the macromedia flash days. Since it has wide support on the internet, it makes sense for Silverlight to support it. You can read some documentation on this file format here.

One use supported by the specification is to specify domains which can access the service:

xml version="1.0"?>
DOCTYPE cross-domain-policy 
  SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="www.yoursite.com" />
  <allow-access-from domain="yoursite.com" />
  <allow-access-from domain="*.moock.org" />
cross-domain-policy>

However, that detailed format is not supported by Silverlight. Instead, you must opt in to all domains if you want to use the crossdomain.xml approach. Such a policy file would look like this:

xml version="1.0"?>
DOCTYPE cross-domain-policy 
  SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*" />
cross-domain-policy>

However, since this format doesn't cover all the scenarios that Silverlight developers are likely interested in (and flash developers too, most likely), Microsoft has provided another cross-domain file that is more flexible and currently Silverlight-specific: clientaccesspolicy.xml.

clientaccesspolicy.xml

lf you want finer control over your cross-domain policy, you'll want to use clientaccesspolicy.xml. This file allows you to specify both what domains have access to your service, and also what subpaths are covered by the policy. You can include both clientaccesspolicy.xml and crossdomain.xml for your services; Silverlight will check this file before looking for the crossdomain.xml

The equivalent to the "allow all domains access to all services" is below:

xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="*"/>
      allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      grant-to>
    policy>
  cross-domain-access>
access-policy>

If you want to get more selective about what you enable, you can specify external domains and subfolders on your site:

xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="http://contoso.com"/>
      allow-from>
      <grant-to>
        <resource path="/public-services/" include-subpaths="true"/>
      grant-to>
    policy>
  cross-domain-access>
access-policy>

You can find additional information about cross-domain files on msdn.

Ian Griffiths discovered a small bug with the Silverlight-specific policy file in Beta 1, and documented it here.

Calling Your Service

The proxy and default configuration generated when you add the service reference will be adequate for your initial testing. The generated .ClientConfig file has specifics about your service. If you change your service, and refresh your reference, this file will be updated to reflect those changes. If you run into any problems with that, just delete the file, remove your service references, and re-add them.

ServiceReferences.ClientConfig File
<configuration>
    <system.serviceModel>
        <client>
            <endpoint 
                address="http://localhost:47879/SilverlightApplication2_Web/Service.svc"
                binding="basicHttpBinding" 
                bindingConfiguration="BasicHttpBinding_IService"
                contract="SilverlightApplication2.ServiceReference1.IService"
                name="BasicHttpBinding_IService" />
        client>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService" 
                         maxBufferSize="65536"
                         maxReceivedMessageSize="65536">
                    <security mode="None" />
                binding>
            basicHttpBinding>
        bindings>
    system.serviceModel>
configuration>

Note that the default endpoint has the address in the file. You can override this in code if you desire. However, since this is a configuration file, you'll probably want to change (and maintain) the endpoint address in the config here, prior to deploying your app to test/production.

The clientconfig file is deployed in the xap.

Calling Code
private void TestService()
{
    ServiceReference1.TestServiceClient client = 
        new ServiceReference1.TestServiceClient();
    
    client.GetTheValueCompleted += 
        new EventHandlerGetTheValueCompletedEventArgs>
            (client_GetTheValueCompleted);
    
    client.GetTheValueAsync();
}

void client_GetTheValueCompleted(
    object sender, 
    TempBizAppDemo1.ServiceReference1.GetTheValueCompletedEventArgs e)
{
    // act upon the information returned from the service
    // e.Result;
}

As you may already know, all service calls in Silverlight 2 Beta 1 are async calls. Getting data from a service is a two-step operation. First, you set up an event handler which will be called when the service completes. Second, you call the service async method.

There's a lot of controversy about requiring async calls in Silverlight, so it may be something that changes in the future. I'll make no value judgements on it here. However, the current async implementation has the broadest support across browsers and operating systems. It also helps to ensure that the UI thread is not blocked (the calls go through the browser network stack, which is typically on the UI thread), and the browser UI remains responsive. Since async calls are a requirement in Beta 1, we'll just take that as a given.

The nice thing is, once you are used to the async pattern, the code is nice. The event handler you get has strongly-typed event args that include the return value from your service in e.Result (there is no e.Result if your service is a void function or VB sub)

Next Steps

At this point, if you have some UI hooked up to view the results from your service, you should be all set to go ... assuming message-level security doesn't matter (and it doesn't in many many cases as proven by the proliferation of AJAX applications out there calling open services without any message-level security)

Security

When it came to dealing with security like I normally would in a WCF service-based application, I ran into a couple brick walls and ran out of time. I did learn about some other options that may work, though.

The current MSDN documentation on securing your services for Silverlight 2 Beta 1 clients can be found here. It's pretty light, though.

I'm still feeling my way around some of the security options available to us, including tokens and rolling custom encryption. Look for a follow-up post once that is all sorted out. In the mean time, continue to secure your services like you would for AJAX applications (transport-level, HTTPS, IIS-based auth for the entire application) and have your authentication happen outside of Silverlight. Developers coming from the desktop world and those currently doing service calls from ASP.NET server-side will likely not be satisfied with that, so I promise to provide some good examples in the future :)

Update: Tim Heuer also has a great post on this topic. Take a look at it when you finish up here. 

 

Share this post: Email it! | bookmark it! | digg it! | reddit!

Subscribe

Comments

  • -_-

    RE: WCF Integration in Silverlight 2 Beta 1


    posted by tintin on Jun 26, 2008 22:10

    Hello

    I  follow your steps but I bug in step add the silverlight service reference..

    I can't find service anywhere ......... i don't understand....

    May you help me

     

     

  • emil

    RE: WCF Integration in Silverlight 2 Beta 1


    posted by emil on Jun 26, 2008 23:10

    Did you started the service? Start the service first, copy the URL and then hit Go as shown in the picture above. Here is a more complete guide of creating and using WCF service in Beta 2.

  • -_-

    RE: WCF Integration in Silverlight 2 Beta 1


    posted by Voodoo on Aug 03, 2008 19:52

    Why can’t you access a Web Service using a SSL with Silverlight?

    This seems to be a big issue because most services you want to mash-up in your Silverlight application will be on a SSL Connection.
    Competitor application like Flex from adobe does allow SSL connections cross domain which I think will be a deciding factor on which one to use.
    I hoping this is just a issues with Silverlight 2 Beta 2

Add Comment

Login to comment:
  *      *