When I decided to create a Windows Communication Foundation (WCF) Data service, the goal was to take an existing class library and expose a portion of its functionality as an action. My biggest issue with this process was that .NET class libraries are focused around providing objects that happen to have some methods, but WCF services are focused on the methods. This inversion of architecture can provide some challenges. Fortunately, I have a heavy background in non-object-oriented (OO) languages, and I often write my objects to be focused around one or two methods, which was the case here. This greatly smoothed the transition to WCF.
A summary of the work performed
In the original library, a primary object was used (with several supporting objects to be used as data structures for properties). Once enough of the properties (some optional) had values in them, an execution method could be called. This wasn't great or "correct" OO design, but the OO architecture is really poor for times when all you really want is a function with a lot of parameters (some optional).
When I went to WCF, I wanted to be able to expose this one method and pass in a data structure that essentially encapsulated all of the properties. In other words, I went from having a data structure with one method that used the properties of the object to a method that accepted all of those properties as a data structure. In both cases, I was getting back a data structure that represented a list of result objects.
The first step was to add a WCF service project to my solution. This created a stub service for me. The stub service contained an interface file, a service file (.svc), and a Web.config file. I renamed the interface and service files to match my service name, and then opened the files and did the same for the service and class defined. Like ASP.NET, the service file has a code behind file, which is what I was actually going to work with.
The code behind and interface have a basic implementation, but it was not useful to me (it does serve as a handy reference point if you are not familiar with this work, though). The place to start is in the interface. It is not mandatory to use an interface, but it is helpful in certain scenarios for architecture reasons, such as when consuming the WCF service directly from another .NET application.
In the interface (which should be decorated with ServiceContract), I created my data structures that I would need for parameters and output values as WCF Data Contracts. To do this, I created classes and decorated it with DataContract. Within the class, I implemented the properties. The properties, which should be exposed via WCF, should be decorated with DataMember. Something to keep in mind is that, as you walk the property tree, all of the leaf nodes must be primitive types. I opted to not worry about data validation at the WCF level, primarily because I would be the only person using this service. Once the data structures were complete, I defined in the interface a method (decorated with OperationContract) that represented the functionality I wanted to expose. Then, I removed the default items that the add project wizard created.Figure A
The default interface implementation. (Click the image to enlarge.)Figure B
A better look at the code in the default interface. (Click the image to enlarge.)
Next, I went into the service code behind file to implement the interface. This is simply a matter of creating methods that implement the interface's methods and performing the actual work. I just had to create an object from my class library and set its properties to the values from the input parameter. Once I had those properties set, I called its execution method and captured the results. I created an object of the method's return type and populated its values from the captured results. Then, that object was returned to the client.Figure C
The default service code behind. (Click the image to enlarge.)Figure D
A better look at the code in the default service code behind. (Click the image to enlarge.)
When you run the project, it will start a local Web server in Visual Studio and bind it to a random port, like working with an ASP.NET project. To test the service, I used the WCF Test Client application, which should open automatically when you run the project; if it doesn't open automatically, look for WcfTestClient.exe in the IDE directory within the Visual Studio installation directory. The test client allows you to make calls against a WCF service and inspect the results. Combining this with the usual breakpoints, watches, etc. will allow you to perform your troubleshooting like any other application.Figure E
The WCF Test Client. (Click the image to enlarge.)
I was deploying to IIS, so there was no need to write code to launch the service, open connections, etc. I could have defined additional endpoints in my Web.config, but the defaults worked fine for me. To make it easier, run the WCF Service Configuration Editor (it's in the Tools menu) once, and it will work as a context-menu item in Solution Explorer.Figure F
The WCF Service Configuration Editor. (Click the image to enlarge.)
Deploying is a snap. I installed the Web Deployment components on my server, right-clicked the project in Solution Explorer, and chose Publish. Filling out the wizard is pretty obvious. There are additional settings in the project's properties to allow more control over the publishing.Figure G
The service publishing wizard. (Click the image to enlarge.)
It was much easier to create my WCF service than I expected. Although I didn't go very deep into WCF's capabilities, such as security and authentication, I don't think most developers need those items (though, from what I have seen, the capabilities are not particularly hard to implement).
If you have been holding back on providing functionality as a Web service because it looked complicated or were confused about how to do it, it's time to roll up your sleeves and get started.
Justin James is the Lead Architect for Conigent.