如何:创建基本 WCF Web HTTP 服务
Windows Communication Foundation (WCF) 允许您创建公开 Web 终结点的服务。Web 终结点通过 XML 或 JSON 发送数据,没有 SOAP 信封。本主题演示如何公开这类终结点。
注意: |
---|
确保 Web 终结点安全的唯一方式是使用传输安全通过 HTTPS 将其公开。使用基于消息的安全性时,通常将安全信息放置在 SOAP 标头中,原因是发送到非 SOAP 终结点的信息不包含 SOAP 信封,没有地方放置安全信息,因而必须依赖于传输安全性。 |
创建 Web 终结点
使用以 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=”参数来指定映射到操作的 HTTP 方法(例如,HEAD、PUT 或 DELETE)。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; } }
承载服务
创建 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/"));
添加一个带有 ServiceEndpoint 的 WebHttpBehavior。
Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
注意: 如果不添加终结点,则 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;
打开服务主机并等待用户按 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 的服务操作
- 打开 Internet Explorer 并键入“https://localhost:8000/EchoWithGet?s=Hello, world!”,然后按 Enter。该 URL 包含服务的基址 ("https://localhost:8000/")、终结点的相对地址 ("")、要调用的服务操作 ("EchoWithGet")、一个问号以及其后通过“and”符号 (&) 分隔的命名参数的列表。
在代码中调用服务操作
在
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"))
将 WebHttpBehavior 添加到 ChannelFactory 调用的终结点。
cf.Endpoint.Behaviors.Add(New WebHttpBehavior())
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)
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);
关闭 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