Ok…So I am more of a general .NET and Silverlight developer, but it is hard to get around the fact that WCF infiltrates most of the projects I ever work on. And after having read a substantial part of Juval Löwy’s book about WCF, I have realized that there was a lot that I didn’t know and didn’t fully understand. Not that I am saying that I get it all now, but I have a better understanding at least.
The thing is that WCF isn’t really very hard in most cases, but having a basic understanding makes it a lot easier. And to be honest, the basics will take you a long way when working with Silverlight, since Silverlight doesn’t support a lot of the more advanced features. To be honest, the WCF support in Silverlight is fairly basic, but it is enough…
So based on this, I thought I would try and write a down to earth and simple introduction to the main concepts in WCF.
So…what are the main concepts in WCF? Well, if you ever get that question, all you have to say is ABC. ABS stands for Address, Binding and Contract. These are the main things in WCF, and 2 of them are quite simple in most cases, while the third is a but more complicated.
Address
Let’s start by looking at the A, or address. Address is simply where you find the service. Basically where should I look for it.
In the real world, you will find the supermarket at the end of Wakefield street, the Sunday fruit and vegetable market at the parking lot across the street from Museum Hotel, the hooker at the red light district and the drug dealer on the corner of that shady street.
As you can see, there are a lot of different ways to give you locations/addresses in the real world. In WCF, it is the same. But they are pretty well defined for obvious reasons, and generally change based on what transport protocol is being used. For an HTTP based service, the address might be http://www.mydomain.com/mywebservice or maybe http://localhost:3100/MyOtherService. But if we switch to TCP we might have net.tcp://127.0.0.1:3400/MyService and for named pipes we might have net.pipe://localhost/MyService.
But all in all, it is actually more or less the same as the real world. The address “type” changes based on what you are looking for and so on…
Contract
Ok, so I am skipping binding for now and going straight to the C, the contract. The contract defines what is offered by the service. This is well defined in the computer world, as we need to know what we can do with the service. In the real world, it isn’t quite as defined, but more an assumed contract.
You assume that the supermarket will have the ingredients you need for dinner, the fruit and vegetable market will have…wait for it…fruit and vegetables…and the hooker will offer…well…a good time, and the drug dealer will have some drugs for you if that is what you want. All of these assumed features are part of the contract.
In WCF, the contract is generally an interface adorned with a ServiceContract attribute, and methods adorned with OperationContract attributes. Both of these are available in the System.ServiceModel namespace, and both of them offer more functionality than I show here. But it is an introduction.
using System.ServiceModel;
namespace DarksideCookie.WCF.Intro.Contracts
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
string Echo(string message);
}
}
I say “generally” as it isn’t mandatory. You can place those attributes straight on an class instead of an interface if you want to, but don’t…and I mean it…DON’T!
In some cases, when adding a WCF service to a project in VS, you get the interface less implementation. I think it is when you add a Silverlight enabled web service… I have no idea why this is, but in most cases VS will give you the “correct” implementation with a separate interface.
Binding
As you might have noticed I left the B to the end. The reason for that is that it is the most complicated part. It includes EVERYTHING but the address and contract. That means that it includes the “language”, the requirements and so on. Basically everything you wish you knew about that hip new restaurant that you have never been to, and that uses this new funky ordering system that everyone else seems to know about but you don’t… Or the fact that in New Zealand, you don’t wait for the waitress to bring out the check, but instead you always pay at the counter at a restaurant… Things like that…
But let’s go back and look at the binding in the scenarios used in the “Contract”s section as each one of them have a “binding” too.
At the supermarket, you are expected to go in, pick up the groceries you need and walk over to the checkout. At the checkout, they will scan the barcodes for you groceries, tell you how much to pay, and you then pay using your preferred method of payment. And in some countries they will pack your bags for you, and in some they wont.
The fruit and vegetable market is very similar. But there are a few subtle differences. The items do not have barcodes, most things are weighed and paid for by weight instead of per item. And you probably can only pay using cash. But the biggest difference is that you can probably haggle over the price. In general, I don’t. I am not the haggling kind of type, and especially not when I don’t know if you are supposed to or not. Just imagine if we have an explicit binding…
Ok, the hooker is different. She doesn’t sell the same type of product, and probably doesn’t have a list of prices on display. You have to ask for prices, and to be honest, you probably need to know what to ask for as well. Being that prostitution is illegal in most countries, they seems to have a “coded” way of talking. At least in the movies… And in some places, you won’t make the deal with the hooker herself, but with some other person. That person might also ask for proof that you are not a cop… and so on. As you can see, it is still a matter of selling a product, but the interaction is very different.
Just as with the drug dealer. But in this case, it is even worse. If you do it wrong, you might end up in a LOT of trouble, and on top of that you definitely need to know what you are asking for. In most cases, you will also make the deal with one guy (and probably refraining from haggling about the price), and then pick up the product from another guy. And depending on the dealer you might also have to earn some trust before you are allowed to buy enough to last you the entire weekend instead of just Friday night…
Disclaimer: All of the above information is based on facts gathered by watching TV and movies. They might be a little off as I have very limited experience in some of the areas. And when I say that I have very limited experience, I mean none. And when I say some of the areas, I don’t mean going to the supermarket or the market even if I have a wife….
As you can see, a simple thing like buying something will be completely different in different scenarios. And with the flexibility that WCF offers, this could get very complicated. And this is the binding…
Luckily, the binding in WCF is, and has to be, very explicit. As WCF is built for distributed systems, the binding needs to be explicit and in a lot of cases discoverable. But before looking at how the client figures out what binding to use, let’s look at how the binding is defined. In the code below, I show how to define a binding from code. In most cases however, configuration is put in an external configuration file instead of set up in code. This makes it easier to switch the settings if needed, but I think it is easier to get a grasp of that is really happening when doing it in code instead of configuration.
private static Binding GetHttpBinding()
{
var binding = new BasicHttpBinding();
return binding;
}
Gets a basic http binding. This is the simplest binding available, and it is supported by Silverlight. Using anything but BasicHttpBinding in a Silverlight project means that you will have to first verify that it works in Silverlight, which it probably doesn’t as Silverlight only supports BasicHttpBinding and CustomBinding.
private static Binding GetTcpBinding()
{
var binding = new NetTcpBinding();
return binding;
}
Returns a TCP based binding. This is a great binding for intranet scenarios for example, but not supported by Silverlight.
private static Binding GetHttpBindingWithSimpleSecurity()
{
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
return binding;
}
Returns an HTTP based binding, but in this case a WS based http binding. WS* adds a bunch of extra features to WCF services over HTTP such as security, as shown above.
And finally you have the option of building your own custom binding. This is actually a lot simpler than you would expect, but does require you to know what you want.
Creating a custom binding is done by creating a new CustomBinding instance, and then adding different “binding elements” to it. A “binding element” is basically one part of the final configuration. You have for example different message encoding elements to support different message encodings, and different transport elements to support different transports. You can even build your own elements and extend WCF to your needs. You need at least a message encoding element and a transport element.
Silverlight supports the use of custom bindings, so in a Silverlight scenario where you need more than just basic http, this is the way to go.
private static Binding GetCustomBinding()
{
var binding = new CustomBinding();
binding.Elements.Add(new BinaryMessageEncodingBindingElement());
binding.Elements.Add(new HttpsTransportBindingElement());
return binding;
}
And as you can see from the code above, without even knowing that much about WCF, this returns a custom binding with binary message encoding and an HTTPS transport. Basically a binding that sends and retrieves the SOAP messages with a binary encoding, and that makes sure it is sent over HTTPS.
Just remember that the client binding configuration obviously needs to be the same as the service configuration binding for quite obvious reasons. You don’t want to walk into the fruit and vegetable market and ask for a “good time”…
Ok…so defining the contract and binding is not that complicated, but this is all done on the server… This works fine when you are building both the server and client yourself, and do it all in .NET, but if you are only building one part, or maybe communicating across multiple platforms, what happens then?
Well, that’s where WSDL comes to the rescue. WSDL stands for Web Service Definition Language, and is an XML based way of defining everything you need to know about a web service to be able to communicate with it. Not all services expose this information, but any public service needs to. Otherwise it would be impossible for the external clients to figure out what to send, in what way and what to expect back.
It is basically like a guide book. It includes everything you need to know find your way around the service… And I say
around the service and not
to it. Most services exposes the WSDL at the same location as the service, so you need to find the address yourself first… In some cases however, you might get hold of the WSDL in some other way, and in that case, the address is included as well.
For a very simple service like the IMyService served up over a BasicHttpBinding, the WSDL looks like this
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="MyService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
<xsd:import schemaLocation="http://localhost:8080/MyService?xsd=xsd0" namespace="http://tempuri.org/"/>
<xsd:import schemaLocation="http://localhost:8080/MyService?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="IMyService_Echo_InputMessage">
<wsdl:part name="parameters" element="tns:Echo"/>
</wsdl:message>
<wsdl:message name="IMyService_Echo_OutputMessage">
<wsdl:part name="parameters" element="tns:EchoResponse"/>
</wsdl:message>
<wsdl:portType name="IMyService">
<wsdl:operation name="Echo">
<wsdl:input wsaw:Action="http://tempuri.org/IMyService/Echo" message="tns:IMyService_Echo_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/IMyService/EchoResponse" message="tns:IMyService_Echo_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BasicHttpBinding_IMyService" type="tns:IMyService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Echo">
<soap:operation soapAction="http://tempuri.org/IMyService/Echo" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MyService">
<wsdl:port name="BasicHttpBinding_IMyService" binding="tns:BasicHttpBinding_IMyService">
<soap:address location="http://localhost:8080/MyService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
And if you really did look through it properly, which I kind of hope you didn’t as it is boring stuff, you would have seen that it contains everything you need to be able to communicate with my service.
If we skip through a lot of the XML and focus on the wsdl:binding element and its children, we can, even without knowing WSDL, figure out that there is service implementing an interface called IMyService. The service is available over HTTP, and it supports a single operation called “Echo”. The Echo operation takes a single literal input and returns a single literal.
And in the wsdl:service element, we can see that the service is available at http://localhost:8080/MyService.
So as mentioned before, the WSDL contains everything we need to know to be able to communicate with the service. Everything including where to find it and what operations it supports, as well as the format of the message to pass to and receive from the operations. So it is basically a very verbose and explicit XML definition of the ABCs of the service. I do however not recommend learning all of this and creating your communication with the service manually. Let the tools do that for you!
So…that was the ABC of WCF. As I have said before, this is a really rough and simple introduction to the basics of WCF. There is SOOO much more to learn, but hopefully this will give you an idea of how it works.
The goal is to show of some options for initiating the communication on the client in my next post. Until then, you can rely on “Add Service Reference” in VS to do the dirty work for you, but as you will see, there are options to that that might be useful once in a while.
Cheers!