ASP.NET JSON 代理、JSON Web 服务和 JavaScript 客户端(托管和使用 JSON 数据 - 同域和跨域)
本文包含一个 ASP.NET JSON 代理、一个简单的 JSON Web 服务以及用于在同域和跨域(使用动态脚本标签)场景下使用 JSON 数据的 JavaScript/jQuery 客户端。
1. 引言
- 本教程旨在实现双重目的
- 演示一个 ASP.NET JSON 代理,该代理从数据库(或 XML 文件/Web 服务)中提取数据并将其作为 JSON 提供,并且
- 使用 JavaScript(通过动态脚本标签)执行跨域请求。
- 为了使我们的文章更全面,我在本文(上方)的 jsonproxy.v2.zip 中包含了一个基本的 JSON Web 服务。这使我们能够了解如何使用 jQuery/JavaScript AJAX 使用 JSON Web 服务。这是同域 JSON 请求的更好方法。
- 我们的 JSON Web 服务根据我们请求的 Content Type 返回 JSON/XML 数据。
- 我们包含了一个名为“jsonServiceClient.htm”的客户端,用于使用我们的 Web 服务。
以上所有脚本都是独立的,可以在不同场景下使用。我们的 JSON 代理页面位于服务器上,可以使用 jQuery.ajax
或 jQuery.getJSON
方法在本地使用。
此解决方案结合了各种技术,为“托管”服务器端数据为 JSON 并使用 jQuery/JavaScript “使用”它提供了一种单一的方法。
要访问本地域上的数据,我们可以创建一个 ASP.NET Web 服务,这是一个更好、更简单的方法。然后,我们可以使用 JavaScript AJAX 或 jQuery.ajax 或 SOAP 调用我们的 Web 服务。(示例已附加到本文中。)
但是,对于跨域需求,我们的 JSON 代理可用于托管 JSON 数据。它还可以用于使用 XMLtoJson
类将任何第三方 XML(或任何 XML 数据库,如 feed)消耗掉,并以 JSON 而非 XML 的形式返回响应。
在本文中,我们尝试学习如何在跨域上“托管”和“使用”JSON 数据。
2. 背景
什么是 JSON 代理
我们的 JSON 代理在此处的工作方式与普通的 ASP.NET 代理页面相同,它们为我们提供来自任何本地或远程 Web 服务的数据。唯一区别是,我们的 JSON 代理返回 JSON 对象,因此我们更容易通过“<script src='out json proxy' />
”标签将我们的代理像普通的 JavaScript 一样调用。这使我们能够将代理用于跨域请求(因为 JavaScript 也可以从任何远程站点调用)。
我们引入的唯一技巧是 - 我们动态编写这些脚本标签。“<script src="our json proxy" />
”标签是在运行时生成并添加到我们网页的 DOM 的(使用附加的脚本)。这使我们能够将参数传递给代理页面,并根据查询字符串获得动态响应。
什么是跨域请求?
跨域请求是浏览器的一个问题。当一个网页(来自网站 www.abcd.com)尝试访问另一个网站(www.xyz.com)的内容时,就会发生这种情况。浏览器将其视为违反“同源策略”,并强制您仅使用原始网站(www.abcd.com)的内容,因为您的网页来自该网站。
有各种为跨域请求建议的变通方法。最简单的方法是在网站“www.abcd.com”上创建一个本地代理,该代理从(www.xyz.com)获取所需数据并将其原样返回给我们。因此,我们位于(www.abcd.com)的网页可以不违反“同源策略”而使用我们的本地代理页面,同时仍能获取来自其他网站(www.xyz.com)的数据。
当我们在 www.abcd.com 上无法创建代理时(例如,如果它是一个静态服务器),就会出现问题。在这种情况下,我们可能需要扩展位于(www.xyz.com)的数据门户,使其返回 JSON 对象格式的数据。由于 JavaScript 可以从任何位置嵌入,我们的 JSON 代理 - 尽管它位于服务器(www.xyz.com)上,但仍能为我们返回可用于我们网页(www.abcd.com)的适当数据。
3. 描述
服务器端
如前所述,我们的服务器端网页(JSON 代理)是我们想要展示的数据的 ASP.NET 代理。唯一的区别是 - 我们的 JSON 代理返回 JSON 对象而不是 XML,而 Web 服务返回 XML。如果我们使用相同的域,我们也可以编写 JSON Web 服务。对于跨域,传递参数并调用 Web 服务会变得有些困难。我们正在使用动态脚本标签来处理跨域请求。
我们的 JSON 代理位于服务器上。它通过从数据库加载,或通过消耗任何 XML Web 服务或 XML 文件数据库来为我们填充数据。
System.Collections.Generic.List<publication> returnList =
new System.Collections.Generic.List<publication>();
//This is our data access method. Supposed to fill our
//publication list from database
//We fill it using the below for loop for simplicity.
for (int tmp1 = 1; tmp1 <= 10; tmp1++)
{
//Some customized data - according to query string.
if ((strSearch.ToUpper() == "ODD") && (tmp1 % 2 == 0))
continue;
else if ((strSearch.ToUpper() == "EVEN") && (tmp1 % 2 != 0))
continue;
returnList.Add(new publication(tmp1, "Author" + tmp1.ToString(),
"Title" + tmp1.ToString(), "Remarks" + tmp1.ToString(), "Category" +
tmp1.ToString(), "Link" + tmp1.ToString()));
}
以下是我们如何使用上述代码加载 XML 并将其作为 JSON 返回。
//For Example
XmlDocument docXml = new XmlDocument();
docXml.Load("someLocation");
returnStr = XmlToJson.XmlToJSON(docXml);
我们使用 JavaScriptSerializer
来序列化我们的业务对象列表
System.Web.Script.Serialization.JavaScriptSerializer ser =
new System.Web.Script.Serialization.JavaScriptSerializer();
returnStr = ser.Serialize(returnList);
客户端
我们的客户端 HTML 页面包含用于创建动态标签的 JavaScript 代码
// Create the script tag
this.scriptObj = document.createElement("script");
// Add script object attributes
this.scriptObj.setAttribute("type", "text/javascript");
this.scriptObj.setAttribute("charset", "utf-8");
this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
this.scriptObj.setAttribute("id", this.scriptId);
上面创建的脚本标签按照以下函数添加到页面的 DOM 的 head
部分
JSONscriptRequest.prototype.addScriptTag = function () {
this.headLoc.appendChild(this.scriptObj);
....
}
然后,我们将我们的 JSON 处理函数“parseData
”附加到我们脚本的 onload
事件。 (请注意,此代码对于 Internet Explorer 和其他浏览器有所不同。相关的脚本是从不同博客收集的。)
//Here I am adding the script to onload event:-
this.scriptObj.onload= function() {parseData(jsonData);}
//and
var scriptTag = document.getElementById(this.scriptId);
scriptTag.onreadystatechange = function () {
if ( scriptTag.readyState === "complete" ) {
parseData(jsonData);
// Avoid memory leaks
//(and duplicate call to callback) in IE
scriptTag.onreadystatechange=null;
}//end if
}//end function;
4. 兴趣点
- 本文使用
- 注意:
- Internet Explorer 代码中有一个
alert("loading...")
。奇怪的是,一旦我插入警报,JavaScript 就能及时加载并正确显示 JSON 数据,但移除警报会导致 JSON 结果为空。除此之外,代码运行正常。
5. 历史记录
我将尝试更新代码,使其无需使用“loading...”警报即可用于 Internet Explorer。我曾尝试将脚本移到 head 部分,但没有帮助。