共用方式為


根據開發比較 ASP.NET Web 服務與 WCF

Windows Communication Foundation (WCF) 具有 ASP.NET 相容性模式選項,可讓 WCF 應用程式進行程式設計及設定,例如 ASP.NET Web 服務,並模擬其行為。 下列各節會根據使用這兩種技術開發應用程式所需的專案,比較 ASP.NET Web 服務和 WCF。

數據表示法

使用 ASP.NET 的 Web 服務開發,通常會從定義服務要使用的任何複雜數據類型開始。 ASP.NET 依賴 XmlSerializer 將 .NET Framework 型別所代表的數據轉譯成 XML,以便傳輸至服務或從服務傳輸,並將接收的數據轉譯為 XML 到 .NET Framework 物件。 定義 ASP.NET 服務要使用的複雜數據類型,需要定義可以串行化至 XML 的 .NET Framework 類別 XmlSerializer 。 您可以使用命令列 XML 架構/資料類型支援公用程式,手動撰寫這類類別,或從 XML 架構中型別的定義產生,xsd.exe。

以下是定義可串行化至 XML 的 .NET Framework 類別 XmlSerializer 時所要知道的關鍵問題清單:

  • 只有 .NET Framework 物件的公用字段和屬性會轉譯成 XML。

  • 只有當集合類別實作 IEnumerableICollection 介面時,其實例才能序列化為 XML。

  • 實作 IDictionary 介面的類別,例如 Hashtable,無法串行化為 XML。

  • 命名空間中的 System.Xml.Serialization 許多屬性類型可以新增至 .NET Framework 類別及其成員,以控制類別實例在 XML 中的表示方式。

WCF 應用程式開發通常也會從複雜型別的定義開始。 WCF 可以使用與 ASP.NET Web 服務相同的 .NET Framework 類型。

WCFDataContractAttributeDataMemberAttribute 可以新增至 .NET Framework 類型,以指出型別的實例要串行化為 XML,以及要串行化類型的特定字段或屬性,如下列範例程式代碼所示。

//Example One:
[DataContract]
public class LineItem
{
    [DataMember]
    public string ItemNumber;
    [DataMember]
    public decimal Quantity;
    [DataMember]
    public decimal UnitPrice;
}

//Example Two:
public class LineItem
{
    [DataMember]
    private string itemNumber;
    [DataMember]
    private decimal quantity;
    [DataMember]
    private decimal unitPrice;

    public string ItemNumber
    {
      get
      {
          return this.itemNumber;
      }

      set
      {
          this.itemNumber = value;
      }
    }

    public decimal Quantity
    {
        get
        {
            return this.quantity;
        }

        set
        {
            this.quantity = value;
        }
    }

    public decimal UnitPrice
    {
      get
      {
          return this.unitPrice;
      }

      set
      {
          this.unitPrice = value;
      }
    }
}

//Example Three:
public class LineItem
{
     private string itemNumber;
     private decimal quantity;
     private decimal unitPrice;

     [DataMember]
     public string ItemNumber
     {
       get
       {
          return this.itemNumber;
       }

       set
       {
           this.itemNumber = value;
       }
     }

     [DataMember]
     public decimal Quantity
     {
          get
          {
              return this.quantity;
          }

          set
          {
             this.quantity = value;
          }
     }

     [DataMember]
     public decimal UnitPrice
     {
          get
          {
              return this.unitPrice;
          }

          set
          {
              this.unitPrice = value;
          }
     }
}

DataContractAttribute表示要串行化類型欄位或屬性的零個或多個,而 DataMemberAttribute 表示要串行化特定欄位或屬性。 DataContractAttribute可以套用至類別或結構。 DataMemberAttribute可以套用至欄位或屬性,而套用屬性的欄位和屬性可以是公用或私用的。 已 DataContractAttribute 套用至這些類型的實例稱為WCF 中的數據合約。 它們透過 DataContractSerializer 被序列化為 XML。

