How to: Host and Run a Basic Windows Communication Foundation Service
This is the third of six tasks required to create a basic Windows Communication Foundation (WCF) service and a client that can call the service. For an overview of all six of the tasks, see the Getting Started Tutorial topic.
This topic describes how to run a basic Windows Communication Foundation (WCF) service. This procedure consists of the following steps:
Create a base address for the service.
Create a service host for the service.
Enable metadata exchange.
Open the service host.
A complete listing of the code written in this task is provided in the example following the procedure. Add the following code into the Main()
method defined in the Program
class. This class was generated when you created the Service
solution.
To configure a base address for the service
Create a Uri instance for the base address of the service. This URI specifies the HTTP scheme, your local machine, port number 8000, and the path ServiceModelSample/Service to the service that was specified for the namespace of the service in the service contract.
Dim baseAddress As New Uri("https://localhost:8000/ServiceModelSamples/Service")
Uri baseAddress = new Uri("https://localhost:8000/ServiceModelSamples/Service");
To host the service
Import the
System.ServiceModel.Description
namespace. This line of code should be placed at the top of the Program.cs/Program.vb file with the rest of the using or imports statements.Imports System.ServiceModel.Description
using System.ServiceModel.Description;
Create a new ServiceHost instance to host the service. You must specify the type that implements the service contract and the base address. For this sample the base address is
https://localhost:8000/ServiceModelSamples/Service
andCalculatorService
is the type that implements the service contract.Dim selfHost As New ServiceHost(GetType(CalculatorService), baseAddress)
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
Add a try-catch statement that catches a CommunicationException and add the code in the next three steps to the try block. The catch clause should display an error message and then call
selfHost.Abort()
.Try ' ... Catch ce As CommunicationException Console.WriteLine("An exception occurred: {0}", ce.Message) selfHost.Abort() End Try
try { // ... } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); }
Add an endpoint that exposes the service. To do this, you must specify the contract that the endpoint is exposing, a binding, and the address for the endpoint. For this sample, specify
ICalculator
as the contract,WSHttpBinding
as the binding, andCalculatorService
as the address. Notice here the endpoint address is a relative address. The full address for the endpoint is the combination of the base address and the endpoint address. In this case the full address ishttps://localhost:8000/ServiceModelSamples/Service/CalculatorService
.' Add a service endpoint selfHost.AddServiceEndpoint( _ GetType(ICalculator), _ New WSHttpBinding(), _ "CalculatorService")
selfHost.AddServiceEndpoint( typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
Note
Starting with .NET Framework 4, if no endpoints are explicitly configured for the service then the runtime adds default endpoints when the ServiceHost is opened. This example explicitly adds an endpoint to provide an example of how to do so. For more information aboutdefault endpoints, bindings, and behaviors, see Simplified Configuration and Simplified Configuration for WCF Services.
Enable Metadata Exchange. To do this, add a service metadata behavior. First create a ServiceMetadataBehavior instance, set the HttpGetEnabled property to true, and then add the new behavior to the service. For more information about security issues when publishing metadata, see Security Considerations with Metadata.
' Enable metadata exchange Dim smb As New ServiceMetadataBehavior() smb.HttpGetEnabled = True selfHost.Description.Behaviors.Add(smb)
ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb);
Open the ServiceHost and wait for incoming messages. When the user presses the ENTER key, close the ServiceHost.
selfHost.Open() Console.WriteLine("The service is ready.") Console.WriteLine("Press <ENTER> to terminate service.") Console.WriteLine() Console.ReadLine() ' Close the ServiceHostBase to shutdown the service. selfHost.Close()
selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close();
To verify the service is working
Run the service.exe from inside Visual Studio. When running on Windows Vista, the service must be run with administrator privileges. Because Visual Studio was run with Administrator privileges, service.exe is also run with Administrator privileges. You can also start a new command prompt running it with Administrator privileges and run service.exe within it.
Open Internet Explorer and browse to the service's debug page at https://localhost:8000/ServiceModelSamples/Service.
Example
The following example includes the service contract and implementation from previous steps in the tutorial and hosts the service in a console application. Compile the following into an executable named Service.exe.
Be sure to reference System.ServiceModel.dll when compiling the code.
Imports System
Imports System.ServiceModel
Imports System.ServiceModel.Description
Module Service
' Define a service contract.
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
<OperationContract()> _
Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
End Interface
' Service class that implements the service contract.
' Added code to write output to the console window.
Public Class CalculatorService
Implements ICalculator
Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
Dim result As Double = n1 + n2
Console.WriteLine("Received Add({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
Dim result As Double = n1 - n2
Console.WriteLine("Received Subtract({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
Dim result As Double = n1 * n2
Console.WriteLine("Received Multiply({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
Dim result As Double = n1 / n2
Console.WriteLine("Received Divide({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
End Class
Class Program
Shared Sub Main()
' Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Dim baseAddress As New Uri("https://localhost:8000/ServiceModelSamples/Service")
' Step 2 of the hosting procedure: Create ServiceHost
Dim selfHost As New ServiceHost(GetType(CalculatorService), baseAddress)
Try
' Step 3 of the hosting procedure: Add a service endpoint.
' Add a service endpoint
selfHost.AddServiceEndpoint( _
GetType(ICalculator), _
New WSHttpBinding(), _
"CalculatorService")
' Step 4 of the hosting procedure: Enable metadata exchange.
' Enable metadata exchange
Dim smb As New ServiceMetadataBehavior()
smb.HttpGetEnabled = True
selfHost.Description.Behaviors.Add(smb)
' Step 5 of the hosting procedure: Start (and then stop) the service.
selfHost.Open()
Console.WriteLine("The service is ready.")
Console.WriteLine("Press <ENTER> to terminate service.")
Console.WriteLine()
Console.ReadLine()
' Close the ServiceHostBase to shutdown the service.
selfHost.Close()
Catch ce As CommunicationException
Console.WriteLine("An exception occurred: {0}", ce.Message)
selfHost.Abort()
End Try
End Sub
End Class
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Microsoft.ServiceModel.Samples
{
// Define a service contract.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
// Service class that implements the service contract.
// Added code to write output to the console window.
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
class Program
{
static void Main(string[] args)
{
// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("https://localhost:8000/ServiceModelSamples/Service");
// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService");
// Step 4 of the hosting procedure: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 of the hosting procedure: Start (and then stop) the service.
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
}
Note
Services such as this one require permission to register HTTP addresses on the machine for listening. Administrator accounts have this permission, but non-administrator accounts must be granted permission for HTTP namespaces. For more information about how to configure namespace reservations, see Configuring HTTP and HTTPS. When running under Visual Studio, the service.exe must be run with administrator privileges.
Now the service is running. Proceed to How to: Create a Windows Communication Foundation Client. For troubleshooting information, see Troubleshooting the Getting Started Tutorial.