jQuery調用WCF服務傳遞JSON對象
下面這個示例使用了WCF去創(chuàng)建一個服務端口從而能夠被ASP.Net頁面通過jQuery的AJAX方法訪問,我們將在客戶端使用Ajax技術來 與WCF服務進行通信。這里我們僅使用jQuery去連接Web Service,而不去使用ASP.Net AJAX庫,至于為什么不使用AJAX庫中,那是因為我們在項目中已經(jīng)使用了jQuery,而它已經(jīng)能處理全部的AJAX請求和所有功能,并且,如果我們 一旦使用ASP.NET AJAX庫,我們也必須多包含一個超過80Kb的數(shù)據(jù)量(調試模式下會更大),但這也不是說ASP.NET AJAX庫不實用,事實上,如果使用了相同的類庫,我們能夠少寫很多的額外代碼,但這個例子就是為了說明,在沒有一個好的客戶端代理的情況下,我們是如何調用Web服務的。
WCF 服務:
我們先創(chuàng)建一個WebSite,然后添加一個AJAX-enabled WCF Service,從而創(chuàng)建WCF服務。(請確保你使用了正確的.Net Framework 版本,我用的是3.5)
在我們添加完service后,它會自動進入該service的后置代碼文件,Go ahead and browse around the file for a second.
首先我們要做的是找到"AspNetCompatibilityRequirements"并將其值置為 "Allowed":
[AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed )]
這個屬性的設置可將我們的服務跑在ASP.NET compatibility模式,如果我們未將該值設為"Allowed",那么就無法通過ASP.Net去訪問到該服務,這個屬性是當你添加 "AJAX-enabled WCF Service" 時自動生成的。更多祥細請參看MSDN。
現(xiàn)在再來看自動生成的后置代碼文件,我們能發(fā)現(xiàn)已經(jīng)存在了一個被標注了"OperationContract"特性的"DoWork()" 的方法,這個方法是自動生成的,我們將使用這個方法來完成下面的示例。我們再來為該方法添加一個"WebGet"的特性,并設"RequestFormat" 的值為 "Json." 我們再來為該方法加上另外的一個特性RequestFormat,WebGet 和Get動詞一樣,作用于一個UriTemplate(本文不對此作進一步討論),RequestFormat 特性可以讓我們接收JSON格式的請求。
我們的 "DoWork()" 方法如下:
- [OperationContract]
- [WebGet( RequestFormat=WebMessageFormat.Json )]
- public void DoWork()
- {
- // Add your operation implementation here
- return;
- }
對象的模型:
我們希望通過"DoWork()" 來傳遞一個叫“Person”的對象,那先來創(chuàng)建一個Person對象寫入到當前類的頭部,其包含字段和屬性(Name, Age 和 the types of Shoes they own),這個類同時也作為所傳遞JSON的結構。
- [Serializable]
- [DataContract( Namespace = "http://www.dennydotnet.com/", Name = "Person" )]
- public class Person
- {
- private string _name = string.Empty;
- private int _age = 0;
- [DataMember( IsRequired = true, Name = "Name" )]
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- [DataMember( IsRequired = true, Name = "Age" )]
- public int Age
- {
- get { return _age; }
- set { _age = value; }
- }
- [DataMember( IsRequired = true, Name = "Shoes" )]
- public List<String> Shoes;
- }
我們已經(jīng)為 "Person”類的名稱和命名空間標注上了契約,我們仍需要為屬性授于數(shù)據(jù)成員特性,為每個屬性 設置"IsRequired"并具體指定其名稱。你只需要具體指定名字,如果它和屬性名不一樣。舉例來說吧,如果你有一個屬性叫作“Level”,但你在 數(shù)據(jù)成員特性中賦值為“Rank”,現(xiàn)在我們要回去修改我們的“DoWork()”方法,去接收Person對象作為參數(shù)。具體參下面代碼塊。
- [OperationContract]
- [WebGet( RequestFormat=WebMessageFormat.Json )]
- public void DoWork(Person p)
- {
- // Add your operation implementation here
- return;
- }
對Web.Config文件進行配置:
我們僅需對web.config文件做出很小的修改就能對服務進行訪問了。首先加入一個 serviceBehavior 用來允許Http Get請求,再添加一些調試選項幫助。代碼如下:
Below </endpointBehaviors>
- <serviceBehaviors>
- <behavior name="ServiceAspNetAjaxBehavior">
- <serviceMetadata httpGetEnabled="true" httpGetUrl="" />
- <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
- </behavior>
- </serviceBehaviors>
在<services>這里</services>之間,你的代碼如下:
- <service name="Service" behaviorConfiguration="ServiceAspNetAjaxBehavior">
- <endpoint address="" behaviorConfiguration="ServiceAspNetAjaxBehavior"
- binding="webHttpBinding" contract="Service" />
- <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
- </service>
注意:
- <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
允許例外可能會導致內部應用相關信息,包括個人信息的泄露。設置為true僅用于調試目的!
你的Web.config文件修改后如下圖所示:
回到前端頁面:
現(xiàn)在我們的服務已經(jīng)被創(chuàng)建和配置了,再來關注前端頁面部分吧(確保頁面已引用jQuery.js文件),首先來創(chuàng)建一個簡單的Json對象用于向service傳遞,我們在Person類結構的基礎上創(chuàng)建該JSON對象。
- var mydata = { "Name":"Denny", "Age":23, "Shoes":["Nike","Osiris","Etnies"] };
如果你對JSON還不是很熟悉,我們可以把它看作一個對象,這個小工具幫助你來查看 (JsonViewer):
我們需要使用WCF和jQuery進行Ajax通信,下面的代碼創(chuàng)建了一個AJAX呼叫,在頭部設置了GET方式,和內容類型為 application/json,將url的路徑置為WCF 服務的 svc 文件,并在其后加上/和所要執(zhí)行方法的名稱,在這里我們要調用的是DoWork()方法,data是用來傳遞參數(shù),為了讓jQuery不去自動處理我們的 數(shù)據(jù),將processData設為false,我們還加入了對success和error的處理,以更多的了解AJAX執(zhí)行完之后的處理過程。
- function sendAJAX(data) {
- $.ajax({
- type: "GET",
- contentType: "application/json",
- url: "Service.svc/DoWork",
- data: data,
- processData: false,
- success: function(msg){
- alert( "Data Saved!" );
- },
- error:function(XMLHttpRequest, textStatus, errorThrown){
- alert( "Error Occured!" );
- }
- });
- }
然而很不幸運,這里有一個小的問題,我們必須發(fā)送真正的JSON字符串,作為參數(shù)傳遞。但還沒有簡單的方法讓JSON對象轉換為字符串,如果你試了data.toString(),得到的會是一個 "[object Object]"值。這不是我們想要的。
所以在這里我們要修改方法使得它能將JSON轉換成字符串。
- function json2string(strObject) {
- var c, i, l, s = '', v, p;
- switch (typeof strObject) {
- case 'object':
- if (strObject) {
- if (strObject.length && typeof strObject.length == 'number') {
- for (i = 0; i < strObject.length; ++i) {
- v = json2string(strObject[i]);
- if (s) {
- s += ',';
- }
- s += v;
- }
- return '[' + s + ']';
- } else if (typeof strObject.toString != 'undefined') {
- for (i in strObject) {
- v = strObject[i];
- if (typeof v != 'undefined' && typeof v != 'function') {
- v = json2string(v);
- if (s) {
- s += ',';
- }
- s += json2string(i) + ':' + v;
- }
- }
- return '{' + s + '}';
- }
- }
- return 'null';
- case 'number':
- return isFinite(strObject) ? String(strObject) : 'null';
- case 'string':
- l = strObject.length;
- s = '"';
- for (i = 0; i < l; i += 1) {
- c = strObject.charAt(i);
- if (c >= ' ') {
- if (c == '\\' || c == '"') {
- s += '\\';
- }
- s += c;
- } else {
- switch (c) {
- case '\b':
- s += '\\b';
- break;
- case '\f':
- s += '\\f';
- break;
- case '\n':
- s += '\\n';
- break;
- case '\r':
- s += '\\r';
- break;
- case '\t':
- s += '\\t';
- break;
- default:
- c = c.charCodeAt();
- s += '\\u00' + Math.floor(c / 16).toString(16) +
- (c % 16).toString(16);
- }
- }
- }
- return s + '"';
- case 'boolean':
- return String(strObject);
- default:
- return 'null';
- }
- }
現(xiàn)在我們有一個方法可以將JSON對象轉成我們所需要的字符串,現(xiàn)在我們回過頭去修改我們之前定義的 "mydata" 變量,我們應當按下面去應用所寫的json2string方法。
- var mydata = { "Name":"Denny", "Age":23, "Shoes":["Nike","Osiris","Etnies"] };
- var jsonStr = "p=" + json2string(mydata);
注意在下面我準備了"p=" 字符在我們的JSON字符串中,“p”對應于"DoWork()" 方法中的參數(shù),當我們將參數(shù)改名為"Dude" ( 例如DoWork(Person Dude) )時,我們也必須將此處替換為"Dude="
現(xiàn)在我們準備好了查詢字符串,我們參看到我們如何調用服務:
- http://www.dennydotnet.com/Service.svc/DoWork/?p={ "Name":"Denny", "Age":23, "Shoes":["Nike","Osiris","Etnies"] }
你將接收到一個已經(jīng)為URL編碼處理過的值,如下:
- http://www.dennydotnet.com/Service.svc/DoWork/?p=%7b+%22Name%22%3a%22Denny%22%2c+%22Age%22%3a23%2c+%22Shoes%22%3a%5b%22Nike%22%2c%22Osiris%22%2c%22Etnies%22%5d+%7d%3b
緊接著我們去調用"SendAjax()" javascript 方法,現(xiàn)在能夠調試我們的服務并驗證數(shù)據(jù)是否被傳遞到服務。如下圖
現(xiàn)在你僅需要在DoWork()方法里實現(xiàn)自己的邏輯。注意無論你如何怎么去做 在WCF的服務端,它已經(jīng)為你做好了。
【編輯推薦】