How to: Host and Run a Basic Service
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

  1. 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.

    Visual Basic
    Dim baseAddress As New Uri("http://localhost:8000/ServiceModelSamples/Service")
    C#
    Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");

To host the service

  1. 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.

    Visual Basic
    Imports System.ServiceModel.Description
    C#
    using System.ServiceModel.Description;
  2. 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 http://localhost:8000/ServiceModelSamples/Service and CalculatorService is the type that implements the service contract.

    Visual Basic
    Dim selfHost As New ServiceHost(GetType(CalculatorService), baseAddress)
    C#
    ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
  3. 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().

    Visual Basic
    Try
        ' ...
    Catch ce As CommunicationException
        Console.WriteLine("An exception occurred: {0}", ce.Message)
        selfHost.Abort()
    End Try
  4. 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, and CalculatorService 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 is http://localhost:8000/ServiceModelSamples/Service/CalculatorService.

    Visual Basic
    ' Add a service endpoint
    selfHost.AddServiceEndpoint( _
        GetType(ICalculator), _
        New WSHttpBinding(), _
        "CalculatorService")
    C#
    selfHost.AddServiceEndpoint(
        typeof(ICalculator),
        new WSHttpBinding(),
        "CalculatorService");
  5. 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.

    Visual Basic
    ' Enable metadata exchange
    Dim smb As New ServiceMetadataBehavior()
    smb.HttpGetEnabled = True
    selfHost.Description.Behaviors.Add(smb)
    C#
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    selfHost.Description.Behaviors.Add(smb);
  6. Open the ServiceHost and wait for incoming messages. When the user presses the ENTER key, close the ServiceHost.

    Visual Basic
    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()
    C#
    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

  1. 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.

  2. Open Internet Explorer and browse to the service's debug page at http://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.

Visual Basic
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("http://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
C#
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("http://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();
            }

        }
    }
}
ms730935.note(en-us,VS.90).gifNote:
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.

See Also


© 2007 Microsoft Corporation. All rights reserved.
Build Date: 2009-10-13
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Enable Metadata Publishing      DBROCK ... Thomas Lee   |   Edit   |   Show History
If this is a WCF web service, you will need to enable metadata publishing. Please refer to MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.
Typo in comments      Jeff Certain ... rbsevertson   |   Edit   |   Show History
Minor detail, but step 1 appears twice in the comments for the hosting code, and step 2 never appears.

Thanks. This has been fixed and will be seen in SP1 - Brad CSDUA
Try/Catch misses exceptions      Jeff Certain   |   Edit   |   Show History
Steps 1 and 2 need to be moved into the try/catch block:
Dim selfHost As ServiceHost = Nothing

Try
' Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Dim baseAddress As New Uri("http://localhost:8000/ServiceModelSamples/Services")

' Step 2 of the hosting procedure: Create ServiceHost
selfHost = New ServiceHost(GetType(CalculatorService), baseAddress)

This will allow the exception handler to catch the error that occurs if permissions are not set correctly.

The catch block also needs to be modified to leave the console open to read the exception:
Catch ce As CommunicationException
Console.WriteLine("An exception occurred: {0}", ce.Message)
Console.ReadLine()
If selfHost IsNot Nothing Then selfHost.Abort()
End Try
Type/inconsistent address redux      Jeff Certain ... BradSeverton   |   Edit   |   Show History
Okay... same problem as reported in the first comment for C#, but in VB.

Currious. This is fixed in the code but was not picked up for some reason. It should be with the SP1.
Sorry about that. -Brad CSDUA
oops retracted      ChristianProgrammer2   |   Edit   |   Show History
previous Steps instructed me to continue work in the same file.....
so where do I create the URI in the class CalculatorService : ICalculator

or in the class program??
Flag as ContentBug
Typo/Bug      gmyers ... Thomas Lee   |   Edit   |   Show History
Namespace "Microsoft.ServiceModel.Samples" becomes never-ending Module Service...

Confusing      AugustWest   |   Edit   |   Show History
On the previous page the code shows that the class CalculatorService has both the Interface definition (ICALCULATOR) as well as the class definition called CalculatorService that implements the interface. But on this page the code shows the interface definition wrapped in the Module called Service. Where the heck did that come from?

Also this page references a new file named Program.vb (or .cs) but no mention of when that was supposed to be created. It appears that we are supposed to add a new class file called program, but it also says that the Sub Main() will be created, which it will not (at least not in VB).

But it appears in the final code at the bottom of this page that the module definition, and the two classes are all contained within one file. It is very confusing.

One other thing, there is a BUG in this code as it is missing the End Module statement.
Tags What's this?: Add a tag
Flag as ContentBug
C#      Vishnu_ingr ... VictorFeintuch   |   Edit   |   Show History
The C# code in this section is missing. How do we host and run using C# ?
I separated the Interface code into a class file.
You can retrieve it from the previous tutorials.
Here is the rest of the code in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description ;

namespace Microsoft.ServiceModel.Samples
{


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("http://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.
// Add a service endpoint
selfHost.AddServiceEndpoint(
typeof (ICalculator),
new WSHttpBinding(),
"CalculatorService");

// Step 4 of the hosting procedure: Enable metadata exchange.
// Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
smb.HttpGetEnabled = true;


// 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();
}




}
}


}


Add permission for HTTP namespaces in Windows 7      Eric Walstra   |   Edit   |   Show History
For windows 7 beta (I think it also applies to Vista) I needed to execute the following in an administrator command prompt:

netsh http add urlacl url=http://+:8000/ServiceModelSamples/Service user=DOMAIN/user
Tags What's this?: Add a tag
Flag as ContentBug
Not getting a debug view in IE      Sephora   |   Edit   |   Show History
I am using Vista and running VS2008 with Admin privalages. I ran the solution using the 'start without debugging' tab. Program ran fine. I cannot however browse the service's debug page. I get a web page with the message 'Internet explorer cannot display the web page',
Tags What's this?: Add a tag
Flag as ContentBug
Processing
Page view tracker