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.
[...] This post was prepared with motivation to the points that Miguel A. Castro, NetFXHarmonics and also Developer’s Dump mentioned. So to use WCF service efficiently, I won’t use “Add Service Reference” and [...]
WCF Services in Silverlight without using “Add Service Reference” « configuration: debug
March 13, 2009 at 19:17
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.
suedeuno
November 18, 2009 at 21:21
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
MyWay
January 21, 2010 at 08:22
What is a good value to use for uri?
Dan
July 14, 2011 at 19:01
Heck Add a service and do it right. ;-> WCF rock when done properly.
Stephen Russell
September 8, 2011 at 19:07
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.
Someone Somewhere (@1ManBanned)
October 2, 2011 at 11:55
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.
Tom
October 2, 2011 at 22:41
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.
roch
January 6, 2012 at 13:33
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.
Tom
January 7, 2012 at 22:50