Showing posts with label service hosting. Show all posts
Showing posts with label service hosting. Show all posts

Wednesday, 9 March 2011

WCF Services with Zero Config (on both the Host and Client)

When dealing with your WCF services have you ever gotten so confused with all the settings in your App.Config that you just wanted to throw the file away? Well now you can, and I’ll show you how.

With .Net 4.0 WCF allows developers to take the convention over configuration approach to their services. This means that by omitting configuration settings, the .Net framework will create defaults in their place and make your services fully available and operational.

So lets check out how it’s done!

First, create a new WCF Service Library project and call it WcfZeroConfig:

new-project

Now, and this is good bit, delete the App.Config file. Just right click on the file, select Delete – feels good right?!

The WCF Service Library project template makes two methods available for us by default and for this artictle we’ll be using the GetData(int value) method for our example.

As our WCF library is now complete, we are going to add another project to our solution to host the service. In production you would usually use IIS or a Windows Service to host your WCF Service Library but for this simple example we are going to use a Console application.

From the Visual Studio main menu select File > Add > New Project > Windows > Console Application and name the project WcfHost:

Console-project

As this project will be acting as the host we’ll need to add references to both the System.ServiceModel assembly and our WCF Service Library project. Right click on the WcfHost Project file, select Add Reference and select System.ServiceModel framework:

servicemodel-ref

Now select Projects (in the top left hand corner) and double click the WcfZeroConfig and press the close button.

Add-reference

To complete the host, copy and paste the following code into the Program.cs file:


As you can see it takes one line of code to create the ServiceHost object, passing in an Endpoint address and a single method call to open the host channel to make the service available.


On startup of the host, under the covers WCF (in .Net 4.0) will detect that no Binding or Contract has been supplied, either in our App.Config file or from our code, and will provide default values. From the Endpoint address the framework can see we are using Http and will provide the default binding of basicHttpBinding. The contract type of IService1 will also be inferred from the Service1 concrete class.


To run the host, select the WcfHost project and press F5 to build and run the application.


wcfhost


We are now ready to create the client application to consume our WCF Service. From the Visual Studio main menu select File > Add > New Project > Windows > Console Application and name the project WcfClient:


wcfclient


As before you’ll need to add the System.ServiceModel framework (right click on the project file > Add Reference…) along with the WcfZeroConfig project, this is so that the WcfClient project is aware of the WCF Service contract type “IService1”.


To complete our client, just paste in the following lines of code into the Program.cs file:


To complete our example:


1) You’ll first need to build the solution by right clicking on the solution file and selecting Build Solution


2) Run the C:\Projects\WcfZeroConfig\WcfHost\bin\Debug\WcfHost.exe file


3) And finally, run the C:\Projects\WcfZeroConfig\WcfClient\bin\Debug\WcfClient.exe file and enter a number


That number then gets passed to our WCF Service and our client receives the result.


WcfClient-result


The full source code is available here: WcfZeroConfig.zip

Sunday, 6 March 2011

How to host multiple isolated WCF services within a single Windows service with zero App.config

Note: The code featured in this blog posting was put together whilst working with David Marsh on the Tranquility.Net (Wcf App Server), an open source .Net app server available on CodePlex.

CodePlex project: http://tranquilitydotnet.codeplex.com/

The source code for this blog entry can be found on the CodePlex project (using the link above), click on the Source Code tab and download changeset 2671 (Initial commit of source).

Ok, hands up who loves IIS? Nope, me neither. Tired of it hogging RAM and eating up your server resources when hosting your lightweight Wcf services? Why not host all your services within a single Windows service on your server. But app pooling in IIS is pretty cool right, we can’t do without that – no problem, we’ll just wrap each of our services within it’s own AppDomain so we can recycle as required.

For an added bonus I’ve removed the Wcf configuration aka the A, B, C’s (Address, Binding and Contract’s) from the app.Config so you can dynamically load them at runtime. This means we could retrieve this information from a central configuration service or from a database, etc,

Ooh that all makes sense but it sounds hard? Nope, it’s easy.

Overview of Classes

Overview-of-classes

The Classes Explained

Program.cs:

The main entry point of the program, on startup of the Windows the service this class just creates and runs a ServiceContainer.

ServiceContainer.cs, ConfigService.cs, WcfServiceConfig.cs and WcfService.cs:

ServiceContainer-and-Config-class

When the ServiceContainer starts, it makes a call to the ConfigService to get the Wcf service information (assembly, service and contract names) along with the endpoint Uri address e.g net.tcp://localhost:8323/WcfServiceLibrary1/Service1. From this information the WcfAppServer can create the A. B, C for the Wcf configuration. The address is provided, the binding can be inferred from the start of the address and the contract and service types are read using reflection on the assembly.

Note: The service DLLs do not need to be referenced (within Visual Studio) by the WcfAppServer but the files will need to be placed in the same folder as the WcfAppServer.exe. This allows reflection to retrieve all required type information.

