恩,在由瘦客戶端轉換成胖浏覽器端的“潮流”下,必然要使用JavaScript調用後台的各種服務。
屌絲所維護的產品通信都是使用的WCF服務,因此必然要學習這樣的內容。借用jQuery強大的庫,使用JavaScript訪問WCF服務非常簡便。同事研究了一個breeze庫,那麼屌絲就來試驗一下ajax。這裡把實現簡單地記錄以便馬克一下,以後忘了就看這篇日志來作弊。
一、更改WCF服務的配置
默認情況下,WCF服務是不允許使用HTTP請求來訪問的。我們需要將WCF服務的配置文件(注意如果有其他啟動WCF服務的項目應該修改該項目的app.config文件)修改,將serviceHostEnvironment節添加aspNetCompatibilityEnabled屬性並設為true:
復制代碼 代碼如下:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<serviceActivations>
<add relativeAddress="TableManager.svc" service="TableManagerIntegrationTestService.TestResultService"
factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"/>
</serviceActivations>
</serviceHostingEnvironment>
而且,與之相關的服務binding屬性要配置成webHttpBinding,這樣js才能進行調用:
復制代碼 代碼如下:
<service name="TableManagerIntegrationTestService.TestResultService">
<endpoint address="" binding="webHttpBinding" contract="TableManagerIntegrationTestService.ITestResultService" behaviorConfiguration="EndpBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
......
二、WCF服務的操作契約
S要調用的服務操作契約必須為WebGet或WebInvoke。標記為WebGet屬性的可以使用HTTP GET方法調用,而WebInvoke標記允許HTTP POST方法調用。
我這裡有一個簡單的例子,該WCF服務接收年月日作為參數,返回該天的日志記錄。
該服務的Service Contract定義如下:
復制代碼 代碼如下:
[ServiceContract]
public interface ITestResultService
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
List<TestResultData> GetData(int year, int month, int date);
}
GetData方法的標記定義了該方法允許HTTP POST方法調用,返回的數據是JSON格式。指定了數據的返回格式後,我們不需要編寫任何代碼,WCF會將一個可序列化的對象自動轉換成對應的格式。
在服務類中,還需要指定AspNetComatibilityRequirements標記,如下面的示例代碼所示:
復制代碼 代碼如下:
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class TestResultService : ITestResultService
{
public List<TestResultData> GetData(int year, int month, int date)
{
try
{
DateTime start_time = new DateTime(year, month, date, 0, 0, 0);
DateTime end_time = new DateTime(year, month, date, 23, 59, 59);
DataSet ds = LogDataAccess.SelectDailyBuildLog(start_time, end_time);
var test_result_list = new List<TestResultData>();
foreach (DataRow result in ds.Tables[0].Rows)
{
TestResultData result_data = new TestResultData
{
DeployDate = Convert.ToDateTime(result["StatTime"]).ToString(),
ServerName = result["ComponentName"].ToString(),
Build = result["Build"].ToString(),
Result = result["Result"].ToString(),
ServerInformation = result["Versions"].ToString()
};
test_result_list.Add(result_data);
}
return test_result_list;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
三、浏覽器請求WCF服務
基本上,$.ajax方法需要8個參數:type指定操作方法(如POST)、url指定WCF服務的地址、data是傳給WCF的數據(也就是參數)、contentType指定data的格式(如json)和文字編碼、dataType指定返回數據的格式、processData指示是否自動將數據處理成application/x-www-form-urlencoded格式、success和error屬性指示操作成功或失敗後的回調方法。
我們在腳本中定義如下全局變量,以便調用ajax時訪問:
復制代碼 代碼如下:
var Type, Url, Data, ContentType, DataType, ProcessData;
我們編寫一個CallService方法,該方法直接調用$.ajax方法,並使用上面定義的參數:
復制代碼 代碼如下:
function CallService() {
$.ajax({
type: Type,
url: Url,
data: Data,
contentType: ContentType,
dataType: DataType,
processData: ProcessData,
success: function (msg) {
ServiceSucceded(msg);
},
error: ServiceFailed
});
}
以下是調用服務的一個示例,該方法從Year、Month和Date文本框中獲取用戶輸入的數據,並調用WCF服務請求數據:
復制代碼 代碼如下:
function WcfJson() {
Type = "POST";
Url = "http://localhost:8734/TableManagerIntegrationTestService/TestResultService/GetData";
Data = '{"year":' + $("#Year").val() + ', "month":' + $("#Month").val() + ', "date":' + $("#Date").val() + '}';
ContentType = "application/json; charset=utf-8";
DataType = "json"; varProcessData = true;
CallService();
}
在數據請求成功後,會調用success參數指定的回調方法,在此我們就可以處理返回結果。
返回結果是一個json格式的數據,如我們的例子中返回的是一個結果列表。如果不確定它的結構,可以在這裡加個斷點看看:
可以看到結果就在result對象的GetDataResult屬性中。直接訪問這個屬性的各元素就能得到結果了:
復制代碼 代碼如下:
function ServiceSucceded(result) {
if (DataType == "json") {
mainView.clearItem();
for (var i = 0; i < result.GetDataResult.length; i++) {
var resultObject = result.GetDataResult[i];
resultCollection.add(resultObject.ServerName, resultObject.DeployDate, resultObject.Build, resultObject.Result, resultObject.ServerInformation);
}
mainView.render(document.getElementById("logContainer"));
}
}
resultCollection和mainView是我自定義的兩個類,用於存儲要顯示的數據和繪制表格。代碼在這裡就不寫了。
現在,啟動WCF的服務,然後跑我們編寫的頁面,結果就出來了:
界面很丑敬請見諒 ^_^。(稍微調下CSS就會好看很多了……)