WCF Simplified Part 7: Hosting a WCF service using WPF
May 26, 2010 1 Comment
In the last post we saw how to host a WCF service using IIS. Today we’ll look at hosting a WCF service in a WPF application.
1. Add a new WPF Application project to the solution (built earlier),
2. Add a reference to the WCF Service Library,
And a reference to System.ServiceModel.
3. The XAML is simple, in the MainWindow.xaml add the code,
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="200"> <Grid> <Grid.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions> <Button Height="30" Width="120" Content="Start WCF service" Click="Button_Click" /> <Button Height="30" Width="120" Grid.Row="1" Content="Stop WCF service" Click="Button_Click1" /> </Grid> </Window>
4. And in the code behind, add,
public partial class MainWindow : Window { ServiceHost host; public MainWindow() { InitializeComponent(); this.host = new ServiceHost(typeof(WcfServiceLibrary1.Service1), new Uri("http://localhost:8003/HelloWCF")); } private void Button_Click(object sender, RoutedEventArgs e) { // Service host is opened on the UI thread host.AddServiceEndpoint(typeof(WcfServiceLibrary1.IService1), new WSHttpBinding(), "HelloWCF"); // Enable metadata exchange ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpGetEnabled = true }; host.Description.Behaviors.Add(smb); // Enable exeption details ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>(); sdb.IncludeExceptionDetailInFaults = true; host.Open(); // Keep track of the UI thread id this.Title = Thread.CurrentThread.ManagedThreadId.ToString(); } private void Button_Click1(object sender, RoutedEventArgs e) { host.Close(); } }
That’s it! We are now hosting a WCF service in a WPF application. As you can see the code is actually the same as what we used when hosting in a console application.
One important note – notice that we created the service host on the UI thread. To see this use the following service contract,
[ServiceContract] public interface IService1 { [OperationContract] string GetThreadData(); }
public class Service1 : IService1 { public string GetThreadData() { return Thread.CurrentThread.ManagedThreadId.ToString(); } }
And the corresponding client,
EndpointAddress epoint = new EndpointAddress("http://localhost:8003/HelloWCF/HelloWCF"); ServiceReference1.IService1 proxy = ChannelFactory<ServiceReference1.IService1>.CreateChannel(new WSHttpBinding(), epoint); using (proxy as IDisposable) { Console.WriteLine(proxy.GetThreadData()); }
Now connect multiple clients to the host and you’ll see that they are all on the same UI thread (the window title ‘10’ displays the UI thread id),
We probably don’t want the UI thread processing requests, it should only be for updating the UI. Another way is to start the service host before you start your UI thread. Now if you go back and change the UseSynchronizationContext to false (by default it is true),
[ServiceBehavior(UseSynchronizationContext=false)] public class Service1 : IService1 { public string GetThreadData() { return Thread.CurrentThread.ManagedThreadId.ToString(); } }
You’ll see something like,
This means that requests are processed on a different thread when UseSynchronizationContext is set to false. However if the service host was created on a non-UI thread to begin with then the UseSynchronizationContext settings doesn’t matter requests are always processed on a new thread.
See more WCF service hosting options here.
Pingback: WCF Simplified Series « I.Net