How to: Create a Basic WCF REST Service

Windows Communication Foundation (WCF) allows you to create a service that exposes a Web endpoint. Web endpoints send data by plain XML, there is no SOAP envelope. This topic demonstrates how to expose such an endpoint.

Note

The only way to secure a Web endpoint is to expose it through HTTPS, using transport security. When using message-based security, security information is usually placed in SOAP headers, because the messages sent to non-SOAP endpoints contain no SOAP envelope, there is nowhere to place the security information and you must rely on transport security.

To create a Web endpoint

  1. Define a service contract using an interface marked with the ServiceContractAttribute, WebInvokeAttribute and the WebGetAttribute attributes.

    <ServiceContract()> _
    Public Interface IService
        <OperationContract()> _
        <WebGet()> _
        Function EchoWithGet(ByVal s As String) As String
    
        <OperationContract()> _
        <WebInvoke()> _
        Function EchoWithPost(ByVal s As String) As String
      end interface
    
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        string EchoWithGet(string s);
    
        [OperationContract]
        [WebInvoke]
        string EchoWithPost(string s);
    }
    

    Note

    By default WebInvokeAttribute maps POST calls to the operation. You can, however, specify the method to map to the operation by specifying a "method=" parameter. WebGetAttribute does not have a "method=" parameter and only maps GET calls to the service operation.

  2. Implement the service contract.

    Public Class Service
        Implements IService
        Public Function EchoWithGet(ByVal s As String) As String Implements IService.EchoWithGet
            Return "You said " + s
        End Function
    
        Public Function EchoWithPost(ByVal s As String) As String Implements IService.EchoWithPost
            Return "You said " + s
        End Function
    End Class
    
    public class Service : IService
    {
        public string EchoWithGet(string s)
        {
            return "You said " + s;
        }
    
        public string EchoWithPost(string s)
        {
            return "You said " + s;
        }
    }
    

To host the service

  1. Create a WebServiceHost object.

    Dim host As WebServiceHost = New WebServiceHost(GetType(Service), New Uri("https://localhost:8000/"))
    
    WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("https://localhost:8000/"));
    
  2. Add a ServiceEndpoint with the WebHttpBehavior.

    Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
    
    ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
    

    Note

    If you do not add an endpoint, WebServiceHost automatically creates a default endpoint. WebServiceHost also adds WebHttpBehavior and disables the HTTP Help page and the Web Services Description Language (WSDL) GET functionality so the metadata endpoint does not interfere with the default HTTP endpoint.

    Adding a non-SOAP endpoint with a URL of "" causes unexpected behavior when an attempt is made to call an operation on the endpoint. The reason for this is the listen URI of the endpoint is the same as the URI for the help page (the page that is displayed when you browse to the base address of a WCF service).

    You can do one of the following actions to prevent this from happening:

    • Always specify a non-blank URI for a non-SOAP endpoint.

    • Turn off the help page. This can be done with the following code.

    Dim sdb As ServiceDebugBehavior = host.Description.Behaviors.Find(Of ServiceDebugBehavior)()
    sdb.HttpHelpPageEnabled = False
    
    ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
    sdb.HttpHelpPageEnabled = false;
    
  3. Open the service host and wait until the user presses ENTER.

    host.Open()
    Console.WriteLine("Service is running")
    Console.WriteLine("Press enter to quit...")
    Console.ReadLine()
    host.Close()
    
    host.Open();
    Console.WriteLine("Service is running");
    Console.WriteLine("Press enter to quit...");
    Console.ReadLine();
    host.Close();
    

    This sample demonstrates how to host a Web-Style service with a console application. You can also host such a service within IIS. To do this, specify the WebServiceHostFactory class in a .svc file as the following code demonstrates.

    <%ServiceHost 
        language=c#
        Debug="true"
        Service="Microsoft.Samples.Service"
        Factory=System.ServiceModel.Activation.WebServiceHostFactory%>
    

    This sample configures the web service host imperatively in code, you can also configure the web service host in an application configuration file. The following application configuration file can be used to perform the same configuration as the code listed above.

    <configuration>
      <system.serviceModel>
        <services>
          <service
              name="Microsoft.ServiceModel.Samples.BasicWebProgramming.Service"
              behaviorConfiguration="MyServiceBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="https://localhost:8000/"/>
              </baseAddresses>
            </host>
            <endpoint address="" 
                      binding="webHttpBinding"
                      contract="Microsoft.ServiceModel.Samples.BasicWebProgramming.IService" />
    
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyServiceBehavior">
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>
    

    In order to use the application configuration file, you must make some modifications to the previous code. You no longer have to specify the base address, service behaviors, or endpoints in code. The following example shows this modified code.

     using (WebServiceHost host = new WebServiceHost(typeof(Service)))
          {
              host.Open();
              Console.WriteLine("Service is running");
              Console.WriteLine("Press enter to quit...");
              Console.ReadLine();
              host.Close();
    }
    

To call service operations mapped to GET in Internet Explorer

  1. Open Internet Explorer and type "https://localhost:8000/EchoWithGet?s=Hello, world!" and press ENTER. The URL contains the base address of the service ("https://localhost:8000/"), the relative address of the endpoint (""), the service operation to call ("EchoWithGet"), and a question mark followed by a list of named parameters separated by an ampersand (&).

