程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF中的REST架構二 (支持AJAX的WCF服務 - 創建服務)

WCF中的REST架構二 (支持AJAX的WCF服務 - 創建服務)

編輯:關於.NET

我在昨天的文章WCF中的REST架構一(REST 概述)談了REST的基本概要,並提出了從HI REST (高REST)到 LO REST (低REST) 的RESTFULness(REST度)的概念。在今天的文章中,我將詳細介紹大家可能最為熟悉的REST風格的WCF 服務:支持AJAX的服務。此類服務應屬於LO REST的范疇。現在很多人直覺地將“好”等同於“高大全”,因而低估了這種LO REST實現的價值。本篇將告訴你這決非事實,支持AJAX的WCF服務是足夠強大的。

解決方案的背景信息

我有一個底層工作已基本完整的初始解決方案,大部分代碼是作為12集AJAX 客戶庫Webcast 系列的組成部分。提供這個初始解決方案的目的是為了讓我更好地展現支持AJAX的WCF服務的強大能力,避免現場創建一個這樣的服務然後再與AJAX 客戶應用集成所需的冗長步驟(如何你認為我創建的范例應用乏善可陳,請試一下Supersefer,這是一個基於這個范例的希伯來文網上商店)。在這個初始解決方案中請特別注意兩個ASP.Net AJAX 控件: Catalog.js和ShoppingCart.js.下面的截圖就是這兩個控件的顯示

Catalog控件是本篇的重要操作對象,它的任務是接受一個特定的數據結構,顯示一頁產品信息,作綁定用途,並在用戶選中某樣產品或者點擊浏覽控件的時候出發消息,至於該控件是如何與宿主頁(Catalog.aspx)交互,大家可以在前面提到的Webcast系列中找到。就本篇而言,我們只要關注Catalog.aspx(宿主頁)中的下列代碼片段,裡面有一個GetData() 方法。等我們實現了WCF服務之後,就在這個方法裡調用它。我們會給WCF服務傳入諸如startIndex(起始索引)和pageSize(頁的大小)之類的參數(服務的返回數據將是指定頁數的產品信息), 以及幾個回調方法(服務調用成功或失敗後被回調)。下面也給出了調用成功的回調方法。該方法直接獲取了指向catalog控件的引用($get 在 asp.net的AJAX中用來指向一個控件)。然後它將設定當前頁的索引值,再用傳入回調函數的數據,也就是我們的WCF有效荷載,來設定productInfo屬性。最後,該函數調用控件的dataBind方法,這個方法直接基於存儲在productInfo屬性中的數據做了一些DOM注入。

添加服務

添加一個支持AJAX的WCF 服務相當簡單。第一步就是使用'AJAX-enabled WCF Service'模板添加服務。過程如下:在Solution Explorer裡面選擇”Add New Item’ > 選擇'AJAX-enabled WCF Service' > 將其命名為 CatalogService.cs > 點擊 ‘Add’.

模板看起來相當神奇,其實它不過是添加了一些特定的文件,並更改了另一些文件(通常是*.config文件)而已。如果你是按照我的步驟,那麼這個模板做了下列事情:

1.在項目根目錄下添加CatalogService.svc文件

2.在app_code目錄下添加CatalogService.cs文件

3.在web.config內配置服務

分析一下生成的文件

我們來看一下上面模板生成的文件並稍加討論:

CatalogService.svc
<%@ ServiceHost   Language="C#"
          Debug="true"
          Service="CatalogService"
          CodeBehind="~/App_Code/CatalogService.cs" %>

*.svc文件可以類比於*.asmx文件。如果該服務在IIS或者WAS上運行,這個文件就作為服務的可定位資源。換句話說,*.svc 就是你服務的的基址。這個文件裡我們只需注意兩個屬性:首先是Service屬性,該屬性被設為實現該服務的CLR類型名(你可以在app_code目錄下的CatalogService.cs中找到該類型)。第二個就是指向實現文件的CodeBehind屬性。

你無需修改svc 文件的內容,我只是為了向你展示該文件就是作為服務的base地址。

web.config
<system.serviceModel>
  <behaviors>
   <endpointBehaviors>
    <behavior name="CatalogServiceAspNetAjaxBehavior">
     <enableWebScript />
    </behavior>
   </endpointBehaviors>
  </behaviors>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  <services>
   <service name="CatalogService">
    <endpoint  address=""
          behaviorConfiguration="CatalogServiceAspNetAjaxBehavior"
          binding="webHttpBinding"
          contract="CatalogService" />
   </service>
  </services>
 </system.serviceModel>

如果熟悉WCF,你一定知道WCF的配置是位於system.serviceModel節點下。你會看到3個子節點:behaviors, serviceHostingEnvironment和serivces:

1.Services: 文件內已經有一個名為CatalogService的服務,與實現服務的類名一致。在Service節點下,你可以看到Endpoint,它包含了服務的ABCs:Address(地址), binding (綁定)和contract (協定).

