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.
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.
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 EventHandler<TempBizAppDemo1.ServiceReference1.GetTheValueCompletedEventArgs>
(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 :)
[Post written as of Silverlight 2 beta 1 and Expression Blend 2.5 march preview]
Strange that the DataGrid is not in Expression Blend 2.5 march preview toolbox, but only in VS2008 !?
If you add a DataGrid in VS2008 and then switch to Blend that will break your designer.
It seems like there are problems with these assemblies references in Blend 2.5:
System.Windows.Controls.dll
System.Windows.Controls.Data.dll
System.Windows.Controls.Extended.dll
Remember that controls are not part of the runtime, they are part of
the SDK and must be distributed with each application. Here are the
different folders:
- Runtime: "C:\Program Files\Microsoft Silverlight\2.0.30226.2"
- SDK: "C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client"
Thanks to Michael Sync from the Silverlight forums, you can fix this:
1. Fix the reference in Blend:
Add reference to "System.Windows.Controls.Data.dll" from the SDK folder.
2. Add this markup in <UserControl declaration:
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
3. then, you can add a DataGrid like that:
<data:DataGrid></data:DataGrid>
Now you can find the DataGrid in Blend 2.5 Toolbox :
- Click on "Asset Library" (bottom of toolbox)
- Check "Show All"

昨天,朋友将自己两年来写的BLOG印成书赠与我做纪念。看到这本装订精美的书,我客气道:“哟,您的大作变成铅字,我得专程到书店里花钱买才能表达诚意
啊!怎么好意思让您送呢?”朋友却说“你看仔细了,这是书店买不到的啊。”我再细细看这书,上边没有售价、也没有出版社,朋友说,这是她为自己印的书,只
为纪念、不为出名。。
超印速是国内一个提供“个性印书,一本起印”服务的网站,或者可以叫做网上出版便利店。也就是任何人都可以在线定制,出版你自己个人的出版物。
提供的服务主要有:在线印书,相册,日历服务等。超印速使用很简单,只需要上传你排版好的作品,每次可同时上传三个文件,容量不能超过50M。持文件格式:DOC,WRI,TXT,P64,PDF,JPG,BMP,RAR,ZIP。可以上传封面和封底图片。如果让超印速帮你排版会收取额外的费用。你可以通过这个页面查看在线印刷需要的价格。一个平装,32开,彩色封面,50页黑白内页的价格为24.7元。
目前,在“超印速”下订单的博客书种类非常多。有的就像日记,记录下个人情感、生活琐事,没有很明确的主题,有时候甚至整篇文章只是一个字的问候语罢了,
这些作者来“超印速”印书的主要目的是为了让作品原汁原味保留下来。当一个博客作者慢慢地写了很多东西以后,可能会开始考虑如何保存自己这段时间以来的文
字和心情。

当然,博客本身有选择备份的功能,或者作者可以自行购买空间的数据库导出功能,但这类功能备份出来的只是一些没有生气的代码、
文本或者压缩文档文件,远远没有博客本身图文并茂那么吸引人。一些博客作者想让以前的作品以最初的图文结合形式保留下来,于是就决定将其印成一本精美的
书。
此外,你还可以通过推荐你的好友使用超印速的服务获得积分,每推荐一个用户,你就可以获取100的积分,1000点积分可以兑换1元人民币。你可以通过这些积分来在线印刷自己的出版物。