Como: criar um serviço Web HTTP WCF básico

O WCF (Windows Communication Foundation) permite que você crie um serviço que expõe um ponto de extremidade da Web. Os pontos de extremidade Web enviam dados por XML ou JSON; não há envelope SOAP. Este tópico demonstra como expor um ponto de extremidade desse tipo.

Observação

A única maneira de proteger um ponto de extremidade Web é exibi-lo via HTTPS, usando segurança de transporte. Quando a segurança baseada em mensagem é usada, as informações de segurança são geralmente colocadas em cabeçalhos SOAP e, como as mensagens enviadas a pontos de extremidade não SOAP não contêm envelopes SOAP, não há lugar para colocar informações de segurança. Assim, é necessário confiar na segurança de transporte.

Para criar um ponto de extremidade Web

  1. Defina um contrato de serviço usando uma interface marcada com os atributos ServiceContractAttribute, WebInvokeAttribute e WebGetAttribute.

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        string EchoWithGet(string s);
    
        [OperationContract]
        [WebInvoke]
        string EchoWithPost(string s);
    }
    
    <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
    
    

    Observação

    Por padrão, WebInvokeAttribute mapeia chamadas POST para a operação. É possível, entretanto, especificar o método HTTP (por exemplo, HEAD, PUT ou DELETE) para mapear a operação especificando um parâmetro "method=". WebGetAttribute não tem um parâmetro "method=" e só mapeia chamadas GET para a operação de serviço.

  2. Implemente o contrato de serviço.

    public class Service : IService
    {
        public string EchoWithGet(string s)
        {
            return "You said " + s;
        }
    
        public string EchoWithPost(string s)
        {
            return "You said " + s;
        }
    }
    
    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
    

Para hospedar o serviço

  1. Crie um objeto WebServiceHost.

    WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("http://localhost:8000/"));
    
    Dim host As WebServiceHost = New WebServiceHost(GetType(Service), New Uri("http://localhost:8000/"))
    
  2. Adicione uma classe ServiceEndpoint com WebHttpBehavior.

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

    Observação

    Se você não adicionar um ponto de extremidade, WebServiceHost criará automaticamente um ponto de extremidade padrão. WebServiceHost também adiciona WebHttpBehavior e desabilita a página da ajuda HTTP e a funcionalidade GET da linguagem WSDL para que o ponto de extremidade de metadados não interfira no ponto de extremidade HTTP padrão.

    A adição de um ponto de extremidade não SOAP com uma URL de "" gera um comportamento inesperado quando há uma tentativa de chamar uma operação no ponto de extremidade. Isso decorre porque o URI de escuta do ponto de extremidade é igual ao URI da página de ajuda (a página que é exibida quando você navega até o endereço básico de um serviço WCF).

    Você pode executar uma das seguintes ações para evitar que isso ocorra:

    • Especifique sempre um URI que não esteja em branco para um ponto de extremidade não SOAP.
    • Desative a página de ajuda. Isso pode ser feito com o código a seguir:
    ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
    sdb.HttpHelpPageEnabled = false;
    
    Dim sdb As ServiceDebugBehavior = host.Description.Behaviors.Find(Of ServiceDebugBehavior)()
    sdb.HttpHelpPageEnabled = False
    
  3. Abra o host do serviço e aguarde até que o usuário pressione 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()
    

    Este exemplo demonstra como hospedar um serviço estilo Web com um aplicativo de console. Também é possível hospedar esse tipo de serviço no IIS. Para fazer isso, especifique a classe WebServiceHostFactory em um arquivo .svc como demonstra o código a seguir.

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

Para chamar operações de serviço mapeadas para GET em um navegador

  1. Abra um navegador da Web, insira a URL "http://localhost:8000/EchoWithGet?s=Hello, world!" e pressione Enter. A URL contém o endereço básico do serviço (http://localhost:8000/), o endereço relativo do ponto de extremidade (""), a operação de serviço a ser chamada ("EchoWithGet") e um ponto de interrogação seguido por uma lista de parâmetros nomeados separados por um E comercial (&).

Para chamar operações de serviço no código

  1. Crie uma instância de ChannelFactory<TChannel> em um bloco using.

    using (ChannelFactory<IService> cf = new ChannelFactory<IService>(new WebHttpBinding(), "http://localhost:8000"))
    
    Using cf As New ChannelFactory(Of IService)(New WebHttpBinding(), "http://localhost:8000")
    
  2. Adicione WebHttpBehavior ao ponto de extremidade que ChannelFactory<TChannel> chama.

    cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
    
    cf.Endpoint.Behaviors.Add(New WebHttpBehavior())
    
  3. Crie o canal e chame o serviço.

    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("http://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);
    
    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("http://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. Feche a classe WebServiceHost.

    host.Close();
    
    host.Close()
    

Exemplo

A seguir está a listagem completa de códigos deste exemplo.

// 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("http://localhost:8000/"));
            try
            {
                ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
                host.Open();
                using (ChannelFactory<IService> cf = new ChannelFactory<IService>(new WebHttpBinding(), "http://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("http://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();
            }
        }
    }
}

'Service.cs
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("http://localhost:8000/"))
        Try
            Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
            host.Open()
            Using cf As New ChannelFactory(Of IService)(New WebHttpBinding(), "http://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("http://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

Compilando o código

Ao compilar Service.cs, faça referência à System.ServiceModel.dll e à System.ServiceModel.Web.dll.

Confira também