a.Address: 你會發現地址是空的,不必擔心,因為svc文件會作為基

b.Binding: webHttpBinding是WCF3.5提供的可以讓服務以REST方式發布的新型綁定。這個綁定有兩種模式,你可以通過特定的終結點行為來指定模式(通過設定behaviorConfiguration)

c.Contract: contract指定了WCF服務提供的功能。該屬性被設為一個已經定義好的服務協定。要定義一個服務協定,你可以用ServiceContract修飾一個接口或者類。被ServiceContract修飾的接口或者類中,所有由OperationContract修飾的方法將被作為服務的操作暴露給客戶。一般來說用接口做服務協定是更好的做法,這樣做的好處是分離了協定與具體實現。 但在我們使用的模板中卻使用了類的方法,也就是說,接口是從類自動推斷出來的(接口推斷)。

d.BehaviorConfiguration: 對於webHttpBinding, 你需要將該屬性設為一個擁有webHttp或enableWebScript子節點的終結點行為。

2.Behaviors: 將behaviors加入到服務或者服務終結點的目的在於改變runtime的默認行為或者加入定制的擴展。你會發現我們使用的模板已經聲明了一個名為CatalogServiceAspNetAjaxBehavior的終結點行為.該行為有一個enableWebScript 元素。enableWebScript是兩種可能的終結點行為之一,另一種就是webHttp。事實上enableWebScript是webHttp用來提供AJAX 功能(比如生成客戶端代理)的子類

3.ServiceHostingEnvironment: 跟ASP.Net運行的WCF服務的默認配置是讓兩者互不干擾 例如,ASP.NET runtime 不參與WCF請求的處理.WCF服務也不能使用ASP.NET context 和 session 這樣的功能.而我們這裡的配置是將aspNetCompatibilityEnabled 設為true, 在這種設置下WCF請求就會加到ASP.Net 的請求流水線裡了。

*要使WCF支持REST,只要在該配置文件中注意最重要的兩點:1)binding應設為webHttpBinding 2) endpoint behavior要設定為webHttp或enableWebScript

CatalogService.cs
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class CatalogService
{
  // Add [WebGet] attribute to use HTTP GET
  [OperationContract]
  public void DoWork()
  {
    // Add your operation implementation here
    return;
  }
  // Add more operations here and mark them with [OperationContract]
}

在這裡我們就真得做點兒事兒了。如果已經讀了上面的內容,你應該已經注意到我們已經用接口推斷的方法定義了的服務協定,就是說用ServiceContract屬性修飾了一個類而不是一個接口。

無論如何,我們要開始做一點兒實現了。第一件事兒是設定ServiceContract屬性的NameSpace參數。這一點非常重要。客戶端用於調用WCF服務的代理的名字空間就是從這裡拿的。我就將名字空間設為urn:shopping/services.[ServiceContract(Namespace = "urn:shopping/services")]

接下來,我要添加一個操作(就是一個用OperationContract修飾的方法)。這個操作使用LINQ to SQL到數據庫獲取一頁產品信息。該實現返回一個包含ProductData類型的ProductGroupingData 類型。我這樣做的原因在於我不僅需要返回產品信息(ProductData),還需要一些有助於分頁的元數據(StartIndex, PageSizebut 和ProductGrouping的TotalCount)。下面就是這些類型:

[DataContract]
public class ProductData
{
  [DataMember]
  public int ProductId;
  [DataMember]
  public string ProductName;
  [DataMember]
  public string Description;
  [DataMember]
  public decimal Price;
  [DataMember]
  public string ProductImage;
}
[DataContract]
public class ProductGroupingData
{
  [DataMember]
  public List<ProductData> Products;
  [DataMember]
  public int StartIndex;
  [DataMember]
  public int PageSize;
  [DataMember]
  public int TotalCount = 0;
}

以下是實現代碼:

[OperationContract]
public ProductGroupingData GetProductGrouping(int startIndex, int pageSize)
{
  using (CatalogDataContext catalogCtx = new CatalogDataContext())
  {
    // Set up the query
    var products = from p in catalogCtx.Products
            orderby p.ProductName
            select new ProductData()
            {
              ProductId = p.ProductId,
              ProductName = p.ProductName,
              Description = p.ProductDescription,
              Price = p.Price,
             ProductImage = p.ProductImage
            };
    // Use skip and take extension methods for server side paging
    // and call ToList to execute the query
    var productColl = products.Skip(startIndex).Take(pageSize).ToList();
    // Add the metadata
    var package = new ProductGroupingData()
    {
      Products = productColl,
      StartIndex = startIndex,
      PageSize = pageSize,
      TotalCount = catalogCtx.Products.Count()
    };
    return package;

}

到這裡,我們已經創建好了一個支持AJAX的服務。一個服務支持AJAX,就是說該服務可以非常容易地被一個 AJAX 客戶端調用。接下來的WCF中的REST架構 三,我就討論如何在客戶端調用服務.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved