標籤:des style class blog c code
建立網站服務(Web Services)
網站服務(Web Services)是基於一些標準的(通常是 SOAP),使應用程式能夠通過HTTP 交換資料。網站服務由網站方法(web methods)組成,公開這些方法,可以在網路上運行;某種程度上,可以把它看作是 F# 的函數,因為網站方法有名字,有參數,也返回結果,參數和結果用中繼資料(metadata)進行描述,網站服務把這些也都公開了,因為用戶端可以知道如何調用它。
建立網站服務非常簡單。事實上,建立網站服務的主要問題可能是如何通過網站伺服器公開代碼。網站伺服器以URL 的形式接收對檔案的請求,就必須告訴網站伺服器,這個請求應該映射到哪一個 .NET 類。通常用 .asmx 檔案運行特定的 F# 類,響應對這個網站服務的請求,如果網站伺服器獲得對這個 .asmx 檔案的請求。準確的實現方法依開發環境和託管服務的網站伺服器的不同而不同。
Visual Studio 有內建的網站伺服器,因此,建立新網站網站,只需要簡單地選擇檔案->建立->網站,然後,選擇網站的位置。網站只能運行用 C# 或者 Visual Basic .NET 寫的頁面,因此,還需要在解決方案中添加 F#項目,然後,手工修改解決方案檔案,以便它駐留在網站目錄中。聽上去複雜,做起來很容易,只要把 .fsharpp 檔案複製到網站目錄,用記事本開啟 .sln 檔案,修改 .fsproj 檔案的路徑。圖 11-3 是修改前後的 .sln 檔案,左邊是原始檔案。
圖 11-3 如何修改 .sln 檔案
之後,需要設定項目檔案的輸出為類庫,並寫到 bin 子目錄。這似乎要一定的努力,但以後只要按下 F5 就行了,項目會自動編譯並運行。
[
1、輸出為類庫,這一項只要確認一下就可以了,因為在添加項目時會要求選擇的,因此,只有當時沒有選擇類庫時,現在才要修改;
2、寫到 bin 子目錄,需要在後期建置事件命令列中輸入:
copy $(TargetFileName)E:\WebSites\ASP.NET\bin
這裡假定E:\WebSites\ASP.NET 是網站駐留的目錄,且已經建立了 bin 子目錄。
]
如果沒有 Visual Studio,那麼下一步要做的事情最好就是用互連網資訊服務(Internet Information Services,IIS)託管網站,微軟自己的用於 Windows 的網站伺服器。在某種意義上,這個比用 Visual Studio 託管更容易,但對於完成代碼後的運行並不方便。為了在 IIS 中Managed 程式碼,需要建立一個 IIS 的虛擬目錄,和子目錄 bin;然後,複製 .asmx 頁面和 web.config 檔案到這個虛擬目錄中。
服務本身很簡單。它應該就是一個類,繼承自System.Web.Service.WebService,有一個無參數的建構函式;也應該把它標記成 System.Web.Service.WebServiceAttribute。如果打算公開網站服務,必須設定屬性的命名空間(Namespace),預設是http://tempuri.org;即使不打算公開服務,設定這個屬性對網站服務的可管理性也有好處。那麼,類的成員,即網站方法,用System.Web.Service.WebMethodAttribute 標記[ 原文 WebServiceAttribute有誤],它也有大量有用的屬性,特別值得設定的是描述(Description)屬性,它能使服務的用戶端知道可以獲得什麼。
清單 11–7 定義了一個簡單網站服務,建立了類型 Service,它有一個成員Addition 的服務,參數必須以元組的風格出現。
清單 11-7 建立一個簡單網站服務
namespaceStrangelights.WebServices
open System.Web.Services
[<WebService(Namespace =
"http://strangelights.com/FSharp/Foundations/WebServices")>]
type Service =
inherit WebService
new() = {}
[<WebMethod(Description ="Perfomsinteger addition")>]
member s.Addition ((x : int), (y : int)) = x + y
[
需要引用 System.Web、System.Web.Services、System.EnterpriseServices;
把x.Addition 改成 s.Addition;當然,也不一定是 s,只要不與後面出現的 x 和 y 相同的字母都是可以的。
]
要想讓網站伺服器發現網站服務,需要建立 .asmx檔案。下面是 .asmx 檔案的樣本,最重要的是把 Class屬性設定為服務的類名。當伺服器收到對這個檔案的請求,就會調相應的服務:
<%@ WebServiceClass="Strangelights.WebServices.Service" %>
如果在本地運行這個服務,只要簡單地在瀏覽器中開啟它,就能測試了。在瀏覽器中,將看到 11-4 所示的介面,可以為網站服務提供參數值,並調用這個服務。
圖 11-4 調用本地的網站服務
用 46 和 28 作為參數值,調用這個服務,產生下面的 XML:
<?xml version="1.0"encoding="utf-8" ?>
<intxmlns="http://strangelights.com/FSharp/Foundations/WebServices">74</int>
通常,在網路上發送少量的資料是效率低下的,因為發送的每個請求都必須有固定數量的中繼資料。因此,更好的辦法是構建的應用程式不能是“閑聊式”的,即應用程式應該發送一個大的請求,而不應該發送許多個小的請求。
網站服務將企圖把任何 .NET 對象的方法返回值序列化(serialize)成 XML;然而,結果可能有點無法預測,因此,結果的 XML 資料也不可能包含所有期望的欄位,這樣,就很難在其他程式設計語言中使用了。要避免這種情況,最好是使用 XSD 架構來定義想要跨網站服務傳遞的對象。XSD 架構是一種 XML 文檔,它描述了 XML 文檔的結構,描述的內容包括哪些欄位是強制性的,以及欄位應該按什麼順序出現等、這些架構會成為網站服務定義的一部分,使用這個網站服務的所有的人都能瞭解他會從這個網站服務期望得到什麼欄位;定義的網站服務中有一個欄位包含二進位或十六進位資料,是最好的,因為用為網站服務的使用者有更多的機會理解結果的含義。
雖然自己定義 XML 結構描述是可能的,但是,Visual Studio 有一些建立架構的圖形方式和文本方式;網上有許多預定義的架構可以下載,而在些基礎上再構建也是可能的。例如,下面將要看到的樣本使用了RNAML,這個在http://www-lbit.iro.umontreal.ca/rnaml/上可以找到,這是為想以 XML 形式交換 RNA(核糖核酸,一種由分子生物學家研究的物質)資訊的人們提供的架構。從網站上下載架構以後,就可以用使用命令列工具 xsd.exe 把架構轉換成 .NET形式的表示。這個工具產生以# 類來表示 XML 資料,通常,XML 中的每個標記都會成為 .NET 的一個類;然後,可以把這個 C# 檔案編譯成一個 .NET 程式集,供 F# 或其他任何 .NET 庫使用。完成的命令列可能像這樣:
xsd rnaml.xsd /classes
注意,需要把下載的架構檔案rnaml.xml 重新命名為 rnaml.xsd,工具才能正確運行。
下面的樣本示範如何建立網站服務,返回酵母 RNA 分子結構,這是 RNAML 網站上系列樣本的縮減版本(http://www-lbit.iro.umontreal.ca/rnaml/)。像以前一樣,需要建立一個 .asmx 檔案,把被請求的檔案連結到 .NET 類型上,來處理請求:
<%@ WebServiceClass="Strangelights.WebServices.DnaWebService" %>
清單 11-8 展示了這個網站服務,可以看到,這個網站的基本組件與前面簡單的網站服務是相同的。像前面的一樣,有一個類定義,標記為WebService 特性;代碼所做的工作是定義了方法GetYeastMolecule,在這裡,我們建立並發布了不同的對象,它們定義在用 rnaml.xsd 檔案建立的庫中,比如分子物件和序列對象。
清單 11-8 建立網站服務,返回 RNA 分子的定義
namespace Strangelights.WebServices
open System.Web.Services
//the web service class
[<WebService(Namespace=
"http://strangelights.com/FSharp/Foundations/DnaWebService")>]
type DnaWebService() =
inherit WebService()
// the web method
[<WebMethod(Description = "Gets arepresentation of a yeast molecule")>]
member x.GetYeastMolecule () =
// the code that populates the yeast xml structure
let tax = new taxonomy(domain = "Eukaryota", kingdom ="Fungi",
phylum = "Ascomycota", ``class`` = "Saccharomycetes",
order = "Saccharomycetales",
family = "Saccharomycetaceae",
genus = "Saccharomyces",
species = "Saccharomycescerevisiae")
let id = new identity(name = "Saccharomycescerevisiae tRNA-Phe",
taxonomy = tax)
let yeast = new molecule(id = "Yeast-tRNA-Phe", identity = id)
let numRange1 = new numberingrange(start = "1", Item ="10")
let numRange2 = new numberingrange(start = "11", Item ="66")
let numSys = new numberingsystem(id="natural", usedinfile=true)
numSys.Items <- [|box numRange1; boxnumRange2|]
let seqData = new seqdata()
seqData.Value <- "GCGGAUUUAGCUCAGUUGGG AGAGCGCCAG ACUGAAGAUC
UGGAGGUCCU GUGUUCGAUC CACAGAAUUCGCACCA"
let seq = new sequence(numberingsystem = [|numSys|], seqdata =seqData)
yeast.sequence <- [|seq|]
yeast
另外,同樣簡單,可以使用基於網站的測試方法,運行前面的代碼,產生如下的 XML:
<?xmlversion="1.0"encoding="utf-8"?>
<moleculexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"id="Yeast-tRNA-Phe">
<identity>
<name>Saccharomycescerevisiae tRNA-Phe</name>
<taxonomy>
<domain>Eukaryota</domain>
<kingdom>Fungi</kingdom>
<phylum>Ascomycota</phylum>
<class>Saccharomycetes</class>
<order>Saccharomycetales</order>
<family>Saccharomycetaceae</family>
<genus>Saccharomyces</genus>
<species>Saccharomyces cerevisiae</species>
</taxonomy>
</identity>
<sequence>
<numbering-systemid="natural"used-in-file="true">
<numbering-range>
<start>1</start>
<end>10</end>
</numbering-range>
<numbering-range>
<start>11</start>
<end>66</end>
</numbering-range>
</numbering-system>
<seq-data>GCGGAUUUAGCUCAGUUGGG AGAGCGCCAG ACUGAAGAUCUGGAGGUCCU GUGUUCGAUC CACAGAAUUC GCACCA</seq-data>
</sequence>
</molecule>
這個樣本返回一個靜態、不變的 XML 文檔,並沒有什麼特別的用處,但是,很容易看出這種程式的潛力。如果不使用GetYeastMolecule 方法,而是用更現實的方法 GetMolecule,把分子的名字作為參數,就可以在資料庫中檢索出這個分子的詳細資料,返回分子資料的結果。其好處是,運行在任何平台上程式都可以使用這個結果資料。現在,樣本網站已經提供了 C++ 和 Java 處理資料的編程介面;我們也已經看到,在 F# 中處理這種資料非常簡單。當然,這項技術並不限於分子生物學,可以發現使用 XML 結構描述幾乎所有領域都適用,科學、工程、數學和金融。
可以有幾種方法加強網站服務的保護,保護網站服務可以保證只能有部分使用者訪問,或者在網路上傳輸的資訊要加密或簽名。一種方法是升級到 Windows 通訊基礎(Windows Communication Foundation,WCF),它類似於網站服務,但在這方面提供了更多的靈活性,將在下一節中討論;另一種方法是我們自己配置網站伺服器,處理這些安全需求。
[
需要引用 System.Web、System.Web.Services、System.EnterpriseServices,以及rnaml;
但是,由於沒有下載到 rnamk.xml,因此,後面的工作也就沒法進行了。
]