以下是使用 DataContractSerializer 和使用 XmlSerializer 以及 System.Xml.Serialization 命名空間的各種屬性之間的重要差異清單。

  • XmlSerializerSystem.Xml.Serialization 命名空間的屬性是設計成可讓您將 .NET Framework 類型映射至 XML 架構中所定義的任何有效類型,因此它們提供非常精確地控制 XML 中類型表示方式。 DataContractSerializerDataContractAttributeDataMemberAttribute 在 XML 中表示型別的方式上提供的控制非常有限。 您只能指定命名空間和名稱,用來代表 XML 中的型別及其欄位或屬性,以及欄位和屬性出現在 XML 中的序列:

    [DataContract(
    Namespace="urn:Contoso:2006:January:29",
    Name="LineItem")]
    public class LineItem
    {
          [DataMember(Name="ItemNumber",IsRequired=true,Order=0)]
          public string itemNumber;
          [DataMember(Name="Quantity",IsRequired=false,Order = 1)]
          public decimal quantity;
          [DataMember(Name="Price",IsRequired=false,Order = 2)]
          public decimal unitPrice;
    }
    

    用來表示 .NET 型別之 XML 結構的其他一切由 決定 DataContractSerializer

  • 藉由不允許對型別在 XML 中的表示方式進行太多控制,串行化程式處理就會變得高度可預測 DataContractSerializer,並因此更容易優化。 設計 DataContractSerializer 的實際優點是更好的效能,大約百分之十的效能更好。

  • XmlSerializer 搭配使用的屬性不會指出型別的哪些欄位或屬性序列化為 XML,而 DataMemberAttribute 搭配使用的 DataContractSerializer 則明確顯示哪些欄位或屬性被序列化。 因此,數據合約是應用程式要傳送和接收之數據結構的明確合約。

  • XmlSerializer只能將 .NET 物件的公用成員轉譯成 XML,不論這些成員的存取修飾詞為何,DataContractSerializer都可以將對象的成員轉譯成 XML。

  • 由於能夠將型別的非公用成員串行化為 XML,因此 DataContractSerializer 對它可以串行化成 XML 的各種 .NET 類型有較少的限制。 特別是,它可以轉譯成類似 Hashtable 實作 介面的 IDictionary XML 類型。 DataContractSerializer更可能能夠將任何預先存在的 .NET 型別實例串行化為 XML,而不需要修改型別的定義或為其開發包裝函式。

  • 能夠存取型別非公開成員的另一個後果是,DataContractSerializer 需要擁有完全信任,而 XmlSerializer 則不需要。 「完全信任」程式代碼訪問許可權可讓您完整存取計算機上可使用程式代碼執行時所使用的認證存取的所有資源。 此選項應該小心使用,因為完全信任的程式代碼會存取您計算機上的所有資源。

  • DataContractSerializer 包含一些版本控制的支援。

    • DataMemberAttribute具有IsRequired屬性,可以為在舊版中未曾存在的新版本數據合約中新增的成員指派為 false 值,從而使具有較新版本合約的應用程式能夠處理舊版。

    • 透過將資料合約實作 IExtensibleDataObject 介面,可以允許 DataContractSerializer 將較新版資料合約中定義的成員,透過具有舊版合約的應用程式傳遞。

儘管存在各種差異,但只要明確定義 XML 的命名空間,那麼 XmlSerializer 所串行化的型別的 XML 就在語意上與 DataContractSerializer 所串行化的型別的 XML 完全相同。 下列類別具有與這兩個串行化程式搭配使用的屬性,由 XmlSerializerDataContractAttribute轉譯成語意完全相同的 XML:

[Serializable]
[XmlRoot(Namespace="urn:Contoso:2006:January:29")]
[DataContract(Namespace="urn:Contoso:2006:January:29")]
public class LineItem
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

Windows 軟體開發工具套件 (SDK) 包含稱為 ServiceModel 元數據公用程式工具 (Svcutil.exe) 的命令行工具。 如同與 ASP.NET Web 服務搭配使用的 xsd.exe 工具,Svcutil.exe 可以從 XML 架構產生 .NET 數據類型的定義。 如果 DataContractSerializer 可以使用 XML 架構所定義的格式發出 XML,則型別為數據合約;否則,這些類型是用於使用 XmlSerializer串行化。 Svcutil.exe 也可以使用參數 dataContractOnly ,從數據合約產生 XML 架構。

備註

雖然 ASP.NET Web 服務使用 XmlSerializer,而 WCF ASP.NET 相容性模式可讓 WCF 服務模擬 ASP.NET Web 服務的行為,但 ASP.NET 相容性選項不會限制使用 XmlSerializer。 仍然可以在 ASP.NET 相容性模式中運行的服務中使用 DataContractSerializer

