Service Client Proxy Classes, Nothing But Problems?

by Danielvg 2. December 2009 22:09

Ever had the classic problem where the same proxy class can be found in different namespaces because more then one service use the same class? Tired of having to “Update reference” whenever you make a small change to the service or data contract?  Maybe you want to add specific client code to the proxy class that cannot be added with a partial class? Well I had all of those problems more then once, especially the namespace problem has been a huge pain! But then I discovered ChannelFactory and the ability to call a service without creating a proxy class.

Did that come out like a TV commercial? I hope so, because I really want to sell the idea (of cause I am not the first one to have it), the benefits really overshadows the small overhead downside, even for small projects.

The basic principle of not having a service reference is that you have your service and data contracts in a separate assembly that both your host and client references.

relactions

I have made a small example based on the above structure. The host is in this case a web application and the client is a consol application.

The shared assembly, Intrastructure, has both the service and data contract:


using System.Runtime.Serialization;
using System.ServiceModel;

namespace Demo.NoProxyClasses.Infrastructure
{
    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
        HelloResponse HelloWorld(HelloRequest request);
    }

    [DataContract]
    public class HelloResponse
    {
        [DataMember]
        public string Value { get; set; }
    }

    [DataContract]
    public class HelloRequest
    {
        [DataMember]
        public string YourName { get; set; }
    }
}

The host contains the actual service(and some stuff to actually host the service):


namespace Demo.NoProxyClasses.Host
{
    public class HelloService : IHelloService
    {
        public HelloResponse HelloWorld(HelloRequest request)
        {
            var response = new HelloResponse { Value = string.Format("Why hello there {0}", request.YourName) };
            return response;
        }
    }
}

Nothing new there, but when we take a look at the client we see that there is a reference to Infrastructure and when calling the service it first creates a ChannelFactory based on the interface “IHelloService” and then calls the service through the ChannelFactory.


using System;
using Demo.NoProxyClasses.Infrastructure;
using System.ServiceModel;

namespace Demo.NoProxyClasses.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            var binding = new WSHttpBinding();
            var endpointAddress = new EndpointAddress(“http://localhost:4881/HelloService.svc”);
            var helloService = new ChannelFactory<IHelloService>(binding, endpointAddress).CreateChannel();
            var request = new HelloRequest { YourName = "Daniel vg" };
            var response = helloService.HelloWorld(request);
            Console.WriteLine(response.Value);
            Console.ReadKey();
        }
    }
}

The result when running the application is:

image

The beautiful part is that there is no service reference and all the troubles that follow.

image 

If you are like me and have validation logic in your domain objects then an extra bonus is that you can now use the same validation on both host and client!

Full source code can be found here Demo.NoProxyClasses.zip (42,08 kb) (VS2010 Beta2)