作法:建立基本 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] 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
注意
根據預設,WebInvokeAttribute 會將 POST 呼叫對應至作業。 但是,您可以指定 "method=" 參數,以指定要對應至作業的 HTTP 方法 (例如,HEAD、PUT 和 DELETE)。 WebGetAttribute 沒有 "method=" 參數,只能將 GET 呼叫對應至服務作業。
實作服務合約。
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
若要裝載服務
建立 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/"))
新增包含 ServiceEndpoint 的 WebHttpBehavior。
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
Dim ep As ServiceEndpoint = host.AddServiceEndpoint(GetType(IService), New WebHttpBinding(), "")
注意
如果您沒有加入端點,WebServiceHost 會自動建立預設端點。 WebServiceHost 也會加入 WebHttpBehavior,並停用 HTTP 說明網頁和 Web 服務描述語言 (WSDL) 的 GET 功能,使中繼資料端點不會干擾預設 HTTP 端點。
如果新增包含 "" 的 URL 非 SOAP 端點,會在嘗試呼叫端點上的作業時導致未預期的行為。 發生原因是因為端點的接聽 URI 與說明頁面 (當您瀏覽至 WCF 服務的基底位址時所顯示的頁面) 的 URI 相同。
您可以執行下列其中一項動作來預防發生這種情況:
- 一律為非 SOAP 端點指定非空白的 URI。
- 關閉說明頁面。 運用下列程式碼即可達到這個目的:
ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>(); sdb.HttpHelpPageEnabled = false;
Dim sdb As ServiceDebugBehavior = host.Description.Behaviors.Find(Of 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%>
若要在瀏覽器中呼叫對應至 GET 的服務作業
- 開啟網頁瀏覽器,輸入 URL "
http://localhost:8000/EchoWithGet?s=Hello, world!
",然後按 Enter。 該 URL 包含服務的基底位址 (http://localhost:8000/
)、端點的相對位址 ("")、要呼叫的服務作業 ("EchoWithGet")、問號,並於後面接續由連字號 (&) 分隔的具名參數清單。
若要透過程式碼呼叫服務作業
在 ChannelFactory<TChannel> 區塊中建立
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")
將 WebHttpBehavior 加入至 ChannelFactory<TChannel> 所呼叫的端點。
cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
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);
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)
關閉 WebServiceHost。
host.Close();
host.Close()
範例
以下是這個範例的完整程式碼清單。
// 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
編譯程式碼
編譯 Service.cs 時,請參考 System.ServiceModel.dll 和 System.ServiceModel.Web.dll。