服務開發

若要使用 ASP.NET 開發服務,通常將 WebService 屬性新增至類別,並將 WebMethodAttribute 新增至該類別中要作為服務作業的任何方法。

[WebService]
public class Service : T:System.Web.Services.WebService
{
    [WebMethod]
    public string Echo(string input)
    {
       return input;
    }
}

ASP.NET 2.0 引入了將WebServiceWebMethodAttribute這類屬性新增至介面而非類別的選項,以及撰寫類別以實作該介面。

[WebService]
public interface IEcho
{
    [WebMethod]
    string Echo(string input);
}

public class Service : IEcho
{

   public string Echo(string input)
   {
        return input;
    }
}

使用此選項是慣用的,因為具有 WebService 屬性的 介面會構成服務所執行之作業的合約,這些作業可以重複使用於可能以不同方式實作該相同合約的各種類別。

WCF 服務是藉由定義一或多個 WCF 端點來提供。 端點是由位址、系結和服務合約所定義。 位址會定義服務所在的位置。 系結會指定如何與服務通訊。 服務合約會定義服務可執行的作業。

通常首先會透過將 ServiceContractAttributeOperationContractAttribute 新增至介面來定義服務合約。

[ServiceContract]
public interface IEcho
{
     [OperationContract]
     string Echo(string input);
}

ServiceContractAttribute 指定該介面定義了一個 WCF 服務合約,而 OperationContractAttribute 則指出介面的方法中,哪些方法(若有)定義了該服務合約的作業。

定義服務合約之後,它會在類別中實作,方法是讓 類別實作服務合約所定義的介面:

public class Service : IEcho
{
    public string Echo(string input)
    {
       return input;
    }
}

實作服務合約的類別稱為 WCF 中的服務類型。

下一個步驟是將位址和系結與服務類型產生關聯。 這通常是在組態檔中完成,方法是直接編輯檔案,或使用WCF提供的組態編輯器。 以下是組態檔的範例。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
     <system.serviceModel>
      <services>
      <service name="Service ">
       <endpoint
        address="EchoService"
        binding="basicHttpBinding"
        contract="IEchoService "/>
      </service>
      </services>
     </system.serviceModel>
</configuration>

系結會指定與應用程式通訊的通訊協定集。 下表列出系統提供的系結,這些系結代表一般選項。

名稱 目標
BasicHttpBinding (基本HTTP綁定) 與支援 WS-BasicProfile 1.1 和基本安全性配置檔 1.0 的 Web 服務和用戶端的互作性。
WSHttpBinding 與透過 HTTP 支援 WS-* 通訊協定的 Web 服務和用戶端的互作性。
WSDualHttpBinding 雙工 HTTP 通訊中,初始訊息的接收者不會直接回覆初始發送者,而是可能根據 WS-* 協議規範,使用 HTTP 在一段時間內傳輸多個回應。
WSFederationBinding HTTP 通訊,根據明確識別認證提供者所發出的認證,可以控制服務資源的存取權。
NetTcpBinding 在網路中實現 WCF 軟體實體之間安全、可靠、高效能的通訊。
NetNamedPipeBinding 在同一部計算機上,WCF 軟體實體之間的安全、可靠、高效能通訊。
NetMsmqBinding 使用 MSMQ 在 WCF 軟體實體之間進行通訊。
MsmqIntegrationBinding(MSMQ整合綁定) 使用 MSMQ 作為方法來促成 WCF 軟體實體與另一個軟體實體之間的通訊。
NetPeerTcpBinding 使用 Windows 對等網路在 WCF 軟體實體之間進行通訊。

系統提供的系結 BasicHttpBinding會納入 ASP.NET Web 服務所支援的通訊協定集。

WCF 應用程式的自定義系結很容易定義為 WCF 用來實作個別通訊協定之綁定項類別的集合。 新的綁定項可以寫入來表示其他通訊協定。

您可以使用稱為行為之類別系列的屬性來調整服務類型的內部行為。 在這裡,類別 ServiceBehaviorAttribute 是用來指定服務類型為多線程。

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class DerivativesCalculatorServiceType: IDerivativesCalculator

某些行為,例如 ServiceBehaviorAttribute,是屬性。 其他,系統管理員想要設定的屬性,可以在應用程式的設定中修改。

