如何:创建基本 WCF Web HTTP 服务

Windows Communication Foundation (WCF) 允许您创建公开 Web 终结点的服务。Web 终结点通过 XML 或 JSON 发送数据,没有 SOAP 信封。本主题演示如何公开这类终结点。

Bb412178.note(zh-cn,VS.100).gif注意:
确保 Web 终结点安全的唯一方式是使用传输安全通过 HTTPS 将其公开。使用基于消息的安全性时,通常将安全信息放置在 SOAP 标头中,原因是发送到非 SOAP 终结点的信息不包含 SOAP 信封,没有地方放置安全信息,因而必须依赖于传输安全性。

创建 Web 终结点

  1. 使用以 ServiceContractAttribute, WebInvokeAttributeWebGetAttribute 特性标记的接口来定义服务协定。

    <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);
    }
    
    Bb412178.note(zh-cn,VS.100).gif注意:
    默认情况下,WebInvokeAttribute 将 POST 调用映射到操作。不过,可以指定“method=”参数来指定映射到操作的 HTTP 方法(例如,HEAD、PUT 或 DELETE)。WebGetAttribute 没有“method=”参数并且仅将 GET 调用映射到服务操作。

  2. 实现服务协定。

    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;
        }
    }
    

承载服务

  1. 创建 WebServiceHost 对象。

    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. 添加一个带有 ServiceEndpointWebHttpBehavior

    Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
    
    ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
    
    Bb412178.note(zh-cn,VS.100).gif注意:
    如果不添加终结点,则 WebServiceHost 自动创建默认终结点。WebServiceHost 还添加 WebHttpBehavior 并禁用 HTTP 帮助页和 Web 服务描述语言 (WSDL) GET 功能,因此元数据终结点不会影响默认的 HTTP 终结点。

    当尝试调用终结点上的操作时,添加 URL 为 "" 的非 SOAP 终结点会导致意外行为。其原因是终结点的侦听 URI 与帮助页(在浏览到 WCF 服务的基址时显示的页)的 URI 相同。

    要防止此类情况发生,可以执行下列操作之一:

    • 总是为非 SOAP 终结点指定非空白 URI。

    • 关闭帮助页。这可以通过以下代码来实现。

    Dim sdb As ServiceDebugBehavior = host.Description.Behaviors.Find(Of ServiceDebugBehavior)()
    sdb.HttpHelpPageEnabled = False
    
    ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
    sdb.HttpHelpPageEnabled = false;
    
  3. 打开服务主机并等待用户按 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();
    

    此示例演示如何使用控制台应用程序来承载 Web 样式服务。还可以在 IIS 内承载这类服务。为此,在 .svc 文件中指定 WebServiceHostFactory 类,如以下代码所示。

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

在 Internet Explorer 中调用映射到 GET 的服务操作

  1. 打开 Internet Explorer 并键入“https://localhost:8000/EchoWithGet?s=Hello, world!”,然后按 Enter。该 URL 包含服务的基址 ("https://localhost:8000/")、终结点的相对地址 ("")、要调用的服务操作 ("EchoWithGet")、一个问号以及其后通过“and”符号 (&) 分隔的命名参数的列表。

在代码中调用服务操作

  1. using 块中创建 WebChannelFactory 的实例。

    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. WebHttpBehavior 添加到 ChannelFactory 调用的终结点。

    cf.Endpoint.Behaviors.Add(New WebHttpBehavior())
    
    cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
    
  3. 创建通道并调用服务。

    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. 关闭 WebServiceHost

    host.Close()
    
    host.Close();
    

示例

下面列出了此示例的完整代码清单。

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

编译代码

编译 Service.cs 时,请引用 System.ServiceModel.dll 和 System.ServiceModel.Web.dll。

另请参见

参考

WebHttpBinding
WebGetAttribute
WebInvokeAttribute
WebServiceHost
WebChannelFactory
WebHttpBehavior

其他资源

WCF Web HTTP 编程模型