小喵最近有個需求,系統必須提供給舊系統呼叫小喵的 COM+ 元件,本來與其他系統負責人溝通後,最好能夠傳回 JSON 內容,並已經敲定透過 WebAPI 應該是比較好的一個合作方式,無奈在跟負責主機管理的人提出環境確認時,不幸得到的消息是,無法安裝新的.NET Framework,因此無法使用 WebAPI 。所幸小喵找到了一個好朋友 Donma 分享的文章,提供了解決的方法~
緣起
小喵最近有個需求,系統必須提供給舊系統呼叫小喵的 COM+ 元件,本來與其他系統負責人溝通後,最好能夠傳回 JSON 內容,並已經敲定透過 WebAPI 應該是比較好的一個合作方式,無奈在跟負責主機管理的人提出環境確認時,不幸得到的消息是,無法安裝新的.NET Framework,因此無法使用 WebAPI 。所幸小喵找到了一個好朋友 Donma 分享的文章,提供了解決的方法~
範例物件
這邊簡單用個UserInfo類別來當作範例物件,相關的內容如下:
Public Class UserInfo
Public Property UserName As String = ""
Public Property Age As Integer = 0
End Class
WebService
接著撰寫 WebService 的部分。首先是因為要傳回JSON的格式,先 Imports System.Web.Script.Service
Imports System.Web.Script.Services
接著,小喵用了兩個練習:
- 透過GET來取得多筆的資料,傳回物件集合,轉JSON格式
- 透過POST送資料過來,最後傳回物件,轉JSON格式
透過 ScriptMothod的宣告,GetUsers 這個不需要傳入資料的部分,宣告可以使用 GET 來呼叫,而傳回的內容指定為JSON (Client端還是要配合指定傳回格式)
相關的程式碼如下:
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Script.Services
' 若要允許使用 ASP.NET AJAX 從指令碼呼叫此 Web 服務,請取消註解下列一行。
<System.Web.Script.Services.ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class WSUser
Inherits System.Web.Services.WebService
<WebMethod()> _
<ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Json)> _
Public Function GetUsers() As List(Of UserInfo)
Try
Dim y As Integer
Dim oUsers As New List(Of UserInfo)
Dim tUser As UserInfo
'迴圈產生傳回的資料
For y = 1 To 10
tUser = New UserInfo
tUser.UserName = "User" & y.ToString("00")
tUser.Age = 20 + y
oUsers.Add(tUser)
Next
Return oUsers
Catch ex As Exception
Throw
End Try
End Function
<WebMethod> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function GetOneUser(ByVal UserName As String, ByVal Age As Integer) As UserInfo
Try
Dim rtnUser As New UserInfo
rtnUser.UserName = UserName
rtnUser.Age = Age
Return rtnUser
Catch ex As Exception
Throw
End Try
End Function
End Class
ScriptMethod中宣告傳回的格式是Json,不過使用端還是要配合設定,不然傳回的預設還是xml。傳回xml或json在Server端這邊程式不必特別為Client端分開寫,有WebAPI 類似的方便。
因為其中 GetUsers 想透過 GET來呼叫,所以在 Web.Config 中特別設定一下,在System.Web的段落中,加入以下的內容
<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpGet"/>
</protocols>
</webServices>
這樣測試一下GetUsers,跑出來如下的內容
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ArrayOfUserInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<UserInfo>
<UserName>User01</UserName>
<Age>21</Age>
</UserInfo>
<UserInfo>
<UserName>User02</UserName>
<Age>22</Age>
</UserInfo>
<UserInfo>
<UserName>User03</UserName>
<Age>23</Age>
</UserInfo>
<UserInfo>
<UserName>User04</UserName>
<Age>24</Age>
</UserInfo>
<UserInfo>
<UserName>User05</UserName>
<Age>25</Age>
</UserInfo>
<UserInfo>
<UserName>User06</UserName>
<Age>26</Age>
</UserInfo>
<UserInfo>
<UserName>User07</UserName>
<Age>27</Age>
</UserInfo>
<UserInfo>
<UserName>User08</UserName>
<Age>28</Age>
</UserInfo>
<UserInfo>
<UserName>User09</UserName>
<Age>29</Age>
</UserInfo>
<UserInfo>
<UserName>User10</UserName>
<Age>30</Age>
</UserInfo>
</ArrayOfUserInfo>
不是指定要丟回JSON嗎,怎麼還是跑出xml ?
其實不必擔心,只要Client端呼叫的時候,指定Content-Type, dataType即可
jQuery呼叫範例:
WebService準備好了,接下來就寫呼叫引用的JavaScript,首先準備測試的畫面:
<input type="button" id="btnGet" value="取得Users" />
<br />
UserName:<input type="text" id="txtUserName" value="" /><br />
Age:<input type="number" id="numAge" value="0" /><br />
<input type="button" id="btnGetOneUser" value="設定並取得User" />
<hr />
<textarea id="ta1" cols="60" rows="20"></textarea>
相關 jQuery Ajax的範例如下:
<script>
var strURL1 = 'http://localhost:48314/WSUser.asmx/GetUsers';
var strURL2 = 'http://localhost:48314/WSUser.asmx/GetOneUser';
$(document).ready(function () {
$('#btnGet').click(getUsers);
$('#btnGetOneUser').click(SetAndGetOneUser);
});
function SetAndGetOneUser() {
var UserName = $('#txtUserName').val();
var Age = $('#numAge').val();
$.ajax({
type: "POST",
url: strURL2,
contentType: "application/json; charset=utf-8",
data:'{UserName:"' + UserName + '",Age:' + Age + '}',
dataType: "json",
success: function (data) {
if (data.hasOwnProperty("d")) {
$('#ta1').text(JSON.stringify(data.d));
}
else {
$('#ta1').text(JSON.stringify(data));
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
}
function getUsers() {
$.ajax({
type: "GET",
url: strURL1,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (data.hasOwnProperty("d")) {
$('#ta1').text(JSON.stringify(data.d));
}
else {
$('#ta1').text(JSON.stringify(data));
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
}
</script>
這樣產出的JSON,會有個怪怪的 d 如下:
所以會透過 data.hasOwnProperty 的方式判斷是否有那個 d 如果有,就取 d 以下的內容
以上好了後,在同一個專案中,沒有問題,不過跨了專案或者Domain之後,又會發生 jQuery 跨 Domain的問題,之前小喵有一篇【[WebAPI][CORS]使用 xdomain.js 實現 WebAPI 多組(Multiple) 跨 Domain】,有個透過 XDomain 的方式可以處理,因此借用這個方式,就可以輕鬆解決跨網域的問題,繼續提供另一個專案跨網域使用jQuery的 AJAX 來呼叫,相關的設定請參考那篇文章的說明。
末記
在環境上的不允許的狀況下,不得以用Web Service來處理,再次感恩好朋友 Donma 大大的文章,非常有幫助,這樣WebService也可以依據Client端的需求,做到傳回物件,就自動依據Client端需求傳回 XML 或 JSON 的格式。小喵這篇大致上與 Donma那篇幾乎相同,小喵改寫為 VB.NET 的方式撰寫,另外配合XDomain的方式來幾決 jQuery 的 Ajax 會有 Cross Domain 被拒絕的問題,相關資訊小喵做個筆記,以利未來有需要時的參考,也提供網路上的朋友們參考。
^_^
參考資料:
特別感恩當麻大的文章:
以下是簽名:
- 歡迎轉貼本站的文章,不過請在貼文主旨上加上【轉貼】,並在文章中附上本篇的超連結與站名【topcat姍舞之間的極度凝聚】,感恩大家的配合。
- 小喵大部分的文章會以小喵熟悉的語言VB.NET撰寫,如果您需要C#的Code,也許您可以試著用線上的工具進行轉換,這裡提供幾個參考
Microsoft MVP Visual Studio and Development Technologies (2005~2019/6) | topcat Blog:http://www.dotblogs.com.tw/topcat |