在程式設計服務類型中,經常使用 OperationContext 類別。 其靜態 Current 屬性可讓您存取執行作業之內容的相關信息。 OperationContextHttpContextContextUtil 類別類似。

主機托管

ASP.NET Web 服務會編譯成類別庫程式集。 提供稱為服務檔案的檔案,其擴展名為 .asmx,並包含 @ WebService 指示詞,識別類別,其中包含服務的程序代碼及其所在元件。

<%@ WebService Language="C#" Class="Service,ServiceAssembly" %>

服務檔案會複製到 Internet Information Services (IIS) 中 ASP.NET 應用程式根目錄,而元件會複製到該應用程式根目錄的 \bin 子目錄中。 接著,應用程式可以使用應用程式根目錄中服務檔案的統一資源定位器(URL)來存取。

WCF 服務可輕易裝載於 IIS 5.1 或 6.0、作為 IIS 7.0 一部分提供的 Windows 進程啟用服務(WAS),以及任何 .NET 應用程式中。 若要在 IIS 5.1 或 6.0 中裝載服務,服務必須使用 HTTP 作為通訊傳輸通訊協定。

若要在 IIS 5.1、6.0 或 WAS 內裝載服務,請使用下列步驟:

  1. 將服務類型編譯為類別庫組件。

  2. 建立具有 .svc 擴展名並包含 @ ServiceHost 指令的服務檔案,以識別服務類型。

    <%@ServiceHost language="c#" Service="MyService" %>

  3. 將服務檔案複製到虛擬目錄,並將元件複製到該虛擬目錄的 \bin 子目錄。

  4. 將群組態檔複製到虛擬目錄,並將它命名為 Web.config。

然後,應用程式可以使用應用程式根目錄中服務檔案的URL來存取。

若要在 .NET 應用程式內裝載 WCF 服務,請將服務類型編譯為應用程式所參考的類別庫元件,並使用 類別將應用程式程式設計為裝載服務 ServiceHost 。 以下是必要的基本程式設計範例:

string httpBaseAddress = "http://www.contoso.com:8000/";
string tcpBaseAddress = "net.tcp://www.contoso.com:8080/";

Uri httpBaseAddressUri = new Uri(httpBaseAddress);
Uri tcpBaseAddressUri = new Uri(tcpBaseAddress);

Uri[] baseAddresses = new Uri[] {
 httpBaseAddressUri,
 tcpBaseAddressUri};

