I cranked up my first WCF Service and it was a great learning experience. As part of an upcoming Vista and Office developer tour across 5 cities in India, I was preparing for delivering Session III on connected applications.
Now, I have written simple WCF code in the past, mostly when the initial bits were available and a lot has changed since then. To add to it, Vista with IIS 7.0 requires some additional steps to create and host WCF services.
Since it took me some searching on the web and some amount of research to figure out some of the nuances, I thought jotting them down would help somebody else save some time.
Before coding your WCF service
To start with, you need to have .NET Framework 3.0 installed. With Vista, this is pre-installed, so you can ignore this if you are running Vista. However, IIS 7.0 is not enabled in Vista by default and you have to do that through the Add/Remove Programs > Turn Windows features on or off in Control Panel.
While you are there, you might also want to turn on features to enable HTTP Activation to be hosted in IIS. You can find this under Microsoft .NET Framework 3.0 as two options - Windows Communication Foundation HTTP Activation and Windows Communication Foundation Non-HTTP Activation. Enabling these installs required modules that allow for processing of WCF components in the HTTP pipeline in IIS.
The above is also the fix if you are stuck with an error message that says: HTTP 500 --- Handler svc-Integrated has a bad module "ManagedPipelineHandler" in its module list
The reason this is not installed by default is that most clients would not require to actually host a WCF service. So it makes sense to only enable it on systems that are used by, say, developers, who might create services, host them in IIS and consume them all on the same system.
You also need to install other handlers that will enable IIS and other hosts in the system to understand the WCF service model. To register these, use the ServiceModelReg.exe utility with the –i option. This utility is found in the %WINDIR%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation path. (If you can't find such a directory structure, you probably haven't installed .NET Framework 3.0). You are also better off running this in a command prompt that is running with Administrative privileges (right-click and Run As Administrator – something you must be familiar with already if you are using Vista).
If you are using Visual Studio to create your WCF applications, you also need the WCF "Orcas" bits, the current version of which is the Nov 2006 CTP. I recommend you search for the latest bits depending on when you are reading this and install those.
Understanding the Basics
Most communication scenarios have a Server and a Client component. In WCF, everything revolves around three things - Contract, Bindings and EndPoints.
Contract defines the actual contract between the client and the server, which means that it defines what the client can request for and what the response would look like. In simple words, the contract is synonymous to the method signature and the methods exposed by the service.
Bindings specify how the communication will actually occur between the client and the service. The client and the service should communicate in a manner that both are capable of understanding - for example, if the service provides information over HTTP, the client should be aware of that and make the appropriate kind of request. Bindings basically specify that information for both the client and the server. Well, that's actually putting it in simple words - in reality, the bindings also enable services and clients to specify various transport protocols, security standards and a host of other things to be specified in great detail.
EndPoints provide the information of the actual address where the service is located and how to reach the same. An end-point is the actual link that has information about what binding to use and what contract is being referred to. Thereby, the end-points actually become the service address that anybody who wants to consume the service would refer to.
Creating your WCF Service
Now to some actual code. Creating the actual WCF service is very easy.
Step 1 : Define the Contract
To begin with, a contract has to be defined. The contract is defined as an Interface and the class that actually provides the implementation of the contract implements the interface.
So, for a simple Math Service that takes two numbers and adds them up, the contract would look like:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace MathService
{
[ServiceContract]
public interface IAdditionService
[OperationContract]
Int32 Add(int number1, int number2);
}
Note that a reference to System.ServiceModel assembly in .NET 3.0 will be required before you write the above code in Visual Studio.
The ServiceContract attribute says tells the .NET Framework that this interface is actually defining a WCF Contract. The OperationContract attribute is applied to method signatures that will be actually exposed as operations of the contract. Basically this means that the client can now access the Namespace.ServiceContract class through a proxy and call the OperationContract methods on it.
If you find this very strange, just think of OperationContract as synonymous to marking methods with the [WebService] attribute when creating web services. This is a similar structure to allow the underlying framework to generate all the plumbing code that will be required to create the actual services.
Step 2 : Service Implementation
Now that the contract is defined, the actual implementation for the service is done by a class that implements the above interface. In our case, that would look like:
public class AdditionService : IAdditionService
public int Add(int number1, int number2)
return (number1 + number2);
Of course, I am not doing anything great in terms of the actual implementation, because I want to focus on the structure of the various components rather than implementation logic.
Step 3 : Host the Service
The contract for your WCF service is actually ready. But for clients to be able to get to it, you will have to host the service. There are a wide variety of options to host your service in Windows Communication Foundation. The simplest one is to host it within a console application that is kept continuously running. Leveraging the same System.ServiceModel namespace, you can use the ServiceHost class to host your service. A simple console application that hosts the service is shown below:
using MathService;
namespace MathServiceHost
class Program
static void Main(string[] args)
using(ServiceHost host = new ServiceHost(typeof(AdditionService),
new Uri("http://localhost:9999/MathService/AdditionService")))
host.Open();
Console.WriteLine("Math Service\n");
Console.WriteLine("Addition Service Started...\n");
Console.ReadKey();
The using attribute helps to scope the ServiceHost instance that is created, so that it is automatically disposed when the program ends. The ServiceHost constructor takes two arguments – the type of the class to host and the URI at which it will be available. The URI can be any valid URI. If you are running Vista or Windows XP SP 2, and try accessing the service from another computer (or in certain cases the same computer), you might not be able to access a port such as 9999, because Windows Firewall blocks most non-standard ports. To get around this, you need to configure Windows Firewall to allow your application to communicate on the ports you want. Details of this can be found at http://msdn2.microsoft.com/en-us/library/ms751530.aspx. Note that this is not required in most cases.
Hosting the service involves another step. The service endpoint has to be configured. Remember, WCF clients can only discover the service if the endpoints are specified. To specify an endpoint, create an app.config file for the console application. In the app.config file, use the following code:
xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="MathService.AdditionService" behaviorConfiguration="MathServiceTypeBehaviors">
<endpoint
address="http://localhost:9999/MathService/AdditionService"
binding="basicHttpBinding"
contract="MathService.IAdditionService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
service>
services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceTypeBehaviors" >
<serviceMetadata httpGetEnabled="true" />
behavior>
serviceBehaviors>
behaviors>
system.serviceModel>
configuration>
[Why some pieces of code are marked in bold will be obvious soon]
A tip here is that if you were creating the above file in Visual Studio 2005 and were using an earlier WCF sample, you will not get intellisense. The configuration tag requires no xmlns namespace, which if you provide, you will not get any intellisense in VS. The quirk is documented here.
The system.serviceModel is a special configuration section that is defined in System.ServiceModel and provides options to configure a lot of the settings with regard to Bindings and Endpoints.
In the example above, a service is defined with the name and a behavior configuration. I will get to the behavior configuration in a minute. The endpoint is defined next with the address, binding and contract. In this case, it specifies the address at which the service will be available, that the binding will be a simple HTTP binding (which means clients make a simple HTTP call to access the service) and the reference to the contract that we defined earlier (to know what is being exposed by the service). You can almost imagine the framework traversing through this one line and discovering where the service is located, what it offers and how to communicate with it – and generating all the necessary code for it to actually happen.
The other endpoint brings us back to the behaviors part. When you access the service through the browser (and you can do this without specifying the pieces of code that I marked in bold), the contract is not automatically shown to the client. This is a piece of security in place to ensure that anybody and everybody doesn't get to see the details of the contract by just browsing to the service. To enable "viewing" the contract details when just visiting the service URL through a browser, it is required to specify a service behavior that allows HTTP GET requests and an endpoint that allows metadata exchange. This special (built-in) endpoint will be used to query the metadata and return the queried information.
So, we're now ready to host the service and just building the application and running the console application should get you hosting the service. You can verify it by visiting the service URL (in our case http://localhost:9999/MathService/AdditionService) through a browser. You should see a page that shows you the service contract and gives you instructions on building a client to consume the service. (You will see a different page if you did not enable the metadata exchange endpoint).
If you received an AddressAccessDeniedException with a message such as - HTTP could not register URL http://+:9999/MathService/AdditionService/. Your process does not have access rights to this namespace, then you probably did a lazy F5 through Visual Studio 2005. I haven't found a workaround for this – and I am already running VS 2005 as administrator – however, I did figure out that it is a Vista security feature not allowing an application to register a URL (kind of create a local HTTP address available on the fly). I opened a command prompt in elevated mode and ran the application directly from the command-line and it worked like a song. So that's probably something you can try as well.
Consuming your WCF Service
Hurray – the server is created. Now we have to consume the client and if you are still with this blog at this point, you'll probably see that creating it in Visual Studio is very, very simple. Just create a console application, right click on References and click on "Add Service Reference". Provide the service URL and a name for your client proxy class and everything is created for you in a jiffy.
Of course, you can do it the harder way (and sometimes it is necessary to do it that way) by using svcutil.exe – just like in earlier versions of the .NET Framework. Type svcutil.exe and the URL of the service to generate the code for the proxy classes which you can then include/reference in your client code.
The last thing is to call this typed proxy that was generated for you. The code to do that is rather simple:
using MathClient.MathServices;
namespace MathClient
Console.WriteLine("Press any key when service is ready...");
try
AdditionService proxy = new AdditionService();
int result = proxy.Add(1, 2);
Console.WriteLine(String.Format("Result: {0}", result));
catch(Exception ex)
Console.WriteLine(ex.Message);
proxy.Close();
Console.WriteLine("Press any key to exit");
A using statement to resolve the proxy class (in this case MathClient.MathServices – MathClient was the namespace of my client console application and MathServices was the name I gave in Visual Studio to the proxy generation wizard) at the top and instantiating the service proxy (which is named the same as your service class by default).
Pretty straightforward. The try/catch clauses actually help on Vista to just show the error message rather than having to see a dialog that tries capturing error information and send it to Microsoft assuming that an application crash happened. This is the behavior by default for all unhandled exceptions. Also, it is useful to just run the application from a console window to actually get to see the exception details if any – otherwise the window just closes too fast.
Remember also that your service should be running before you run the client, otherwise you will get an error that says that The target machine actively refused the connection for obvious reasons.
Further Steps
I started out writing this article to also cover IIS hosting of the service where there are some more quirks when working with the secure environment of Windows Vista and IIS 7.0. But I think I will do a part 2 on that just to keep this article readable. So in part 2, we'll take the same service and do an IIS hosting of the same service.
Reference
An excellent reference of several starter quirks and solutions for the same is the One-time setup procedure for the Windows Communication Foundation available at: http://msdn2.microsoft.com/en-us/library/ms751527.aspx
Hope this article helped! Do leave comments if you face any other issues or think anything else needs to be added.
Remember Me
Page rendered at Friday, November 21, 2008 4:01:09 AM (India Standard Time, UTC+05:30)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent the views of Microsoft Corporation in anyway.