For convenience, I post the sample's readme file here, someone who have interest on this sample could download 1Code latest release.
Creation
To demonstrate silverlight accessing WCF, we may need a WCF service and a Silverlight WCF client. Here we separate the creation progress into three tasks:
- Creating Duplex WCF service with netTcpBinding
- Creating Silverlight WCF client
- Deploying cross domain policy file
1. Create a new console project "NetTcpWCFService", add a new WCF Service to project, named WeatherService.
2. Open IWeatherService.cs, define the service contract like this:
namespace NetTcpWCFService { [ServiceContract(CallbackContract=typeof(IWeatherServiceCallback))] public interface IWeatherService { [OperationContract(IsOneWay = true)] void Subscribe(); [OperationContract(IsOneWay = true)] void UnSubscribe(); } public interface IWeatherServiceCallback { [OperationContract(IsOneWay=true)] void WeatherReport(string report); } }3. Open WeatherService.cs. We use static event approach to implement subscription service.
First, prefix the ServiceBehavior to the existing WeatherService class, set InstanceContext mode to PerSession. Then, replace the default contents of the WeatherService class with the following:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class WeatherService : IWeatherService { static event EventHandler4. Create a separate thread to generate fake weather report periodically.WeatherReporting; IWeatherServiceCallback _callback; public void Subscribe() { _callback = OperationContext.Current.GetCallbackChannel (); WeatherReporting += new EventHandler (WeatherService_WeatherReporting); } public void UnSubscribe() { WeatherReporting -= new EventHandler (WeatherService_WeatherReporting); } void WeatherService_WeatherReporting(object sender, WeatherEventArgs e) { // Remember check the callback channel's status before using it. if (((ICommunicationObject)_callback).State == CommunicationState.Opened) _callback.WeatherReport(e.WeatherReport); else UnSubscribe(); } } class WeatherEventArgs:EventArgs { public string WeatherReport{set;get;} }
static WeatherService() { ThreadPool.QueueUserWorkItem( new WaitCallback(delegate { string[] weatherArray = { "Sunny", "Windy", "Snow", "Rainy" }; Random rand = new Random(); while (true) { Thread.Sleep(1000); if (WeatherReporting != null) WeatherReporting( null, new WeatherEventArgs { WeatherReport = weatherArray[rand.Next(weatherArray.Length)] }); } })); }5. Configure the app.config file to add netTcpbinding endpoint to WCF service.
Note that, only a few ports are allowed to be accessed by Silverlight, that is 4502-4534, and we need client access policy file to permit Silverlight access, please refer to Deploying cross domain policy file
6. Start the ServiceHost in Main method
static void Main(string[] args) { using (var host = new ServiceHost(typeof(WeatherService))) { host.Open(); Console.WriteLine("Service is running..."); Console.WriteLine("Service address: "+host.BaseAddresses[0]); Console.Read(); } }
Creating Silverlight WCF client
Now, create Silverlight application to consume the WCF. We need one button to subscribe/unsubscribe servicie, and one listbox to display the weather report from service.
1. Create a new Silverlight project.
2. Open MainPage.xaml, Add Button, TextBlock and ListBox to MainPage and adjust layout.
3. Add Service Reference to our “weatherService” WCF service. To do this: First, set NetTcpWCFService project as startup project, press Ctrl+F5 to start the service. Then, right click Silverlight project, select “Add Service Reference”, in dialog, input the weather service address, and press OK. After done this, VS would generate wcf proxy code in Silverlight project.
4. Open MainPage.cs file, Initialize the WCF proxy in Loaded event
public partial class MainPage : UserControl,IWeatherServiceCallback { public MainPage() { InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded); } bool _subscribed; WeatherServiceClient _client; void MainPage_Loaded(object sender, RoutedEventArgs e) { _client = new WeatherServiceClient( new System.ServiceModel.InstanceContext(this)); _client.SubscribeCompleted += _client_SubscribeCompleted; _client.UnSubscribeCompleted += _client_UnSubscribeCompleted; } void _client_UnSubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error == null) { _subscribed = false; btnSubscribe.Content = "Subscribe weather report"; tbInfo.Text = ""; }else tbInfo.Text = "Unable to connect to service."; btnSubscribe.IsEnabled = true; } void _client_SubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error == null) { _subscribed = true; btnSubscribe.Content = "UnSubscribe weather report"; tbInfo.Text = ""; } else tbInfo.Text="Unable to connect to service."; btnSubscribe.IsEnabled = true; } // Display report when callback channel get called. public void WeatherReport(string report) { lbWeather.Items.Insert( 0, new ListBoxItem { Content = string.Format("{0} {1}",DateTime.Now, report) }); } }5. Add event handler to handle button click event
private void Button_Click(object sender, RoutedEventArgs e) { if (!_subscribed) { _client.SubscribeAsync(); } else { _client.UnSubscribeAsync(); } btnSubscribe.IsEnabled = false; }Now, the Silverlight WCF Client is completed. We have one last task to permit the Silverlight access.
Deploying cross domain policy file
1. Create a xml file, named "clientaccesspolicy.xml", set content as below
This file grant permissions to allow Silverlight clients from any domian to access server's 4502-4506 port.
2. Find out the server web site's root physical path (by default, C:\inetpub\wwwroot), place the policy file in that folder. To varify the deployment, browse http://localhost/clientaccesspolicy.xml, check if you could see the policy xml content.
Demo
To test the project
1. Open CSSL4WCFNetTcp solution, build.
2. Start the duplex WCF. Run NetTcpWCFService.exe, it's under CSSL4WCFNetTcp\NetTcpWCFService\bin\debug folder.
3. Right click "CSSL4WCFNetTcpTestPage.aspx" in VS, Select "View in Browser".
4. When Silverlight application loaded, click "subscribe" button, if all code and configuration is correct, you may find the listbox displaying a new record in each second.