using(ServiceHost host = new ServiceHost(
typeof(Service), //"Service" is the name of the service type baseAddresses))
{
     host.Open();

     […] //Wait to receive messages
     host.Close();
}

這個範例示範如何在 建構 中指定一或多個傳輸通訊協議的 ServiceHost位址。 這些地址稱為基位址。

為 WCF 服務的任何端點提供的位址是相對於端點主機之基地址的位址。 主機可以針對每個通訊傳輸通訊協定有一個基位址。 在上述組態檔中的範例組態中, BasicHttpBinding 針對端點選取的 會使用 HTTP 作為傳輸通訊協定,因此端點 EchoService的位址會相對於主機的 HTTP 基位址。 在上述範例中的主機案例中,HTTP 基位址為 http://www.contoso.com:8000/。 對於裝載於 IIS 或 WAS 的服務,基地址是服務服務檔案的 URL。

只有裝載於 IIS 或 WAS 的服務,且以 HTTP 設定為傳輸通訊協定,才能使用 WCF ASP.NET 相容性模式選項。 開啟該選項需要下列步驟。

  1. 程式設計人員必須將 屬性新增 AspNetCompatibilityRequirementsAttribute 至服務類型,並指定允許或需要 ASP.NET 相容性模式。

    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(
          RequirementsMode=AspNetCompatibilityRequirementsMode.Require)]
    public class DerivativesCalculatorServiceType: IDerivativesCalculator
    
  2. 系統管理員必須將應用程式設定為使用 ASP.NET 相容性模式。

    <configuration>
         <system.serviceModel>
          <services>
          […]
          </services>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        </system.serviceModel>
    </configuration>
    

    WCF 應用程式也可以設定為使用 .asmx 作為其服務檔案的擴展名,而不是 .svc。

    <system.web>
         <compilation>
          <compilation debug="true">
          <buildProviders>
           <remove extension=".asmx"/>
           <add extension=".asmx"
            type="System.ServiceModel.ServiceBuildProvider,
            System.ServiceModel,
            Version=3.0.0.0,
            Culture=neutral,
            PublicKeyToken=b77a5c561934e089" />
          </buildProviders>
          </compilation>
         </compilation>
    </system.web>
    

    此選項可讓您在將服務修改為使用 WCF 時,無需修改已設定為使用 .asmx 服務檔 URL 的用戶端。

客戶端開發

ASP.NET Web 服務的用戶端是使用命令行工具產生,WSDL.exe,提供 .asmx 檔案的 URL 做為輸入。 WCF 所提供的對應工具是 ServiceModel 元數據公用程式工具(Svcutil.exe)。 它會產生程式代碼模組,其中包含服務合約的定義和 WCF 用戶端類別的定義。 它也會產生具有服務地址和系結的組態檔。

在對遠端服務的用戶端進行程序設計時,通常建議根據異步模式進行程序設計。 WSDL.exe 工具所產生的程式代碼預設一律會同時提供同步和異步模式。 ServiceModel 元數據公用程式工具 (Svcutil.exe) 所產生的程式代碼可以提供任一模式。 它預設會提供同步模式。 如果此工具是以 /async 參數執行,那麼生成的程式碼會支援異步模式。

不能保證預設情況下,ASP.NET WSDL.exe 工具所產生的 WCF 用戶端類別名稱會與 Svcutil.exe 工具所產生的相符。 特別是,類別的屬性名稱必須使用 XmlSerializer 進行串行化。依預設,這些名稱在使用 Svcutil.exe 工具生成的程式代碼中會自動添加後綴 Property,而 WSDL.exe 工具則不會如此。

訊息表示法

您可以自訂 ASP.NET Web 服務所傳送和接收之 SOAP 訊息的標頭。 類別衍生自 SoapHeader 以定義標頭的結構,然後使用 SoapHeaderAttribute 來指出標頭是否存在。

public class SomeProtocol : SoapHeader
{
     public long CurrentValue;
     public long Total;
}

[WebService]
public interface IEcho
{
     SomeProtocol ProtocolHeader
     {
      get;
     set;
     }

     [WebMethod]
     [SoapHeader("ProtocolHeader")]
     string PlaceOrders(PurchaseOrderType order);
}

public class Service: WebService, IEcho
{
     private SomeProtocol protocolHeader;

     public SomeProtocol ProtocolHeader
     {
         get
         {
              return this.protocolHeader;
         }

         set
         {
              this.protocolHeader = value;
         }
     }

     string PlaceOrders(PurchaseOrderType order)
     {
         long currentValue = this.protocolHeader.CurrentValue;
     }
}

WCF 提供 屬性、 MessageContractAttributeMessageHeaderAttributeMessageBodyMemberAttribute ,以描述服務所傳送和接收的 SOAP 訊息結構。

[DataContract]
public class SomeProtocol
{
     [DataMember]
     public long CurrentValue;
     [DataMember]
     public long Total;
}

[DataContract]
public class Item
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

[MessageContract]
public class ItemMessage
{
     [MessageHeader]
     public SomeProtocol ProtocolHeader;
     [MessageBody]
     public Item Content;
}

[ServiceContract]
public interface IItemService
{
     [OperationContract]
     public void DeliverItem(ItemMessage itemMessage);
}

此語法會產生訊息結構的明確表示法,而訊息的結構則由 ASP.NET Web 服務的程式代碼所隱含。 此外,在 ASP.NET 語法中,訊息標頭會以服務的屬性表示,例如 ProtocolHeader 上一個範例中的屬性,而在WCF語法中,訊息標頭會更準確地表示為訊息的屬性。 此外,WCF 允許將訊息標頭新增至端點的組態。

<service name="Service ">
     <endpoint
      address="EchoService"
      binding="basicHttpBinding"
      contract="IEchoService ">
      <headers>
      <dsig:X509Certificate
       xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
       ...
      </dsig:X509Certificate>
      </headers>
     </endpoint>
</service>

此選項可讓您避免對客戶端或服務程式代碼中基礎結構通訊協定標頭的任何參考:標頭會因為端點的設定方式而新增至訊息。

服務描述

針對 ASP.NET Web 服務的 .asmx 檔案發出 HTTP GET 要求,並加上查詢 WSDL,ASP.NET 會產生 WSDL 來描述該服務。 它會傳回要求的回應,該回應為 WSDL。

ASP.NET 2.0 可讓您驗證服務是否符合 Web Services-Interoperability 組織的基本設定檔 1.1 (WS-I),並將服務符合其 WSDL 規範的宣告插入。 這是使用 ConformsTo 屬性的 EmitConformanceClaimsWebServiceBindingAttribute 參數來完成的。

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(
     ConformsTo = WsiProfiles.BasicProfile1_1,
     EmitConformanceClaims=true)]
