Mantracker
Mantracker

Reputation: 613

How to make Simple WCF Service work in WPF Application?

I've been following tutorial here and trying to host a simple REST Server using WCF. Basically, I created the WCF interface and class file as described in the tutorial:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebInvoke(Method = "GET", UriTemplate = "/GET/{msg}/{msg2}")]
    string GetRequest(string msg, string msg2);

    [OperationContract]
    [WebInvoke(Method = "PUT", UriTemplate = "/PUT/{msg}")]
    void PutRequest(string msg, Stream contents);
}

and the concrete class:

class Service : IService
{
    static string Message = "Hello";

    public string GetRequest(string msg, string msg2)
    {
        return Message + msg + msg2;
    }

    public void PutRequest(string msg, Stream contents)
    {
        Service.Message = msg + msg + msg;

        string input = new StreamReader(contents).ReadToEnd();
        Console.WriteLine("In service, input = {0}", input);
    }
}

These 2 WCF service classes work perfecting in a Console Application I created. Here is how "Main" looks like. When I submit a GET request to the Console Application, I get a 200 OK:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
             using (var host = new ServiceHost(typeof(Service)))
             {
                 var ep = host.AddServiceEndpoint(typeof(IService), new   WebHttpBinding(), new Uri("http://1.10.100.126:8899/MyService"));

                 ep.EndpointBehaviors.Add(new WebHttpBehavior());
                 host.Open();
                 Console.WriteLine("Service is running");
                 Console.ReadLine();
                 host.Close();
             }
        }


    }

}

However, when I want to use those 2 classes in a WPF Application, they don't work anymore. Here is the MainWindow class for the WPF Application. When I submit a GET Request to the WPF Application, I get error 502 BAD GATEWAY:

namespace WpfApplication1
{

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            using (var host = new ServiceHost(typeof(Service)))
            {
                var ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), new Uri("http://1.10.100.126:8899/MyService"));

                ep.EndpointBehaviors.Add(new WebHttpBehavior());
                host.Open();
                Console.WriteLine("Service is running");
                Console.ReadLine();
                host.Close();
            }
        }
    }
 }

How do you make those 2 WCF classes work with a simple empty WPF Application project? Why does those 2 WCF classes work with an empty Console Application project, but not an empty WPF Application Project?

Upvotes: 1

Views: 2539

Answers (1)

Dan Field
Dan Field

Reputation: 21641

Giving you a complete, thorough answer on how to properly host a WCF service properly in a WPF application is really a bit too broad, but here are some pointers.

You have a few major problems with your WPF attempt:

  1. You're attempting to host the service on the UI thread, a big no-no in GUI design and programming. If you got it working the way you have it, you'd lock your UI and the user wouldn't be able to do anything but force-close your application.
  2. You're handling it all in a code behind for a Window - WPF encourages the MVVM pattern, which guides you to separate concerns of how your view (window, controls, etc.) is rendered vs. what services are used/hosted/consumed.
  3. You're attempting to block the thread by using Console.ReadLine() in a GUI application, where there is no Console listening - so Console.ReadLine() is just returning immediately (but if you did manage to block the thread, you'd be back to problem #1).

For a full tutorial on how to do what you're attempting with better design principles, see the following blog

Some highlights from that:

  1. Create some controls (e.g. buttons that say 'Start' and 'Stop') to start and stop your service.
  2. Wire up those buttons to the logic to start your service and stop your service respectively.

There's definitely improvements that could be made there - starting and managing the lifetime of the service, using the Commanding model in WPF, using the TPL or a BackgroundWorker to run the service in a different thread, making fuller usage of the MVVM pattern - but it's a start.

Upvotes: 3

Related Questions