摘要:Ajax 在 Web 2.0 時代起著非常重要的作用,然而有時因為同源策略(SOP)(俗稱:跨域問題(cross domain)) 它的作用會受到限制。在本文中,將學習如何克服合作限制。本文以asmx方式搭建webservice作為測試用後端,給出完整的前後端調用解決方案、範例代碼。
關鍵詞: jquery ajax 跨域 webservice asmx cross-domain
0 問題分析
0.1 什麼是跨域問題。
越來越多的網站需要相互協作。例如,線上房屋租賃網站需要Google地圖的支援,以顯示特定租賃房屋的位置。為了滿足這樣的需求,已經出現了各種各樣的 mashup。mashup 是一種將不同供應商的資料或組件整合起來,使之更加有用或更使用者化的Web應用程式。Mashup(或協作功能)被認為是Web 2.0的重要組成部分。
出人意料的是,將非同步 JavaScript、XML (Ajax)和mashup結合起來並不容易。由於瀏覽器施加的安全限制,讓頁面上的不同小組件彼此之間相互連信比較麻煩。通常,您可以通過在伺服器端設定一個代理來解決此問題,該方法是不可擴充的。
問題詳情見圖:
0.2 問題解決思路
0.2.1 JSONP
JSONP 利用了 Web 頁面可以從任何源碼中下載指令碼的能力。但 JSONP 有兩個主要的限制:它與 Ajax 調用一樣沒有錯誤處理機制,並且指令碼標記請求要使用 Get method,其中對長度有所限制。此方法非本文討論重點,更多詳情請自行搜尋。
0.2.2 代理方法
思路請見圖
本文使用vs2013作為整合式開發環境(後簡稱IDE),理論上不受IDE限制。下文為測試專案,證明代理方案的可行性。
1 使用asmx建立asp.net webservice後端
1.1建立項目
VS2013->new project->Web Visual Studio2012->Asp.net Empty Web Application,取名“CrossDomain.Backend”,路徑隨意。
1.2 建立asmx
右擊“CrossDomain.Backend”項目->新增->新項目->web->asmx->新增按鈕
代碼如下:
using System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Web;using System.Web.Script.Services;using System.Web.Services;namespace CrossDomain.Backend{ /// <summary> /// Summary description for WebService1 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. [System.Web.Script.Services.ScriptService] public class WebService1 : System.Web.Services.WebService { [WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public int Sum(int a,int b) { Thread.Sleep(3000); return a+b; } }}
1.3 小結。
後端建立完畢,可以自行調試。
2 建立前端
2.1 建立項目
VS2013->new project->Web Visual Studio2012->Asp.net Empty Web Application,取名“CrossDomain.Frontend”,路徑隨意。
2.2 建立檔案架構
架構如下圖
2.3 index.html代碼如下:
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>ajaxCallAsmxSample</title> <script src="js/jquery-2.2.3.min.js" type="text/javascript"></script> <script src="js/jquery.blockUI.js" type="text/javascript"></script> <script src="js/index.js" type="text/javascript"></script></head><body> a:<input type="text" id="a"><br> b:<input type="text" id="b"><br> <button id="ButtonAjaxRequest">AjaxRequest</button><br> <label id="result"></label></body></html>
2.4 index.js代碼如下
"use strict";$(document).ready(function () { $("#ButtonAjaxRequest").click(AjaxCallAsmx);});var dtStart;var dtEnd;var administrativeLevelStr;var areaName;var backEndUrl = "http://localhost:5633/WebService1.asmx/Sum";var proxyUrl = "/DotNet/proxy.ashx?";function AjaxCallAsmx() { //顯示遮罩並阻塞使用者互動 $.blockUI({ message: '<h1><img src="images/loading.gif" .> Just a moment...</h1>' }); $.ajax({ type: "POST", url: proxyUrl+backEndUrl, data: { a: $("#a").val(), b: $("#b").val() }, dataType: "xml", //asmx預設返回xml格式資料 success: function (data, statusText, jqXHR) { var x = $.parseXML(jqXHR.responseText); var c = x.childNodes[0].textContent; $("#result").html(c); //去除遮罩 $.unblockUI(); } });}
請注意:
1 如果此處不使用代理(proxy),將出現常見的“跨域錯誤”,此處對錯誤案例不做列舉,相信查閱到此文的讀者都遇到過類似問題。
2 主要起到代理作用的是DotNet/proxy.ashx,和proxy.config檔案;建議將這兩個檔案放在同一檔案夾下。此檔案最新版詳見github,下載地址:https://github.com/Esri/resource-proxy。作者提供了:dotnet/java/php三種主流版本。
3 總結
文本對跨域問題的原因、分析、解決思路、思路實踐案例進行了整理。留以方便讀者少走彎路,同時自己備查。
4 參考文獻
Wang Jiaye, Hu Changchun;利用用戶端解決方案改進跨域通訊; https://www.ibm.com/developerworks/cn/web/wa-crossdomaincomm/
JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls; https://developer.yahoo.com/javascript/howto-proxy.html
本範例代碼下載地址:http://download.csdn.net/detail/fanrong1985/9513581