To call service operations in code

  1. Create an instance of ChannelFactory within a using block.

    Using cf As New ChannelFactory(Of IService)(New WebHttpBinding(), "https://localhost:8000")
    
    using (ChannelFactory<IService> cf = new ChannelFactory<IService>(new WebHttpBinding(), "https://localhost:8000"))
    
  2. Add WebHttpBehavior to the endpoint the ChannelFactory will call.

    cf.Endpoint.Behaviors.Add(New WebHttpBehavior())
    
    cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
    
  3. Create the channel and call the service.

    Dim channel As IService = cf.CreateChannel()
    
    Dim s As String
    
    Console.WriteLine("Calling EchoWithGet via HTTP GET: ")
    s = channel.EchoWithGet("Hello, world")
    Console.WriteLine("   Output: {0}", s)
    
    Console.WriteLine("")
    Console.WriteLine("This can also be accomplished by navigating to")
    Console.WriteLine("https://localhost:8000/EchoWithGet?s=Hello, world!")
    Console.WriteLine("in a web browser while this sample is running.")
    
    Console.WriteLine("")
    
    Console.WriteLine("Calling EchoWithPost via HTTP POST: ")
    s = channel.EchoWithPost("Hello, world")
    Console.WriteLine("   Output: {0}", s)
    
    IService channel = cf.CreateChannel();
    
    string s;
    
    Console.WriteLine("Calling EchoWithGet via HTTP GET: ");
    s = channel.EchoWithGet("Hello, world");
    Console.WriteLine("   Output: {0}", s);
    
    Console.WriteLine("");
    Console.WriteLine("This can also be accomplished by navigating to");
    Console.WriteLine("https://localhost:8000/EchoWithGet?s=Hello, world!");
    Console.WriteLine("in a web browser while this sample is running.");
    
    Console.WriteLine("");
    
    Console.WriteLine("Calling EchoWithPost via HTTP POST: ");
    s = channel.EchoWithPost("Hello, world");
    Console.WriteLine("   Output: {0}", s);
    
  4. Close the WebServiceHost.

    host.Close()
    
    host.Close();
    

Example

The following is the full code listing for this example.

'Service.cs
Imports System
Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Web
Imports System.Text

<ServiceContract()> _
Public Interface IService
    <OperationContract()> _
    <WebGet()> _
    Function EchoWithGet(ByVal s As String) As String

    <OperationContract()> _
    <WebInvoke()> _
    Function EchoWithPost(ByVal s As String) As String
  end interface

Public Class Service
    Implements IService
    Public Function EchoWithGet(ByVal s As String) As String Implements IService.EchoWithGet
        Return "You said " + s
    End Function

    Public Function EchoWithPost(ByVal s As String) As String Implements IService.EchoWithPost
        Return "You said " + s
    End Function
End Class

Module program

    Sub Main()
        Dim host As WebServiceHost = New WebServiceHost(GetType(Service), New Uri("https://localhost:8000/"))
        Try
            Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
            host.Open()
            Using cf As New ChannelFactory(Of IService)(New WebHttpBinding(), "https://localhost:8000")

                cf.Endpoint.Behaviors.Add(New WebHttpBehavior())

                Dim channel As IService = cf.CreateChannel()

                Dim s As String

                Console.WriteLine("Calling EchoWithGet via HTTP GET: ")
                s = channel.EchoWithGet("Hello, world")
                Console.WriteLine("   Output: {0}", s)

                Console.WriteLine("")
                Console.WriteLine("This can also be accomplished by navigating to")
                Console.WriteLine("https://localhost:8000/EchoWithGet?s=Hello, world!")
                Console.WriteLine("in a web browser while this sample is running.")

                Console.WriteLine("")

                Console.WriteLine("Calling EchoWithPost via HTTP POST: ")
                s = channel.EchoWithPost("Hello, world")
                Console.WriteLine("   Output: {0}", s)
                Console.WriteLine("")
            End Using

            Console.WriteLine("Press <ENTER> to terminate")
            Console.ReadLine()

            host.Close()
        Catch cex As CommunicationException
            Console.WriteLine("An exception occurred: {0}", cex.Message)
            host.Abort()
        End Try
    End Sub

End Module
// Service.cs
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;

namespace Microsoft.ServiceModel.Samples.BasicWebProgramming
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        string EchoWithGet(string s);

        [OperationContract]
        [WebInvoke]
        string EchoWithPost(string s);
    }
    public class Service : IService
    {
        public string EchoWithGet(string s)
        {
            return "You said " + s;
        }

        public string EchoWithPost(string s)
        {
            return "You said " + s;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("https://localhost:8000/"));
            try
            {
                ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
                host.Open();
                using (ChannelFactory<IService> cf = new ChannelFactory<IService>(new WebHttpBinding(), "https://localhost:8000"))
                {
                    cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
                    
                    IService channel = cf.CreateChannel();

                    string s;

                    Console.WriteLine("Calling EchoWithGet via HTTP GET: ");
                    s = channel.EchoWithGet("Hello, world");
                    Console.WriteLine("   Output: {0}", s);

                    Console.WriteLine("");
                    Console.WriteLine("This can also be accomplished by navigating to");
                    Console.WriteLine("https://localhost:8000/EchoWithGet?s=Hello, world!");
                    Console.WriteLine("in a web browser while this sample is running.");

                    Console.WriteLine("");

                    Console.WriteLine("Calling EchoWithPost via HTTP POST: ");
                    s = channel.EchoWithPost("Hello, world");
                    Console.WriteLine("   Output: {0}", s);
                    Console.WriteLine("");
                }

                Console.WriteLine("Press <ENTER> to terminate");
                Console.ReadLine();
                
                host.Close();
            }
            catch (CommunicationException cex)
            {
                Console.WriteLine("An exception occurred: {0}", cex.Message);
                host.Abort();
            }
        }
    }
}

Compiling the Code

When compiling Service.cs reference System.ServiceModel.dll and System.ServiceModel.Web.dll.

See Also

Reference

WebHttpBinding
WebGetAttribute
WebInvokeAttribute
WebServiceHost
ChannelFactory
WebHttpBehavior


© 2007 Microsoft Corporation. All rights reserved.
Last Published: 2010-03-21