[VS2010] Visual Studio 2010 與 Windows Azure: 在 AppFabric Service Bus 上開發 REST 服務

[VS2010] Visual Studio 2010 與 Windows Azure: 在 AppFabric Service Bus 上開發 REST 服務

AppFabric 除了 Access Control 之外,另一個重要的服務是服務匯流排 (Service Bus),服務匯流排是一種服務介接的機制,可以允許企業在 AppFabric 中掛上一個或多個服務,並且利用 AppFabric Service Bus 作為中轉站,將服務開放給用戶端使用。也可以和 AppFabric Access Control 合併使用,以搭建企業的服務通訊平台。而 Service Bus 的核心技術是 WCF (Windows Communication Foundation),必須要使用 WCF 才可以開發 Service Bus 應用程式,在本文介紹的就是利用 WCF 配合 AppFabric 開發一個簡單的 REST 服務應用程式。WCF 是微軟目前正在推廣的新一代通訊整合開發平台,它整併了許多以前 .NET Framework 中與通訊有關的功能,像 .NET Remoting,ASMX Web Service 這些都被整併到 WCF 中,雖然 WCF 讓程式設計模型統一了,但也因為統一,讓開發與設定的工作變得十分繁雜。限於篇幅,本文將假設讀者已經對 WCF 有一定的知識,如果讀者不了解 WCF 的話,可以參考 MSDN 上的 WCF Programmer’s Guide,或至市面上找尋有寫 WCF 的書籍。

本文所開發的 Service Bus REST 服務具有下列功能:

1. 使用 Entity Framework 存取資料庫 (Northwind 資料庫)。
2. 利用 REST 來開放介面,讓用戶端可使用 URL 讀取產品清單。

那麼,我們就來動手開發吧。

1. 建立一個新的 Console Application,並且在專案屬性中將 Target Framework 切換到 .NET Framework 4.0 (預設是 .NET Framework 4.0 Client Profile)。

 

image

 

然後將 System.ServiceModel.dll 以及 System.Web.dll 加入參考,並且也將 Microsoft.ServiceBus.dll 加入參考 (此組件在 Windows Azure platform AppFabric SDK 安裝目錄下的 Assemblies 目錄中)。

 

2. 建立一個新的 ADO.NET Entity Data Model,連接到 Northwind 資料庫。

 

image

 

3. 在 Program.cs 中,加入下列命名空間的宣告:

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Description;
using Microsoft.ServiceBus.Web;

 

4. 定義產品資訊的資料合約 (Data Contract),這份資料合約是很簡單的 POCO 物件:

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

 

並且再定義服務合約 (Service Contract) 以及方法 (Operation Contract) 以建立服務規範:

[ServiceContract(Namespace = "http://sample.azure.com/appfabric/servicebus/productcontract")]
public interface IProductQuery
{
    [OperationContract, WebGet] // 使用 WebGet 宣告,以設定讓此方法使用於 REST API
    List<ProductInfo> LookupProducts();
    [OperationContract, WebGet] // 使用 WebGet 宣告,以設定讓此方法使用於 REST API
    ProductInfo LookupProduct(int ProductID);
}

 

5. 實作服務合約,這裡會使用到 LINQ to Entities:

[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;
    }
}

 

6. 修改 app.config,加入下列設定 (其中的 [YOUR_SB_ACCOUNT] 與 [YOUR_SB_PASSWORD] 請填入你的 AppFabric Service Bus 的名稱與 key 字串):

<system.serviceModel>
<bindings>
  <!-- Application Binding -->
  <webHttpRelayBinding>
    <binding name="default">
      <!-- Turn off client authentication so that client does not need to present credential through browser or fiddler -->
      <security relayClientAuthenticationType="None" />
    </binding>
  </webHttpRelayBinding>
</bindings>

<services>
  <!-- Application Service -->
  <service name="AppFabricSB_ProductService.ProductQuery"
           behaviorConfiguration="default">
    <endpoint name="RelayEndpoint"
              contract="AppFabricSB_ProductService.IProductQuery"
              binding="webHttpRelayBinding"
              bindingConfiguration="default"
              behaviorConfiguration="sharedSecretClientCredentials"
              address="" />
  </service>
</services>

<extensions>
  <behaviorExtensions>
    <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </behaviorExtensions>
  <bindingExtensions>
    <add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </bindingExtensions>
</extensions>

<behaviors>
  <endpointBehaviors>
    <behavior name="sharedSecretClientCredentials">
      <transportClientEndpointBehavior credentialType="SharedSecret">
        <clientCredentials>
          <sharedSecret issuerName="[YOUR_SB_ACCOUNT]" issuerSecret="[YOUR_SB_PASSWORD]" />
        </clientCredentials>
      </transportClientEndpointBehavior>
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="default">
      <serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>

</system.serviceModel>

 

7. 在 Main 方法中,設定 WebServiceHost 物件,讓程式將服務掛載在 WCF Host 上:

static void Main(string[] args)
{
    string serviceNamespace = "[service namespace]"; // 設定你的命名空間。
    Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "ProductQuery");

    WebServiceHost host = new WebServiceHost(typeof(ProductQuery), address);
    host.Open();

    Console.WriteLine("To close this service, please press ENTER.");
    Console.ReadLine();

    host.Close();
}

 

8. 執行此程式,你應該會看到這個訊息:

image

 

這表示服務已經掛載到了行程上,並且允許用戶端使用 http”//[service namespace].servicebus.windows.net/ProductQuery/[REST Method] 來存取服務。如下畫面:

image

 

參考資料:

REST Toturial for AppFabric Service Bus