In the previous chapter, we built a basic HelloWorld
WCF service, and hosted it with the ASP.NET Development Server. In this chapter, we will explore more hosting options for WCF services, including hosting WCF services in a managed application, in a Windows Service, in IIS, and in some other advanced WCF hosting applications.
We will also explain how to debug WCF services, including debugging from the client application, debugging only the WCF service, attaching to the WCF service process, and the Just-In-Time debugger.
In this chapter, we will discuss:
In the previous chapter, we hosted our HelloWorldService
in the ASP.NET Development Server. In addition to this, we have several other options for hosting a WCF service. In this section, we will explore them one by one.
We can create a .NET managed application, and host a WCF service inside the application. The hosting application can be a command line application, a Windows form application, or a web application. This hosting method gives you full control over the lifetime of the WCF service. It is very easy to debug and deploy, and supports all bindings and transports. The drawback of this hosting method is that you have to start the hosting application manually, and it has only limited support for high availability, easy manageability, robustness, recoverability, versioning, and deployment scenarios.
For example, what follows are the steps to host HelloWorldService
in a command line application. Note that these steps are very similar to the steps in the previous section where we hosted a WCF service in the ASP.NET Development Server. However, we must remember that we don't need a .svc
file, and that the configuration file is called app.config
, and not web.config
. Refer to the previous section for diagrams. Also, if you want to host a WCF service in a Windows Form application, or a web application, you can follow the same steps as we have listed here simply by creating the project using an appropriate project template.
In the Solution Explorer, right-click on the solution file, and select Add | New Project…, from the context menu. The Add New Project dialog box should appear. Select Visual C# as the project type, and Console Application as the template. Then, change the name from ConsoleApplication1 to HostCmdLineApp, and click the OK button. A new project is added to the solution.
HostCmdLineApp
as the startup project:In the Solution Explorer, right-click on the project HostCmdLineApp
, and select Set as StartUp Project from the context menu. You can also select the project in the Solution Explorer, and click on menu item Project | Set as StartUp Project to do this.
HelloWorldService
project.In the Solution Explorer, right-click on the project HostCmdLineApp
and select Add Reference…, from the shortcut menu. The Add Reference dialog box should appear. Click on the Projects tab, select the HelloWorldService
project, and then click OK. Now, the HelloWorldService
is under the References folder of this project. You will also notice that two files from HelloWorldService
project have been copied to the bin
directory under this project. If you can't see the bin directory, press F4, or click on the Show All Files icon in the Solution Explorer.
System.ServiceModel:
This reference is required, as we will manually create a service host application and start and stop it in the steps that follow. In the Solution Explorer window, right click on the HostCmdLineApp
project, and select Add Reference… from the context menu. You can also select menu item Project | Add Reference… to do this. Select System.ServiceModel
from the .NET tab, and click OK.
The configuration file will be very similar to the configuration file we created for the HostDevServer
project. So, in Windows Explorer, copy the web.config
file from the project folder of HostDevServer
to the project folder of HostCmdLineApp
, change its name to app.config
, then from Solution Explorer, include this file in the project HostCmdLineApp
(if you can't see app.config
file under this project, click the Show All Files button in the Solution Explorer, or click the Refresh button to refresh the screen).
Open this configuration file, and change the HTTPBaseAddress from empty to http://localhost:8080/HostCmdLineApp/HelloWorldService/. This means we will host HelloWorldService
using http, at port 8080, and under the HostCmdLineApp
virtual directory.
app.config
file:<?xml version="1.0"?> <configuration> <appSettings> <add key="HTTPBaseAddress" value="http://localhost:8080/ HostCmdLineApp/HelloWorldService/"/> </appSettings> <system.serviceModel> <services> <service name="MyWCFServices.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors"> <endpoint address="" binding="wsHttpBinding" contract="MyWCFServices.IHelloWorldService"/> <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/> </service> HelloWorld WCF service, hostingin console application</services> <behaviors> <serviceBehaviors> <behavior name="MyServiceTypeBehaviors"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> <system.web> <compilation debug="true"/></system.web></configuration>
Program.cs
file to write some code to start and stop the WCF service inside the Program.cs
.First, add two using statements as follows: using System.ServiceModel; using System.Configuration; Then, add the following lines of codes within the static Main method: Type serviceType=typeof(MyWCFServices.HelloWorldService); string httpBaseAddress = ConfigurationSettings.AppSettings["HTTPBaseAddress"]; Uri[] baseAddress = new Uri[] {new Uri(httpBaseAddress)}; ServiceHost host = new ServiceHost(serviceType, baseAddress); host.Open(); Console.WriteLine("HelloWorldService is now running. "); Console.WriteLine("Press any key to stop it ..."); Console.ReadKey(); host.Close();
As you can see, we just get the type of the HelloWorldService, construct a base address for the WCF service, create a service host passing the type and base address, and call the Open method of the host to start the service. To stop the service, we just call the Close method of the service host.
Program.cs
file.using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Configuration; namespace HostCmdLineApp { class Program { static void Main(string[] args) {
Type serviceType=typeof(MyWCFServices.HelloWorldService); string httpBaseAddress = ConfigurationSettings.AppSettings["HTTPBaseAddress"]; Uri[] baseAddress = new Uri[] {new Uri(httpBaseAddress)}; ServiceHost host = new ServiceHost(serviceType, baseAddress); host.Open(); Console.WriteLine("HelloWorldService is now running. "); Console.WriteLine("Press any key to stop it ..."); Console.ReadKey(); host.Close(); } } }
HelloWorldService
is available and is waiting for requests.To consume the service hosted in the above console application, you can follow the same steps as described in the section "Creating a Client to Consume the HelloWorld WCF Service" above, except that you pass http://localhost:8080/HostCmdLineApp/HelloWorldService/?wsdl
and not http://localhost:8080/HostDevServer/HelloWorldService.svc?wsdl
to the SvcUtil.exe
when you generate the proxy class and the configuration file.
In fact, you can re-use the same client project, but inside the app.config
file, change the following line:
<endpoint ddress="http://localhost:8080/HostDevServer/HelloWorldService.svc"
To this line:
<endpoint address="http://localhost:8080/HostCmdLineApp/HelloWorldService/"
Now, when you run this client program, it will use the WCF service hosted in our newly created command line application and not the previously-created HostDevServer
application. You will get the same result as before, when the ASP.NET Development Server was used to host the WCF service.
If you don't want to manually start the WCF service, you can host it in a Windows service. In addition to the automatic start, Windows service hosting gives you some other features such as recovery ability when failures occur, security identity under which the service is run, and some degree of manageability. Just like the self-hosting method, this hosting method also supports all bindings and transports. However, it has some limitations; for example, you have to deploy it with an installer, and it doesn't fully support high availability, easy manageability, versioning, or deployment scenarios.
The steps to create such a hosting application are very similar to what we did to host a WCF service in a command line application, except that you have to create an installer to install the Windows service in the Service Control Manager (or you can use the .NET Framework Installutil.exe
utility).
It is a better option to host a WCF service within the Internet Information Server (IIS), because IIS provides a robust, efficient, and secure host for the WCF services. IIS also has better thread and process execution boundaries handling (in addition to many other features) compared to a regular managed application. Actually, web service development on IIS has long been the domain of ASP.NET. When ASP.NET 1.0 was released, a web service framework was part of it. Microsoft leveraged the ASP.NET HTTP pipeline to make web services a reality on the Windows platform.
The main drawback of hosting the service within the IIS prior to version 7.0 is the tight coupling between ASP.NET and Web services, which limits the transport protocol to HTTP/HTTPs.
Another thing you need to pay particular attention to when hosting WCF in the IIS is that the process and/or application domain may be recycled if certain conditions are met. By default, the WCF service session state is not saved in memory so that each recycle will lose all such information. This will be a big problem if you run a web site in a load-balanced or web-farm (web-garden) environment. In this case, you might want to turn on the ASP.NET compatibility mode (add the attribute AspNetCompatibilityRequirements
to your WCF service) so that the session state can be persisted in an SQL Server database or in the ASP.NET State Server.
Now, we will explain how to host the HelloWorldService
within IIS.
First, we need to prepare the folders and files for the host application. Follow these steps to create the folders and copy the required files:
In the Windows Explorer, create a new folder called HostIIS under D:SOAwithWCFandLINQProjectsHelloWorld, and a new subfolder called bin under this HostIIS folder. You should now have the following new folders:
D:SOAwithWCFandLINQProjectsHelloWorldHostIIS D:SOAwithWCFandLINQProjectsHelloWorldHostIISin
Now, copy the files HelloWorldService.dll and HelloWorldService.pdb from the HelloWorldService project folder D:SOAwithWCFandLINQProjectsHelloWorldHelloWorldServiceinDebug to the new folder we created, D:SOAwithWCFandLINQProjectsHelloWorldHostIISin.
Copy the files HelloWorldService.svc and Web.config from the HostDevServer project folder D:SOAwithWCFandLINQProjectsHelloWorldHostDevServer to the new folder, D:SOAwithWCFandLINQProjectsHelloWorldHostIIS.
The files under the two new directories now should be like the following:
Folder |
HostIIS |
HostIISin |
---|---|---|
Files |
HelloWorldService.svc Web.config |
HelloWorldService.dll HelloWorldService.pdb |
Next, we need to create a virtual directory named HelloWorldService
. Follow these steps to create this virtual directory in the IIS.
Once you have the files copied to the HostIIS
folder, and have the virtual directory created, the WCF service is ready to be called by the clients. When a WCF service is hosted within IIS, we don't need to explicitly start the service. As with other normal web applications, IIS will control the lifetime of the service. As long as the IIS is started, client programs can access it.
To test the WCF service, open an Internet browser, and enter the following URL in the address bar of the browser. You will get an almost identical screen to the one you got previously:
http://localhost/HelloWorldService/HelloWorldService.svc
You don't need to add a port after the host, because it is now hosted in the IIS with the default HTTP port 80. This also means that you can access it using your real computer (host) name, and even outside of your network if you are connected to the Internet. Two example URLs are as follows:
http://[your_pc_name]/HelloWorldService/HelloWorldService.svc http://[your_pc_name].[your_company_domain].com/HelloWorldService/HelloWorldService.svc
We can re-use the client program we created earlier to consume this WCF service hosted within the IIS. Just change the endpoint address line from this:
<endpoint address="http://localhost:8080/HostCmdLineAPP/HelloWorldService.svc"
To this:
<endpoint address="http://localhost/HelloWorldService.svc"
Now, when you run this client program, it will use the WCF service hosted within the IIS, and not the previously-created HostCmdLineApp
application. You will get the same result as before, when it was hosted in our own host application.
The hosting methods we previously discussed were the three most popular options prior to Visual Studio 2008/Internet Information Services (IIS) 7.0 (Windows Vista / Windows 2008). In addition to these, there are some new advanced hosting methods for a WCF service in Visual Studio 2008 and IIS 7.0.
In Visual Studio 2008, there is a ready-made, general-purpose WCF Service Host (WcfSvcHost.exe), which makes the WCF host and development test much easier. This host will be used by default if you create a WCF service using a WCF Service Library template. We will cover this new feature in a later chapter.
Another option is to create a WCF service using a WCF Service Application template, in which case the WCF service project itself is a web site and is ready to run within its own project folder. We will also cover this new feature later.
With Internet Information Services (IIS) 7 (Windows Vista / Windows Server 2008), there is another new feature called Windows Activation Services (WAS). This feature makes it possible to host a WCF service using all four WCF transport protocols (HTTP, NET.TCP, and NET.PIPE, NET.MSMQ), instead of just HTTP/HTTPS as in the case in IIS 6.0. As we will only use HTTP protocol in this book, we will not discuss this hosting method. However, in your real projects, you are recommended to explore this option and use it wherever possible.