Now comes the most important part: using the service!
How you go about consuming a WCF service depends greatly on the type of
client application used.
Non-WCF clients
If you plan on calling a WCF
service from a non-WCF client, then have no fear, you're still in great
shape. One of the design goals of WCF (and any quality SOA solution) is
interoperability, which means that a WCF services should be consumable
on a wide variety of platforms and technology stacks.
Now, it is still the
responsibility of the service designer to construct a service that's
usable by non-WCF applications. For instance, a broadly used service
would offer a basicHttpBinding to ensure
that applications based on the .NET Framework 2.0, or JRE 1.4 would
have no problem consuming it. An interoperable service would also use
security schemes, which rely upon commonly available certificates for
transport security.
Let's assume that a WCF
service with a basic HTTP endpoint has been exposed. Let's also assume
that this service has a metadata "behavior" attached to it, so that we
can interrogate its WSDL contract. If you have a .NET Framework 2.0
application that typically consumes classic ASMX services (ASP.NET web
services), they can consume a WCF in the exact same fashion. That is,
add a new Web Reference to the WCF service metadata definition.
If you have Visual Studio.NET 2008 installed, the Add Web Reference option isn't immediately available on the project. You first right-click the Project and choose the Add Service Reference menu item. At the bottom of the resulting window, you'll find a button labeled Advanced which you should click.
The next window that
opens is a settings window, which has a button at the bottom for those
who wish to add a traditional "web reference" that leverages older .NET
technology.
Choosing the Add Web Reference
button finally opens up the traditional service browser, where we plug
in the URL of our service and see the corresponding metadata.
In the subsequent code
which calls this service, the developer would use the assigned web
reference just as if they were calling any standard SOAP web service.
Console.WriteLine("Vendor client launched ...");
try
{
AsmxProxy.VendorService svc = new AsmxProxy.VendorService();
AsmxProxy.Vendor newVendor = new AsmxProxy.Vendor();
newVendor.VendorId = "1234";
newVendor.VendorName = "Watson Consulting";
newVendor.VendorContactName = "Watson Seroter";
svc.InsertVendor(newVendor);
Console.WriteLine("Vendor " + newVendor.VendorId + " inserted ...");
Console.ReadLine();
}
catch (System.Web.Services.Protocols.SoapException ex)
{
//grab "insert fault" part of message
Console.WriteLine(ex.Detail.InnerText);
Console.ReadLine();
}
The result? The HTTP host was opened successfully by WCF, and after the client executed the insert operation, the service wrote its confirmation message to the host console.
However, if our service fails and throws our custom fault message, our
client code catches it as a SOAP exception, and still has access to the
custom fault details. Below notice that the exception's detail object
contains the XML message of the InsertFault type.
WCF clients
If you have the benefit of
using a WCF application to call a WCF service, then the full might of
Microsoft's communication stack is laid before you. You are no longer
constrained by HTTP-only communication and you can exploit a wide range
of encoding, security, and transaction capabilities in your service
consuming application.
Critical point
While WCF-to-WCF communication
scenarios offer a rich set of communication options, technically any
WS*-compliant application should be able to take advantage of a majority
of WCF's service characteristics. For example, an Oracle application
which understands WS-Security can effectively participate in secure
conversations with a WCF service.
The easiest way to consume
WCF services from a WCF application is to generate a proxy class that
shields us from the plumbing necessary to call the service. A WCF proxy
can be generated in one of two ways. First, we use the ServiceModel Metadata Utility Tool (svcutil.exe)
command line tool if we want full control of the way the proxy class is
generated. This tool takes the service metadata and generates a .NET
source code file that may be used to call the WCF service.
The power in this little
utility lies in the ability to apply a cornucopia of command line
parameters, which define attributes of the .NET source code file such as
its programming language, namespace, output location, and a whole lot
more. For instance, executing the following command on our service
results in a full WCF proxy class and merges the new WCF configurations
with the existing configuration file for the client application.
Svcutil.exe http://localhost:8081/VServiceBase?WSDL / out:WCFProxy.cs /language:c# /config:app.config /mergeConfig
Because I built the WCF service proxy manually, my client application must have both the System.ServiceModel and System.Runtime.Serialization assemblies added as project references.
Consuming the WCF proxy
class looks quite similar to consuming the ASMX proxy class. In fact,
the only real difference that you’ll notice here is more explicit
interaction with the client proxy class. Notice that we work with the
proxy class within a "try" block and catch any exceptions (including our
custom one) in well defined "catch" blocks. While it is tempting to
apply the C# "using" statement to WCF proxies, that practice can
actually lead to swallowed exceptions and should be avoided. See http://msdn.microsoft.com/en-us/library/aa355056.aspx
for more details. The other slight difference is that the WCF proxy
class has an overloaded constructor. In this case, I'm passing in the
name of the service endpoint name, which resides in the application
configuration file.
WcfProxy.VendorServiceClient svc = new WcfProxy.VendorServiceClient ("BasicHttpBinding_VendorService");
try
{
WcfProxy.Vendor newVendor = new WcfProxy.Vendor();
newVendor.VendorId = "9876";
newVendor.VendorName = "Noah Partners";
newVendor.VendorContactName = "Noah Seroter";
svc.InsertVendor(newVendor);
Console.WriteLine("Vendor " + newVendor.VendorId + " inserted ...");
svc.Close();
}
catch (System.ServiceModel.FaultException<WcfProxy.InsertFault> ex)
{
Console.WriteLine(ex.Detail.FriendlyMessage);
Console.ReadLine();
}
catch (System.ServiceModel.CommunicationException) { svc.Abort(); }
catch (System.TimeoutException) { svc.Abort(); }
catch (System.Exception) { svc.Abort(); throw; }
If you're looking for an easier way to generate a WCF proxy class, look no further! Visual Studio.NET also offers an Add Service Reference option, which enables us to generate our proxy class from within our development environment.
By either using the ServiceModel Metadata Utility Tool explicitly to generate proxy classes, or instead using Visual Studio.NET (which uses svcutil.exe underneath the covers), you have some efficient options for generating WCF-compliant code for use by service clients.