How to debug a WCF service

Introduction

WCF default debugging does not support edit and continue features, as I have said in my blog post

Background

In that post I said that there is an easy way to do it, but I didn’t give any code. So this article is about how to it. The reason I wrote this article, is because a fellow member wrote a useful article about wcf, and in tip1 he suggested using a console application.

My scenario for wcf service consuming and debugging is a Client Server application. I believe my solution can apply and for other scenarios.

How to do it

You need this class DebugServiceHost

internal class DebugServiceHost:IDisposable
{
    private static string serviceExecuteTypeName = "ExecutionService.ServiceExecute, ServiceSide.ExecutionService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
    private static string iServiceExecuteTypeName = "ExecutionService.IServiceExecute, ServiceSide.ExecutionService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
public static string Address = @"http://localhost:9999/ExecutionService/ServiceExecute/";
    public static Binding Binding = new WSHttpBinding();
    
    static DebugServiceHost()
    {
        isEnabled = Type.GetType(serviceExecuteTypeName) != null;
    }
    public DebugServiceHost()
    {
        Type serviceType = Type.GetType(serviceExecuteTypeName);
        Type iServiceType = Type.GetType(iServiceExecuteTypeName);
        this.debugHost = new ServiceHost(serviceType);

        this.debugHost.AddServiceEndpoint(iServiceType, Binding, Address);
        this.debugHost.Open();
    }

    private System.ServiceModel.ServiceHost debugHost;

    private static bool isEnabled = false;
    public static bool IsEnabled
    {
        get { return isEnabled; }
    }

    #region IDisposable Members
    private bool disposed = false;
    public void Dispose()
    {
        if (this.disposed)
        {
            return;
        }
        this.debugHost.Close();
        GC.SuppressFinalize(this);
    }

    #endregion
}

where ServiceSide.ExecutionService.ServiceExecute is the namespace of the wcf service and ServiceSide.ExecutionService the assembly containing it.

Using the code

I use a provider class, but its up to you how to implement the above feature.

DebugServiceHost has a static property IsEnabled, which basically checks whether the service is locally located to the running client execution folder. If that is true then using an instance of the class, host the service as well, which is automatically disposed.

This a sample code from my project that consumed the true or debug hosted service.

Collapse

public static class Provider
{
    private static DebugServiceHost dbh;
    public static void CheckAndRunDebugService()
    {
        if (DebugServiceHost.IsEnabled)
        {
            dbh = new DebugServiceHost();
        }
    }
    public static string RemoteURL { get; set; }
    private static IServiceExecute iServiceExecute = null;
    private static IServiceExecute GetInterface()
    {
        if (iServiceExecute != null)
            return iServiceExecute;
        iServiceExecute = CreateClient();
        return iServiceExecute;
    }
    private static ServiceExecuteClient CreateClient()
    {
        string address = "";
        if (DebugServiceHost.IsEnabled)
        {
            address = DebugServiceHost.Address;
        }
        else
        {
            address = String.Format("{0}/Service.svc", Provider.RemoteURL);
        }
        return new ServiceExecuteReference.ServiceExecuteClient("DefaultEndPoint", address);
    }
}

where

  • IServiceExecute is the Interface created when you add the service Reference.
  • ServiceExecuteReference.ServiceExecuteClient is the client created when you add the service reference
  • DefaultEndPoint is the endpoint in my config file.

Points of Interest

At first I at the first call to the service, I create the host. But as I mentioned in my post there was problem with that implementation.

Last problem hopefully

Finally a point of interest which was my last obstacle that took me a half day to find. I had implemented a provider class for the remoting part, which if needed, fired up the service host. Everything worked just great in the test projects, but at some point I tried to extend the framework with WPF.

The trick was that at first request, through static constructor I checked if the service was required to be hosted, and did that. But this did not work when I made the call from WPF. The only error was a timeout exception. I was going crazy, and then it kicked in. Never trust completely a 3 party library.

Solution

I made three clients, one Console, one Windows one WPF and stripped down the functionality of my framework to test. On each UI Client I made the call (and raised subsequently the host) after a UI reaction. I turns out that neither Windows Forms played correctly, when for example the call is made through a button click event. When I saw that, I made the host come up before the UI part was ever initialized and guess what? It all played just fine.

I really can’t understand how this has not been mentioned.

So I refactored the code, and at the program main entry method I call Provider.CheckAndRunDebugService()

Final thing is that, you must implement a trick in order for all serverside assemblies to be found in the client execution folder when you are debugging. There are a number of ways to do achieve this mainly by using post build event or by just adding the references and deleting them when in deployment face. I use the first.

Apologies

There is not project code, because the above resides in a framework project, I have written for the company I work for.

CodeProject Article

Advertisements

5 comments

  1. Very nice, well I believe it’s a cool piece of code but for me is useless since I’m new in it and I would have benefited from a project code.

  2. I think that you should try it.
    It is not that defdicult.
    The hard part is the trick you will use to get the server side file into the clientside

    I heavyly use batch files and post build events.

  3. I find it AMAZING that WCF, for all of its marketing, books written and such, is totally a step BACKWARDS. These problems were solved, long ago. Why were the solutions broken? Were they such houses of cards to begin with?

    It’s just amazingly disappointing as I’m working through this new technology stack (Silverlight / wcf). The technology is becoming less extensible, less performant, less useful and, quite frankly, less useful.

    Sorry about the rant….I’m just frustrated with these new ‘technologies’.

  4. There is no problem about the ranting.
    I partly feel the same.

    The only reason I accept WCF because I think that if needed my server side can be easily ported to a web service for example.

    All other things I can easily do without or simulate with good all fashion remoting which I believe is the best technology out there.

    My objections with WCF is that that tried to implement eveyring under one unified library, with one configuration file. The result is that in order to use it, you must become proficient in at least the configuration of WCF and its various security features and bindings.

    When I’m interested to build something that runs only with a tcp/ip remoting what do I care about web and all other things that are implemented in WCF. Don’t get me wrong, I believe in the combined power of WCF, but I really thing that they should have splitted it.

    One of things I really can’t understand is that of Known types. Why oh why should I tell WCF about all possible types I will probably pass through the channel? I think it is , to be able to use it in mex, and create the appropriate proxy. Stupid I say. Make it easier tou create the proxy, shate the objects types as You should, and serialize based on the actual instance type passed to the method, just like remoting does.

    I’m saying these because in my case, I needed to have only one interface, with a base class in its declaration, and then to be able to pass anything I want, derived from that class. I can’t describe you the flexibility that these gives me, and how I can implement it in a framework, and nobody must know about WCF. But doing the above just caused a lot of problems, because the transported types where not known at the framework level.

    Did you know that because of this reason WCF cant transfer a dataset with a column that has type of object? There is a reason that object is used in declarations, and the reason is that I do not know in advance what I will put in it.

    I think that in NET3 microsoft did a lot of stupid things that partly undo some of the great features of .NET2

  5. Pingback: WPF vs Windows Forms « Alex Sarafian as Developer


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s