Don’t use “Add Service Reference”!

The Visual Studio tools have always been crappy at generating code. The result is acceptable if you are a Microsoft representative selling new technology at some fancy seminar, but it is nothing you want to use in a release version of you application. The Visual Studio “Add Service Reference” (WCF) feature makes no exception.

The “Add Service Reference” feature might become handy when you need to connect to some none-.NET services, but in most other cases I sincerely recommend the manual approach. In this article I’m only going to tell you have, if you need more information check Miguel A. Castro’s article “WCF the Manual Way…the Right Way“.

Start by createing a basic class library project and reference the System.ServiceModel. This library is going to be referenced by both the client and the server. Don’t use the WCF templates as they will only make your life harder on the long run.

Add your service interface to the newly created project:

[ServiceContract(Name = “TestService”, Namespace = http://www.company.com/tests”)]
public
interface ITestService
{
    
    [OperationContract]
    TestData GetData(TestData data);

}

[DataContract]
public
class TestData
{
   
public TestData(string message)
    {
        Message = message;
    }

    [DataMember]
    public
string Message { get; set; }

   
public
override string ToString()
    {
        return “Some shared override”;
    }
}

Now add a new project to your solution and implement the server the same way you normaly would:

public class TestService: ITestService
{

    #region ITestService Members

    public TestData GetData(TestData data)
    {
        return new TestData(“Hello world! + data.Message);
    }

    #endregion
}

Instead of messing around with the XML configuration file, just configure your host by code:

ServiceHost host = new ServiceHost(typeof(TestService), new Uri[] { new Uri(uri) });
NetTcpBinding
binding = new NetTcpBinding(SecurityMode.Transport);

binding.TransferMode = TransferMode.Streamed;
binding.MaxBufferSize = 65536;

binding.MaxReceivedMessageSize = 104857600;
host.AddServiceEndpoint(typeof(ITestService), binding, “service1”);

host.Open();

As you can see there is not much new to implementing the service, but now it’s time for the client!

Create a new project for the client and reference the class library you first created. Instead of going for the “Add Service Reference” option create your own proxy:

public class TestServiceClient: ITestService
{

    private ITestService service;
    
    public TestServiceClient(Uri uri)
    {
        
// Any channel setup code goes here
   
     EndpointAddress address = new EndpointAddress(uri);
        NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport);
        binding.TransferMode = TransferMode.Streamed;
        binding.MaxBufferSize = 65536;
        binding.MaxReceivedMessageSize = 104857600;

        ChannelFactory<ITestService> factory = new ChannelFactory<ITestService>(binding, address);
        service = factory.CreateChannel();
    }

    #region ITestService Members

    public TestData GetData(TestData data)
    {
        return service.GetData(data);
    }

    #endregion
}

You can now place useful functions in your data classes and utilize them both on the client and server side. If you are running with .NET 3.5 you can even leave out the Data and Member Contract attributes of the data classes (same as choosing “Reuse types in referenced assemblies” when using thee Add Service Reference feature).

The biggest advantages of building your proxy manually compared to using the Add Service Reference feature is that you can now share classes and have the same client class implement several service interfaces instead of only one.

20 thoughts on “Don’t use “Add Service Reference”!

  1. Pingback: WCF Services in Silverlight without using “Add Service Reference” « configuration: debug

  2. This option only seems practical if you know you’ll only have 1 or 2 clients because those clients have to reference the project with the service contract class. Not really ideal if you have multiple clients and everytime that project gets compiled you have update the clients references.

  3. HI,
    This post doesn’t give any idea about why not to use add service reference.
    If my webservice is returning arraylist how to handle that in this scenario

  4. One of the benefits of using the code generation is setting the aptly name “variables” in a configuration file rather than in code so that you don’t need to recompile and redeploy just to change a configuration setting. I agree with your method of serving and consuming WCF webservices but you are over simplifying things.

    • True. But then again, there is no project I’ve worked in where the app would not have a “custom” config file of its own.

  5. I have a question:
    Is this method (writting my own proxy client class instead of making Visual Studio generating code) applicable if the web service I want to use wasn’t made using the recommandation of the 3rd paragraph :
    “Start by createing a basic class library project and reference the System.ServiceModel.”
    I don’t think it’s possible since I only have the web service wsdl url and not a library I can reference in my project.

    • The method applies when you are responsible for building both the client and the host in a .NET-only environment. In case of an external web service the code generator is the best (and only practical) choise.

  6. Hi,
    thank you very match.
    this artical it is very useful..
    but, I have question:
    I write your code and the program not hit in my breakpoint (in service).
    but if I returns back to the yellow arrow (of debuger) it hit in my breakpoint.

    I hope I was clear enough – I am from Israel- and my english it not good 😦

    Thank you !

  7. Hi, I have a doubt, How I handle asynchronous operations generated by the ASR feature? Do I have to specify them on the client manually? Or I have to handle them from clients requests in the service? I’m kind of new to this way of working since I’ve only worked with the ASR but I want to make the things in the right way.

  8. I agree with you about no using “Service Reference”, however I don’t agree about not using .config files and your client strategy. Putting WCF in config files allows to adjust configuration without having to recompile and redeploy the application.
    Also your strategy to the client proxy is too messy for big projects. The idea of merging several service clients in the same class goes against the SRP principle. If you want to do this what’s the point of separating the services in the first place?
    You also have to create a method in the client proxy for each WebMethod you have. In our company we have to maintain an application with about 50 WebServices. It would be very hard to maintain the client code with your strategy.
    For generating service clients we have a different strategy. We created a generic class with the generic parameter being the contract of the service. This way we can create a property that returns the service channel. Something like this:

    TContract ServiceChannel
    {
    get { return serviceChannel as TContract; }
    }

    The actual code is bit more complicated as before we return the service channel we check if the channel is ready for invoking (check if it was already created, if it faulted, etc…). This actualy produces a more rubost solution than your because we only need to create one class (we have to write and maintain less code) and use it to all of our services and we can even add extra verifications before invoking the channel. Also we don’t have to change our client class every time we make a change in the Service Contract.
    At the end you say: “ If you are running with .NET 3.5 you can even leave out the Data and Member Contract attributes of the data classes (same as choosing “Reuse types in referenced assemblies” when using thee Add Service Reference feature).”
    I’m not sure what you meant with this but by default a class with an empty constructor and public get/set properties is a DataContract and all the properties with public getter and setter are considered as part of the contract (DataMember). Also this is not the as choosing reuse types in reference assemblies. All the types in a WCF contract have to be DataContract and whether or not you explicitly mark the classes with DataContract you can use this option.

    • Nuno, I appreciate your comments. There are couple of cases where using the standard config file is not a option, e.g. if the client is an add-in (the host exe is not the application) or the config would reveal too much information about the architecture.

  9. Reading both your excellent article and Miguel Castro’s as well I realize that perhaps I have been spoiled by the wizardry of templates. But I am stuck with this situation: I have to connect to a third party service that has to be connected through HTTPS with a certificate. I have that in place allright. But the template won’t work for me (VS2012). So I was looking for a way to do it manually. Because it is third party, I cannot reference to the class library as you suggest here. And I have the strong impression that from there on, for me nothing will work as you describe here. All I have is the uri of the service, a wsdl file describing the service and an xsd file of the service.
    How can I make a working connection to the service and call the method with these ingredients?
    Peter

    • In many cases (e.g. Java in the other end) the older “Add web reference” has worked better for me. Have you tried it already? Check some of my other posts on the topic.

  10. No Offence Meant…
    I think if you know how to use stuff. Doing WCF way is different so it seems difficult, but when you dive into it, it is cool and my opinion is correct way. We do not have to re-invent the wheel.

  11. Admiring the hard work you put into your site and detailed information you offer. It’s good to come across a blog every once in a while that isn’t the same unwanted rehashed material. Wonderful read! I’ve bookmarked your site and I’m adding your RSS feeds to my Google account. dededgeegebb

  12. Pingback: Unable to add reference to third party WCF Service using Visual Studio

Leave a reply to Noe Cancel reply