[VS2010] WCF 4.0 新功能 (1): 簡易組態 (Simple Configuration)

[VS2010] WCF 4.0 新功能 (1): 簡易組態 (Simple Configuration)

WCF (Windows Communication Foundation) 自.NET Framework 3.0 發布以來,歷經二次的大改版後,已經取代 .NET Remoting 以及 ASMX Services 成為微軟欽定的統一通訊 (Unified Communication) 開發平台,很多微軟的通訊平台都是利用 WCF 來開發的,它也悄悄的成為使用微軟開發平台的開發人員的重要關卡之一,未來在微軟平台上許許多多的伺服器與通訊架構都將要使用 WCF 來開發,Windows Azure AppFabric 的 Service Bus 就是其中一個最好的例子,但 WCF 學習曲線較陡的幾個地方,也是開發人員學習的瓶頸,像是協定繫結組態 (Protocol Binding Configuration) 就是其中的一個陡坡,在 WCF 中支援相當多的通訊協定,選擇是一回事,設定又是一回事,光是設定協定就已經令開發人員頭大,微軟也知道這點,在 WCF 4.0 中微軟將幾個常用的通訊協定,包裝成稱為標準終端點 (Standard Endpoint) 的封裝,這些封裝設定內建在標準通訊協定的程式碼中,因此使用這些協定的應用程式,將可大量簡化 WCF 應用程式的通訊設定,如此開發人員學習 WCF 4.0 的學習曲線便可降低一級。

有多簡單呢?舉例來說,下列一個簡單且使用 WCF 3.5 的應用程式的組態設定:

<system.serviceModel>
  <bindings>
    <!-- Application Binding -->
    <wsHttpBinding>
      <binding name="default” />
    </wsHttpBinding>
  </bindings>

  <services>
    <!-- Application Service -->
    <service name="AppFabricSB_ProductService.ProductQuery"
             behaviorConfiguration="default">
      <endpoint name="Endpoint"
                contract="AppFabricSB_ProductService.IProductQuery"
                binding="wsHttpBinding"
                bindingConfiguration="default"
                behaviorConfiguration="sharedSecretClientCredentials"
                address="" />
    </service>
  </services> 
  <behaviors>
    <endpointBehaviors>
      <behavior name="sharedSecretClientCredentials">
        <transportClientEndpointBehavior credentialType="SharedSecret">
          <clientCredentials>
            <sharedSecret issuerName="owner" issuerSecret="ceSHrhkaqcqgN/suoV8j2Zte+9HJvlJexxJaWtjp0Mo=" />
          </clientCredentials>
        </transportClientEndpointBehavior>
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior name="default">
      </behavior>
    </serviceBehaviors>
  </behaviors>

</system.serviceModel>

到了 WCF 4.0 時,組態設定變成只要這樣:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled ="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <protocolMapping>
    <add binding="wsHttpBinding" scheme ="http"/>
  </protocolMapping>
</system.serviceModel>

有沒有變得很簡單呢?這就是 WCF Simple Configuration 的威力。

例如,下列的應用程式是一個使用 WCF 4.0 的範例程式碼 (專案類型為 Console Application,有加入 System.Runtime.Serialization.dll, System.ServiceModel.dll 與 System.ServiceModel.Web.dll 的參考):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;

namespace SimpleConfiguration
{
    [DataContract]
    public class ProductInfo
    {
        [DataMember]
        public int ProductID { get; set; }
        [DataMember]
        public string Name { get; set; }
    }

    [ServiceContract(Namespace = "http://sample.azure.com/appfabric/servicebus/productcontract")]
    public interface IProductQuery
    {
        [OperationContract, WebGet]
        List<ProductInfo> LookupProducts();
        [OperationContract, WebGet]
        ProductInfo LookupProduct(int ProductID);
    }

    [ServiceBehavior(Name = "ProductQuery", Namespace = "http://sample.azure.com/appfabric/servicebus/productqueryservice")]
    public class ProductQuery : IProductQuery
    {
        public List<ProductInfo> LookupProducts()
        {
            List<ProductInfo> products = new List<ProductInfo>();

            using (NorthwindEntities context = new NorthwindEntities())
            {
                var query = from q in context.Products
                            select q;

                if (query.Count() > 0)
                {
                    foreach (var item in query)
                        products.Add(new ProductInfo() { Name = item.ProductName, ProductID = item.ProductID });
                }
            }

            return products;
        }

        public ProductInfo LookupProduct(int ProductID)
        {
            ProductInfo productInfo = new ProductInfo();

            using (NorthwindEntities context = new NorthwindEntities())
            {
                var query = from q in context.Products
                            where q.ProductID == ProductID
                            select q;

                if (query.Count() > 0)
                {
                    productInfo.ProductID = query.First().ProductID;
                    productInfo.Name = query.First().ProductName;
                }
            }

            return productInfo;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            WebServiceHost host = new WebServiceHost(typeof(ProductQuery), new Uri("
http://localhost:8080/ProductQuery"));
            host.Open();

            Console.WriteLine("Press ENTER to stop this service.");
            Console.ReadLine();

            host.Close();
            host = null;
        }
    }
}

以上程式碼皆只使用 WCF 的基本指令,沒有做什麼額外的設定,但重點是在 app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled ="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme ="http"/>
    </protocolMapping>
  </system.serviceModel>

  <connectionStrings>
    <add name="NorthwindEntities" connectionString="metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://*/Northwind.msl;provider=System.Data.SqlClient;provider connection string=…"
         providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

 

編譯並建立執行檔,然後執行它,會看到這樣的畫面:

image

 

然後瀏覽 http://localhost:8080/ProductQuery/LookupProducts,可以看到這樣的結果:

image

 

參考資料:

Simple Configuration in WCF 4.0

Standard Endpoints in WCF 4.0