如何:向 SOAP 和 Web 客户端公开协定
默认情况下,Windows Communication Foundation (WCF) 使终结点只可用于 SOAP 客户端。在如何:创建基本 WCF Web HTTP 服务中,非 SOAP 客户端可以使用终结点。有时可能需要使相同的协定可以同时作为 Web 终结点和 SOAP 终结点使用。本主题演示了如何实现此目的的示例。
定义服务协定
使用通过 ServiceContractAttribute、WebInvokeAttribute 和 WebGetAttribute 特性进行标记的接口来定义服务协定,如下面的代码所示。
<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); }
注意:
默认情况下,WebInvokeAttribute 将 POST 调用映射到操作。不过,可以指定“method=”参数来指定映射到操作的方法。WebGetAttribute 没有“method=”参数并且仅将 GET 调用映射到服务操作。 实现服务协定,如下面的代码所示。
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; } }
承载服务
创建 ServiceHost 对象,如下面的代码所示。
Dim host As New ServiceHost(GetType(Service), New Uri("https://localhost:8000"))
ServiceHost host = new ServiceHost(typeof(Service), new Uri("https://localhost:8000"));
添加一个带有针对 SOAP 终结点的 BasicHttpBinding 的 ServiceEndpoint,如下面的代码所示。
host.AddServiceEndpoint(GetType(IService), New BasicHttpBinding(), "Soap")
host.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), "Soap");
添加一个带有针对非 SOAP 终结点的 WebHttpBinding 的 ServiceEndpoint,并将 WebHttpBehavior 添加到该终结点,如下面的代码所示。
Dim endpoint As ServiceEndpoint endpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "Web") endpoint.Behaviors.Add(New WebHttpBehavior())
ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "Web"); endpoint.Behaviors.Add(new WebHttpBehavior());
在 ServiceHost 实例上调用
Open()
以打开服务主机,如下面的代码所示。host.Open()
host.Open();
在 Internet Explorer 中调用映射到 GET 的服务操作
- 打开 Internet Explorer,键入 https://localhost:8000/Web/EchoWithGet?s=Hello, world!,然后按 Enter。该 URL 包含服务的基址 ("https://localhost:8000/")、终结点的相对地址 ("")、要调用的服务操作 ("EchoWithGet")、一个问号以及其后通过“and”符号 (&) 分隔的命名参数的列表。
使用代码在 Web 终结点上调用服务操作
在
using
块中创建 WebChannelFactory 的实例,如下面的代码所示。Using wcf As New WebChannelFactory(Of IService)(New Uri("https://localhost:8000/Web"))
using (WebChannelFactory<IService> wcf = new WebChannelFactory<IService>(new Uri("https://localhost:8000/Web")))
![]() |
---|
将自动在 using 块末尾处的通道上调用 Close() 。
|
创建通道并调用服务,如下面的代码所示。
Dim channel As IService = wcf.CreateChannel() Dim s As String Console.WriteLine("Calling EchoWithGet by 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/Web/EchoWithGet?s=Hello, world!") Console.WriteLine("in a web browser while this sample is running.") Console.WriteLine("") Console.WriteLine("Calling EchoWithPost by HTTP POST: ") s = channel.EchoWithPost("Hello, world") Console.WriteLine(" Output: {0}", s)
IService channel = wcf.CreateChannel(); string s; Console.WriteLine("Calling EchoWithGet by 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/Web/EchoWithGet?s=Hello, world!"); Console.WriteLine("in a web browser while this sample is running."); Console.WriteLine(""); Console.WriteLine("Calling EchoWithPost by HTTP POST: "); s = channel.EchoWithPost("Hello, world"); Console.WriteLine(" Output: {0}", s);
在 SOAP 终结点上调用服务操作
在
using
块中创建 ChannelFactory 的实例,如下面的代码所示。Using scf As New ChannelFactory(Of IService)(New BasicHttpBinding(), "https://localhost:8000/Soap")
using (ChannelFactory<IService> scf = new ChannelFactory<IService>(new BasicHttpBinding(), "https://localhost:8000/Soap"))
创建通道并调用服务,如下面的代码所示。
Dim channel As IService = scf.CreateChannel() Dim s As String Console.WriteLine("Calling EchoWithGet on SOAP endpoint: ") s = channel.EchoWithGet("Hello, world") Console.WriteLine(" Output: {0}", s) Console.WriteLine("") Console.WriteLine("Calling EchoWithPost on SOAP endpoint: ") s = channel.EchoWithPost("Hello, world") Console.WriteLine(" Output: {0}", s)
IService channel = scf.CreateChannel(); string s; Console.WriteLine("Calling EchoWithGet on SOAP endpoint: "); s = channel.EchoWithGet("Hello, world"); Console.WriteLine(" Output: {0}", s); Console.WriteLine(""); Console.WriteLine("Calling EchoWithPost on SOAP endpoint: "); s = channel.EchoWithPost("Hello, world"); Console.WriteLine(" Output: {0}", s);
关闭服务主机
关闭服务主机,如下面的代码所示。
host.Close()
host.Close();
示例
下面列出了此主题的完整代码。
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 New ServiceHost(GetType(Service), New Uri("https://localhost:8000"))
host.AddServiceEndpoint(GetType(IService), New BasicHttpBinding(), "Soap")
Dim endpoint As ServiceEndpoint
endpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "Web")
endpoint.Behaviors.Add(New WebHttpBehavior())
Try
host.Open()
Using wcf As New WebChannelFactory(Of IService)(New Uri("https://localhost:8000/Web"))
Dim channel As IService = wcf.CreateChannel()
Dim s As String
Console.WriteLine("Calling EchoWithGet by 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/Web/EchoWithGet?s=Hello, world!")
Console.WriteLine("in a web browser while this sample is running.")
Console.WriteLine("")
Console.WriteLine("Calling EchoWithPost by HTTP POST: ")
s = channel.EchoWithPost("Hello, world")
Console.WriteLine(" Output: {0}", s)
Console.WriteLine("")
End Using
Using scf As New ChannelFactory(Of IService)(New BasicHttpBinding(), "https://localhost:8000/Soap")
Dim channel As IService = scf.CreateChannel()
Dim s As String
Console.WriteLine("Calling EchoWithGet on SOAP endpoint: ")
s = channel.EchoWithGet("Hello, world")
Console.WriteLine(" Output: {0}", s)
Console.WriteLine("")
Console.WriteLine("Calling EchoWithPost on SOAP endpoint: ")
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
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)
{
ServiceHost host = new ServiceHost(typeof(Service), new Uri("https://localhost:8000"));
host.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), "Soap");
ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "Web");
endpoint.Behaviors.Add(new WebHttpBehavior());
try
{
host.Open();
using (WebChannelFactory<IService> wcf = new WebChannelFactory<IService>(new Uri("https://localhost:8000/Web")))
{
IService channel = wcf.CreateChannel();
string s;
Console.WriteLine("Calling EchoWithGet by 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/Web/EchoWithGet?s=Hello, world!");
Console.WriteLine("in a web browser while this sample is running.");
Console.WriteLine("");
Console.WriteLine("Calling EchoWithPost by HTTP POST: ");
s = channel.EchoWithPost("Hello, world");
Console.WriteLine(" Output: {0}", s);
Console.WriteLine("");
}
using (ChannelFactory<IService> scf = new ChannelFactory<IService>(new BasicHttpBinding(), "https://localhost:8000/Soap"))
{
IService channel = scf.CreateChannel();
string s;
Console.WriteLine("Calling EchoWithGet on SOAP endpoint: ");
s = channel.EchoWithGet("Hello, world");
Console.WriteLine(" Output: {0}", s);
Console.WriteLine("");
Console.WriteLine("Calling EchoWithPost on SOAP endpoint: ");
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
ChannelFactory
WebHttpBehavior