public interface IEcho

您可以自訂 ASP.NET 為服務產生的 WSDL。 自訂項目是通過建立 ServiceDescriptionFormatExtension 的衍生類別,將項目加入 WSDL。

針對託管於 IIS 5.1、6.0 或 WAS 之 HTTP 端點的 WCF 服務的 .svc 檔案,在查詢 WSDL 時發出 HTTP GET 請求,會導致 WCF 回應並以 WSDL 描述該服務。 如果 HTTPGetEnabled 設定為 true,向 .NET 應用程式內裝載之服務的 HTTP 基地址發出查詢 WSDL 的 HTTP GET 要求,效果會相同。

不過,WCF 也會使用 WSDL 產生的 WSDL 回應 WS-MetadataExchange 要求,以描述服務。 ASP.NET Web 服務沒有 WS-MetadataExchange 要求的內建支援。

WCF 產生的 WSDL 可以廣泛自定義。 類別 ServiceMetadataBehavior 提供自定義 WSDL 的一些設施。 WCF 也可以設定為不產生 WSDL,而是在指定的 URL 使用靜態 WSDL 檔案。

<behaviors>
     <behavior name="DescriptionBehavior">
     <metadataPublishing
      enableMetadataExchange="true"
      enableGetWsdl="true"
      enableHelpPage="true"
      metadataLocation=
      "http://localhost/DerivativesCalculatorService/Service.WSDL"/>
     </behavior>
</behaviors>

例外狀況處理

在 ASP.NET Web 服務中,未處理的例外狀況會以 SOAP 錯誤的形式傳回給用戶端。 您也可以明確擲回該類別的 SoapException 實例,並更能控制傳送至用戶端的 SOAP 錯誤內容。

在 WCF 服務中,未處理的例外狀況不會以 SOAP 錯誤的形式傳回給用戶端,以避免不小心透過例外狀況公開敏感性資訊。 提供組態設定,以將未處理的例外狀況傳回給用戶端,以便進行偵錯。

若要將 SOAP 錯誤傳回用戶端,您可以使用數據合約類型作為泛型型別來擲回FaultException<TDetail>的實例。 您也可以將屬性新增 FaultContractAttribute 至作業,以指定作業可能產生的錯誤。

[DataContract]
public class MathFault
{
     [DataMember]
     public string operation;
     [DataMember]
     public string problemType;
}

[ServiceContract]
public interface ICalculator
{
     [OperationContract]
     [FaultContract(typeof(MathFault))]
     int Divide(int n1, int n2);
}

這麼做會導致在服務的 WSDL 中公告可能的錯誤,讓用戶端程式設計人員預期作業可能導致哪些錯誤,並撰寫適當的 catch 語句。

try
{
     result = client.Divide(value1, value2);
}
catch (FaultException<MathFault> e)
{
 Console.WriteLine("FaultException<MathFault>: Math fault while doing "
  + e.Detail.operation
  + ". Problem: "
  + e.Detail.problemType);
}

狀態管理

用來實作 ASP.NET Web 服務的類別可能衍生自 WebService

public class Service : WebService, IEcho
{

 public string Echo(string input)
 {
  return input;
 }
}

在此情況下,類別可以程序設計成使用 WebService 基類的Context屬性來存取 HttpContext 物件。 HttpContext物件可用來更新和擷取應用程式狀態資訊,方法是使用其Application屬性,並使用其 Session 屬性來更新和擷取工作階段狀態資訊。

ASP.NET 提供高度控制,通過使用 HttpContext 的 Session 屬性來存取的會話狀態資訊實際上被儲存的位置。 它可以儲存在 Cookie、資料庫、目前伺服器的記憶體中,或儲存在指定伺服器的記憶體中。 選擇是在服務的組態檔中做出。