You can replace the ConfigService code for a call to your own config service or database. For this demonstration the ConfigService just returns hard coded information (see further down for code).

Once the ServiceContainer has its list of WcfServiceConfigs, it loops through each item first creating, then opening an IsolatedServiceHost for each service. A list of IsolatedServiceHosts is stored by the ServiceContainer.

ServiceContainer_OnStart

IsolatedServiceHost.cs:

This class isolates each service host by creating a ServiceHostWrapper object within a new AppDomain. This ensures one service faulting will not affect any of the other services.

IsolatedServiceHost

ServiceHostWrapper.cs:

This class simply serves as a wrapper around the generic .Net ServiceHost with the added bonus of being derived from MarshalByRefObject which allows for cross AppDomain communication. This enables our service container to send commands to our ServiceHost like Open, Close and Abort – which is pretty sweet! A couple of methods to easily setup the WCF config have also been included.

ServiceHostWrapper

WcfServiceInstaller.cs:

installer

This code allows the Windows Service to be installed from either a setup deployment project (.msi) or by using the InstallUtil command. For this example we’ll be using the InstallUtil command. The AfterInstall event will startup the service on our behalf service.

WcfHelper.cs:

WcfHelper

This class infers and creates the binding from the start of an endpoint address. For example:

net.tcp://localhost:7834/Assembly/Service requires the net tcp binding

http://localhost:7834/Assembly/Service requires the HTTP binding

Right, it’s….. SHOWTIME!

Ok, so you ready for some code? Here’s how it’s done.

Note: This code was created using Visual Studio 2010 Ultimate edition.

Create a Windows Service from Visual Studio, called “WcfAppServer”:

Create-windows-service

Once project has been created, remove the default Service1.cs file from your project.

As we’ll be dealing with WCF services, we’ll want to a reference to the System.ServiceModel and System.ServiceProcess frameworks. Just right click on References and select Add Reference…, then scroll down and double click on System.ServiceModel and System.ServiceProcess.

A third reference System.Configuration.Install is also required by the service installer class.

Add-reference

In order to be able to build the project whilst we add each file, just to make sure we haven’t entered a typeo, you’ll want to comment out the reference to recently removed Service1 class.

Program.cs

Next up we’ll need to add our files, you can cut and paste from the code below or download these files from the source code links at the bottom of this blog.


WcfHelper.cs


ServiceHostWrapper.cs


IsolatedServiceHost.cs


WcfService.cs

WcfServiceConfig.cs

ConfigService.cs


ServiceContainer.cs


So we can install our Windows Service we’ll need to add an installer class.


WcfAppServerInstaller.cs


Finally, update the Program.cs file to instantiate our ServiceContainer class on start up:


We now need to add our two Wcf Service Libraries to the project which will act as sample libraries for our demo. From the Visual Studio main menu select File > Add > Add New Project, and then select WCF > WCF Service Library, accepting the default name and location for the project.


Add-new-wcf-project-1


Repeat the process again to add a second WcfServiceLibrary, this time with the default name WcfServiceLibrary2.


To ensure each Wcf Service Library returns a unique message (so we can tell them apart during the demo), update each service to return a relevant message.


WcfServiceLibrary1.Service1.cs


And repeat for WcfServiceLibrary2.Service1.cs.


Now the next bit is optional and I’ll explain why. The WcfAppServer can load and host any Wcf Service classes from a .Net assembly. All you need to do is drop the dll into the same folder as the WcfAppServer.exe and using reflection, the service will load them from our “config service”.


For this demo I’m going to include the project references to save having to build and copy across the DLL files manually. To add the references to our WcfAppServer project right click on the WcfAppServer project > Add Reference…, then select Projects and double click on each of our new projects:


Add-project-reference


So with a quick “CTRL + SHIFT + B” to build the project in debug mode, we are now ready to install our new Windows Service. Just run the following commands from the Visual Studio Command Prompt:


install-service


Note: The Visual Studio Command Prompt can be found in the Visual Studio tools shortcut folder (Start > Programs > Microsoft Visual Studio 2010 > Visual Studio Tools > Visual Studio Command Prompt (2010)).


Now we can start up our Wcf App Server Windows Service and test our hosting.


Open the Services mmc management window (Start > Control Panel > Administration Tools > Services)


Start-Service


Now our Windows Service is up and running we can test them using the WcfTestClient. To add this Tool to Visual Studio, from the main menu in Visual Studio select Tools > External Tools, then enter the following details:


WcfTestClient


The WcfTestClient.exe can be found within C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ folder.


Note: This tool is installed relative to your Visual Studio installation folder (64 bit machines will be different from the above address).


You can now run the tool from within Visual Studio. From the main menu Tools > WcfTestClient


You can now add each of our services to the test client by right clicking on My Service Projects > Add Service…


add-service


Once you’ve added both the Wcf endpoints you’re ready to start test driving your services!


Testing WcfServiceLibrary1


testing-nettcp-1


Testing WcfServiceLibrary2


testing-nettcp-2