Well we’ve written a service, specified the contracts, operations, custom data object and the structure of our SOAP message, and now, it’d be time to share it with the world. But how should we do that?
The answer is easy, we need to define endpoints to which clients can connect, and gather (or post) the required information from/to us. An endpoint is built up from three things, which are the ABCs of them. These are:
- Address: the URL of the service, with which you can reach it. The address of a WCF service can expose the following properties:
- Scheme: the scheme is the very beginning of the address, typically http://, but this is not the same thing as the protocol, even though it’s called the same.
- Machine: the name of the machine, for example localhost, or http://www.somedomainname.com, or the IP address.
- Port: the optional port number (:8080).
- Path: the path of the service, can be multilevel. I think you can guess what’s it.
- Binding: the binding specifies how your service can be accessed it defines the protocol name, type, encoding, etc. You should imagine the binding as something which stores anything else than the message contract, and the address used to reach it. So security settings, metadata exposing, and a lot other things belong to here. There are some preinstalled bindings, which you can extend, or create entirely new bindings from scratch. I’ll provide a table of the installed bindings later in this post.
- Contract: you have seen it in work, we’ve defined it in the previous posts. The contract specifies the methods, operations to expose, custom data types, etc. The name of the contract is the same as the class or interface marked with the ServiceContractAttribute. If you’ve set the “Name” named parameter explicitly, then you should use the value you specified there.
Now that you know the basics, let’s head towards the creation of an endpoint. You have two ways to build one: using a .config file, or hard-coding it programmatically. The latter is a discouraged method, because endpoint addresses tend to change in time, and you’ll face a costly code recompilation if you’ve added your endpoints programmatically. It’s much more simpler to edit a plain XML file to create or modify your endpoints. Let’s see how:
<endpoint address=”http://localhost:8080/ServiceName/” binding=”basicHttpBinding” contract=”theNamespace.IServicename”/>
As you saw, to define an endpoint, the system.serviceModel element should be used. Then we’ve added a services collection to it, and a single service element. To this element, we’ve added a single endpoint, specifying the address, binding and the contract. Of course you can use multiple endpoints in a single service, as long as the addresses are different. But I’m a bit incorrect here, because you can use the same address in multiple endpoints, but then you must use different contracts for them. If you fail to do so, there will be a runtime exception.
The last thing to mention here is the use of base addresses. You define them as follows:
In this case, you can define relative addresses to your endpoints. For example, if you set an endpoint address to the previous service of “anEndpoint”, then you’ll be able to call your service at http://localhost/theServie/anEndpoint.
The last topic covered in this post is the strongly discouraged programmatic endpoint creation. You create one by using the ServiceHost class, which’s constructor takes a type parameter, and an array of Uri objects. The type in this case is the class implementing the interface marked with the ServiceContractAttribute. The array will be used to specify the base addresses of the service. Then you call the AddServiceEndpoint method, which takes three parameters. A type, which is the type of the contract (the interface), a binding class, and the relative address of the endpoint, in string or Uri.