WCF 提供狀態管理的可延伸物件。 可延伸物件是實作 IExtensibleObject<T> 的物件。 最重要的可延伸物件是 ServiceHostBaseInstanceContextServiceHostBase 可讓您維護相同主機上所有服務類型的所有實例都可以存取的狀態,同時 InstanceContext 可讓您維護可在相同服務類型實例內執行的任何程式代碼存取的狀態。

在這裡,服務類型 TradingSystem具有 ServiceBehaviorAttribute ,指定來自相同 WCF 用戶端實例的所有呼叫都會路由傳送至服務類型的相同實例。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class TradingSystem: ITradingService

類別 DealData會定義任何在相同服務類型實例中執行的程式代碼都可以存取的狀態。

internal class DealData: IExtension<InstanceContext>
{
 public string DealIdentifier = null;
 public Trade[] Trades = null;
}

在實作服務合約其中一項作業的服務型別程序代碼中, DealData 狀態物件會新增至服務類型目前實例的狀態。

string ITradingService.BeginDeal()
{
 string dealIdentifier = Guid.NewGuid().ToString();
 DealData state = new DealData(dealIdentifier);
 OperationContext.Current.InstanceContext.Extensions.Add(state);
 return dealIdentifier;
}

然後,程式代碼可以擷取和修改該狀態物件,以實作另一個服務合約的作業。

void ITradingService.AddTrade(Trade trade)
{
 DealData dealData =  OperationContext.Current.InstanceContext.Extensions.Find<DealData>();
 dealData.AddTrade(trade);
}

雖然 ASP.NET 提供類別中 HttpContext 狀態資訊實際儲存位置的控制,但 WCF 至少在其初始版本中,不會控制可延伸物件儲存的位置。 這構成了為 WCF 服務選取 ASP.NET 相容性模式的最佳原因。 如果可設定的狀態管理是至關重要的,那麼選擇使用 ASP.NET 相容模式可以讓您像在 ASP.NET 中一樣使用 HttpContext 類別的功能,也可以讓您配置使用 HttpContext 類別管理的狀態資訊的儲存位置。

安全

保護 ASP.NET Web 服務的選項是保護任何 IIS 應用程式的選項。 因為 WCF 應用程式不僅可以裝載在 IIS 內,而且裝載在任何 .NET 可執行檔內,因此保護 WCF 應用程式的選項必須與 IIS 的功能無關。 不過,ASP.NET Web 服務所提供的設施也適用於以 ASP.NET 相容性模式執行的 WCF 服務。

安全性:驗證

IIS 提供用來控制應用程式存取的功能,您可以選取匿名存取或各種驗證模式:Windows 驗證、摘要式驗證、基本身份驗證和 .NET Passport 驗證。 Windows 驗證選項可用來控制 ASP.NET 網頁服務的存取。 不過,當 WCF 應用程式裝載於 IIS 內時,IIS 必須設定為允許匿名存取應用程式,讓 WCF 本身可以管理驗證,而 WCF 本身可支援 Windows 驗證的各種其他選項。 內建的其他選項包括用戶名稱令牌、X.509 憑證、SAML 令牌和 CardSpace 卡,但也可以定義自定義驗證機制。

安全性:冒充

ASP.NET 提供一個身分識別元素,使 ASP.NET Web 服務能夠模擬特定使用者,或依據當前請求提供的任意用戶憑證進行模擬。 該元素可用來在 ASP.NET 相容性模式中執行的 WCF 應用程式中設定模擬。

WCF 組態系統提供自己的身分識別元素,以指定要仿真的特定使用者。 此外,WCF 客戶端和服務也可以獨立配置以進行身份模擬。 用戶端可以設定為在傳送要求時模擬目前使用者。

<behaviors>
     <behavior name="DerivativesCalculatorClientBehavior">
      <clientCredentials>
      <windows allowedImpersonationLevel="Impersonation"/>
      </clientCredentials>
     </behavior>
</behaviors>

服務作業可以設定為使用目前要求所提供的用戶憑證,以模擬任何用戶的身份。

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void Receive(Message input)

安全性:使用訪問控制清單進行授權

訪問控制清單 (ACL) 可用來限制對 .asmx 檔案的存取。 不過,除了 ASP.NET 相容性模式之外,WCF .svc 檔案上的 ACL 會被忽略。

安全性:角色型授權

