Often, I’ll have a customer that wants to utilize a new feature in the .NET framework but they don’t necessarily know where to start or they have a large investment in another area and they’re afraid of the amount of rework required to get something working. This week, for example, I was teaching a customer about WPF and they asked:
“We have several class libraries and we’d like to expose them as WCF services. How can we do it?”
Yes, it was a bit off-topic from WPF but not really. I’ve found that when a customer chooses to start investing in a newer technology, like WPF, I’ve found that they also want to look at ways to revamp their existing applications to use other new features. But I digress…
In pre-.NET 4.0, if you wanted to expose a class as a WCF endpoint and make it available in IIS as an SVC file, you would have to do the following:
- Create a new WCF Service (in the same category as WebSite).
- Add a bunch of new “WCF Service” classes (files with an extension of “.SVC”).
- Write some code to call out to your existing class library from the WCF Service.
It’s not exactly a painful experience but would require a bit of work to get everything up and running. In many cases, if you have a huge investment in something like a class library, the amount of work may be incredibly daunting. Fortunately, using some of the features in WCF 4 (part of .NET 4), this type of story is ridiculously easy. The steps that we’ll follow are the following:
- Decorate your existing class.
- Add configuration.
- Deploy to IIS
Then, I’ll discuss additional options for debugging your new service.
Step 1: Decorate your existing class
So, I’m sure we all have a class in some Class Library somewhere that looks like this:
public class MyBusinessLogic
{
public string GetName(int id)
{
return "My ID is: " + id;
}
public MyDataClass GetEmpInformation(int id)
{
return new MyDataClass()
{
FirstName = "Greg",
LastName = "Varveris",
Occupation = "Developer"
};
}
}
This is just a simple little business logic class that exposes two public methods – GetName and GetEmpInformation. So, let’s say we wanted to make this class accessible as a WCF service. The first thing we need to do is add a reference to the .NET 4 version of System.ServiceModel in our Class Library project.
I’ve included a screenshot to our left just to further show that there is no special sauce here. All of the assemblies being referenced in this project are straight up class library defaults. Now that we have the assembly referenced, let’s decorate our class with two attributes:
- ServiceContract – This decorates our class and tells .NET that we have a WCF Service.
- OperationContract – This decorates our methods and tells .NET which methods/functions we want to expose in our service.
The decorated class will now look like:
[ServiceContract]
public class MyBusinessLogic
{
[OperationContract]
public string GetName(int id)
{
return "My ID is: " + id;
}
[OperationContract]
public MyDataClass GetEmpInformation(int id)
{
return new MyDataClass()
{
FirstName = "Greg",
LastName = "Varveris",
Occupation = "Developer"
};
}
}
And really that’s all you have to do from the code side.
Step 2: Add Configuration
WCF configuration has always been synonymous with “WOAH” before. Even using the great configuration editor tool, you may end up with a large amount of XML in your .config file. This is mostly because WCF is just so darn extensible. Well, for our scenario, we’ll use some great new features in WCF 4 to make the configuration a breeze:
- File-less Activation
- Default Configuration model
You can read-up about each of these features in the nice MSDN documentation. Basically, WCF 4 exposes the ability to map a file-name to a class and then it can expose a default endpoint (using BasicHttpBinding). For our scenario my entire config file is:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="MyBusinessLogic.svc" service="WCFSample.Library.MyBusinessLogic"/>
</serviceActivations>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
That’s it. In the first snippet, we are adding a relative address of “MyBusinessLogic.svc” which will point to our MyBusinessLogic class we defined above. The second section along the bottom is just to enable the service metadata.
The only minor manual snafu you’ll need to handle is that Visual Studio won’t let you add a web.config to a Class Library project. This can be easily remedied in a variety of ways. I just added an app.config to my project and then changed the name from “app.config” to “web.config”. Then, you just need to tell it to Copy to the output directory. This makes our project look like the following:
Step 3: Deploy to IIS
Now that we have our minuscule configuration and trivial decorations to our class, we need to host our service somewhere. For this, we’ll just use IIS with an ASP.NET 4.0 application pool. The structure of this folder will need to have the assemblies in a “bin” folder and the web.config in the root.
The bin folder is required so that the IIS engine can find your assembly. Once you configure this in IIS, you can simply navigate to your service (make sure you include the SVC in your url) in a browser and you’ll see the glorious WCF Service start page. For example, on my machine, when I navigate to: http://localhost/SampleWCFService/MyBusinessLogic.svc, I’ll see:
Debugging your service
So you have created your service, added configuration to it and deployed it to your hosting environment and everything is running smoothly. What if you want to debug the service in Visual Studio? Well, you really have 3 different options:
- Attach to the instance of w3wp hosting your WCF service.
- Cassini…errr, the ASP.NET Development Server.
- IIS Express
I personally prefer either options 2 or 3 as it provides that seamless debugging experience we all crave where we just hit the “Green Arrow” to start the debugging session. With either option you select, we’ll need to make one or two minor configuration changes.
First, we’ll need to tell the solution to start our process. For this, you can right-click on your solution file in the Solution explorer and select “Properties”. In this window, you’ll need to select the Multiple Startup Projects radio button and set both of your projects (the Client and the Service) to the “Start” option.
Second, you’ll need to add a pre/post-build step for your service to structure the output folder correctly. Since we will deleting the contents of the “Bin” folder wherever our assemblies are being output, the command we will use is:
if exist "$(TargetDir)bin" del /q "$(TargetDir)bin\*.*"
Then, for our post-build step, we will need to create the bin folder if it doesn’t exist and then copy over our DLL’s into that bin folder. Those commands will be:
if not exist "$(TargetDir)bin" mkdir "$(TargetDir)bin"
copy "$(TargetDir)\*.dll" "$(TargetDir)\bin"
copy "$(TargetDir)\*.pdb" "$(TargetDir)\bin"
del "$(TargetDir)\*.dll"
del "$(TargetDir)\*.pdb"
That will take our output directory from zero to hero quite nicely:
Now that the prerequisites are met, we just need to point our local hosting tool (either the Development Server or IIS Express) at that folder. We’ll do this in the Debug tab of the project properties. Set the “Start External Program” radio button and set the path to:
C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE
Then, in the Command Line Arguments, specify the following:
/port:12345
/path:"<path to folder containing bin & web.config>"
/vpath:/myservice
Then, you can set a Service Reference on whatever vpath you chose above. For example, my service reference points to: http://localhost:12345/myservice/MyBusinessLogic.svc
Once the service reference is set, you can just hit the fancy green arrow to start debugging:
Enjoy!