Partilhar via


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.

    Dim baseAddress As New Uri("https://localhost:8000/ServiceModelSamples/Service")
    
    Uri baseAddress = new Uri("https://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.

    Imports System.ServiceModel.Description
    
    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 https://localhost:8000/ServiceModelSamples/Service and CalculatorService is the type that implements the service contract.

    Dim selfHost As New ServiceHost(GetType(CalculatorService), baseAddress)
    
    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().

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

  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.

    ' 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);
    
  6. 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

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

See Also

Tasks

Getting Started Sample
Self-Host