IIS Windows 驗證選項可以與 ASP.NET 組態語言所提供的授權專案搭配使用,以根據使用者指派的 Windows 群組,協助 ASP.NET Web 服務的角色型授權。 ASP.NET 2.0 引進了更一般的角色型授權機制:角色提供者。

角色提供者是實作基本介面的類別,這些類別用來查詢使用者被指派的角色,而每個角色提供者都知道如何從不同的來源擷取資訊。 ASP.NET 2.0 提供角色提供者,可從 Microsoft SQL Server 資料庫擷取角色指派,另一個可從 Windows Server 2003 授權管理員擷取角色指派。

角色提供者機制實際上可以不依賴於 ASP.NET 而獨立使用於任何 .NET 應用程式中,包括 WCF 應用程式。 WCF 應用程式的下列範例組態示範如何透過 ServiceAuthorizationBehavior 選擇使用 ASP.NET 角色提供者作為選項。

<system.serviceModel>
     <services>
         <service name="Service.ResourceAccessServiceType"
             behaviorConfiguration="ServiceBehavior">
             <endpoint
              address="ResourceAccessService"
              binding="wsHttpBinding"
              contract="Service.IResourceAccessContract"/>
         </service>
     </services>
     <behaviors>
       <behavior name="ServiceBehavior">
       <serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
      </behavior>
     </behaviors>
</system.serviceModel>

安全性:宣告型授權

WCF 最重要的創新之一是其徹底支援根據宣告授權存取受保護的資源。 主張包含類型、權利和值,例如駕照。 它提出了一組關於持有人的索賠,其中一個是持有人的出生日期。 該宣告的類型是出生日期,而宣告的值則是司機的出生日期。 宣告授與持有人的權利會指定持有人可以使用宣告值執行哪些動作。 在司機主張其出生日期的情況下,權利是擁有:司機擁有該出生日期,但不能更改。 宣告型授權會封入角色型授權,因為角色是宣告的類型。

基於宣告的授權是藉由比較一組宣告與操作的存取需求來完成,並根據比較的結果,授與或拒絕對該操作的存取權。 在 WCF 中,您可以再次藉由將值指派給 ServiceAuthorizationManagerServiceAuthorizationBehavior 屬性,來指定類別以執行宣告型授權。

<behaviors>
     <behavior name='ServiceBehavior'>
     <serviceAuthorization
     serviceAuthorizationManagerType=
                   'Service.AccessChecker, Service' />
     </behavior>
</behaviors>

必須衍生自ServiceAuthorizationManager的類別才可用來執行宣告型授權,而這些類別只有一個方法可供覆寫,那就是AccessCheck()。 每當服務的作業被叫用時,WCF 會呼叫該方法並提供一個 OperationContext 物件,該物件的 ServiceSecurityContext.AuthorizationContext 屬性中具有使用者的宣告。 WCF 從用戶提供的安全性令牌中組合使用者的宣告,並將評估這些宣告是否足以執行特定作業的任務留給後續流程。

WCF 能夠自動從任何類型的安全性令牌組合宣告,這是一項具有重大意義的創新,因為這使得基於宣告的授權程式碼可以完全獨立於驗證機制。 相較之下,ASP.NET 中使用 ACL 或角色的授權會與 Windows 驗證緊密系結。

安全性:機密性

透過將 IIS 內的應用程式設定為使用安全超文字傳輸通訊協定 (HTTPS),即可確保與 ASP.NET Web 服務交換之訊息的機密性。 針對 IIS 中裝載的 WCF 應用程式,可以執行相同的作業。 不過,裝載於 IIS 外部的 WCF 應用程式也可以設定為使用安全的傳輸通訊協定。 更重要的是,WCF 應用程式也可以使用 WS-Security 通訊協定,在訊息傳輸之前先設定為保護訊息。 使用 WS-Security 只保護訊息本文,可讓訊息在到達其最終目的地之前,以機密方式在媒介之間傳輸。

全球化

ASP.NET 組態語言可讓您指定個別服務的文化特性。 WCF 不支援該組態設定,但 ASP.NET 相容性模式除外。 若要將不使用 ASP.NET 相容性模式的 WCF 服務當地語系化,請將服務類型編譯成特定文化特性的元件,並針對每個特定文化特性元件使用不同的文化特性特定端點。

另請參閱