JQuery Ajax通过Handler访问外部XML数据的代码


Posted in Javascript onJune 01, 2010

JQuery的使用非常简单,我们只需要从其官方网站上下载一个脚本文件并引用到页面上即可,然后你就可以在你的脚本代码中任意使用JQuery提供的对象和功能了。

在JQuery中使用Ajax方法异步获取服务器资源非常简单,读者可以参考其官方网站上提供的例子http://api.jquery.com/category/ajax/。当然,作为客户端脚本,JQuery也会遇到跨域访问资源的问题,什么是跨域访问呢?简单来说就是脚本所要访问的资源属于网站外部的资源,脚本所在的位置和资源所在的位置不在同一区域。默认情况下,浏览器是不允许直接进行资源的跨域访问的,除非客户端浏览器有设置,否则访问会失败。在这种情况下,我们一般都会采用在服务器端使用handler来解决,就是说在脚本和资源之间建立一个桥梁,让脚本访问本站点内的handler,通过handler去访问外部资源。这个是非常普遍的做法,而且操作起来也非常简单,因为会经常使用到,所以在此记录一下,方便日后使用!

首先需要在网站中创建一个handler,在Visual Studio中新建一个Generic Handler文件,拷贝下面的代码:

<%@ WebHandler Language="C#" Class="WebApplication1.Stock" %> 
namespace WebApplication1 
{ 
using System; 
using System.IO; 
using System.Net; 
using System.Text; 
using System.Web; 
using System.Collections.Generic; 
using System.Linq; 
/// <summary> 
/// Asynchronous HTTP handler for rendering external xml source. 
/// </summary> 
public class Stock : System.Web.IHttpAsyncHandler 
{ 
private static readonly SafeList safeList = new SafeList(); 
private HttpContext context; 
private WebRequest request; 
/// <summary> 
/// Gets a value indicating whether the HTTP handler is reusable. 
/// </summary> 
public bool IsReusable 
{ 
get { return false; } 
} 
/// <summary> 
/// Verify that the external RSS feed is hosted by a server on the safe list 
/// before making an asynchronous HTTP request for it. 
/// </summary> 
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) 
{ 
var u = context.Request.QueryString["u"]; 
var uri = new Uri(u); 
if (safeList.IsSafe(uri.DnsSafeHost)) 
{ 
this.context = context; 
this.request = HttpWebRequest.Create(uri); 
return this.request.BeginGetResponse(cb, extraData); 
} 
else 
{ 
throw new HttpException(204, "No content"); 
} 
} 
/// <summary> 
/// Render the response from the asynchronous HTTP request for the RSS feed 
/// using the response's Expires and Last-Modified headers when caching. 
/// </summary> 
public void EndProcessRequest(IAsyncResult result) 
{ 
string expiresHeader; 
string lastModifiedHeader; 
string rss; 
using (var response = this.request.EndGetResponse(result)) 
{ 
expiresHeader = response.Headers["Expires"]; 
lastModifiedHeader = response.Headers["Last-Modified"]; 
using (var stream = response.GetResponseStream()) 
using (var reader = new StreamReader(stream, true)) 
{ 
rss = reader.ReadToEnd(); 
} 
} 
var output = this.context.Response; 
output.ContentEncoding = Encoding.UTF8; 
output.ContentType = "text/xml;"; // "application/rss+xml; charset=utf-8"; 
output.Write(rss); 
var cache = output.Cache; 
cache.VaryByParams["u"] = true; 
DateTime expires; 
var hasExpires = DateTime.TryParse(expiresHeader, out expires); 
DateTime lastModified; 
var hasLastModified = DateTime.TryParse(lastModifiedHeader, out lastModified); 
cache.SetCacheability(HttpCacheability.Public); 
cache.SetOmitVaryStar(true); 
cache.SetSlidingExpiration(false); 
cache.SetValidUntilExpires(true); 
DateTime expireBy = DateTime.Now.AddHours(1); 
if (hasExpires && expires.CompareTo(expireBy) <= 0) 
{ 
cache.SetExpires(expires); 
} 
else 
{ 
cache.SetExpires(expireBy); 
} 
if (hasLastModified) 
{ 
cache.SetLastModified(lastModified); 
} 
} 
/// <summary> 
/// Do not process requests synchronously. 
/// </summary> 
public void ProcessRequest(HttpContext context) 
{ 
throw new InvalidOperationException(); 
} 
} 
/// <summary> 
/// Methods for matching hostnames to a list of safe hosts. 
/// </summary> 
public class SafeList 
{ 
/// <summary> 
/// Hard-coded list of safe hosts. 
/// </summary> 
private static readonly IEnumerable<string> hostnames = new string[] 
{ 
"cnblogs.com", 
"msn.com", 
"163.com", 
"csdn.com" 
}; 
/// <summary> 
/// Prefix each safe hostname with a period. 
/// </summary> 
private static readonly IEnumerable<string> dottedHostnames = 
from hostname in hostnames 
select string.Concat(".", hostname); 
/// <summary> 
/// Tests if the <paramref name="hostname" /> matches exactly or ends with a 
/// hostname from the safe host list. 
/// </summary> 
/// <param name="hostname">Hostname to test</param> 
/// <returns>True if the hostname matches</returns> 
public bool IsSafe(string hostname) 
{ 
return MatchesHostname(hostname) || MatchesDottedHostname(hostname); 
} 
/// <summary> 
/// Tests if the <paramref name="hostname" /> ends with a hostname from the 
/// safe host list. 
/// </summary> 
/// <param name="hostname">Hostname to test</param> 
/// <returns>True if the hostname matches</returns> 
private static bool MatchesDottedHostname(string hostname) 
{ 
return dottedHostnames.Any(host => hostname.EndsWith(host, StringComparison.InvariantCultureIgnoreCase)); 
} 
/// <summary> 
/// Tests if the <paramref name="hostname" /> matches exactly with a hostname 
/// from the safe host list. 
/// </summary> 
/// <param name="hostname">Hostname to test</param> 
/// <returns>True if the hostname matches</returns> 
private static bool MatchesHostname(string hostname) 
{ 
return hostnames.Contains(hostname, StringComparer.InvariantCultureIgnoreCase); 
} 
} 
}

我给出的例子中是想通过Ajax异步取得msn站点上微软的股票信息,其外部资源地址为http://money.service.msn.com/StockQuotes.aspx?symbols=msft,我们在页面上这样使用JQuery api通过Handler来访问数据:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title></title> 
<script type="text/javascript" src="jquery-1.3.2.min.js"></script> 
</head> 
<body> 
<div id="con"> 
<span id="loader">loading...</span> 
</div> 
<script type="text/javascript"> 
function getData() { 
$("#loader").ajaxStart(function() { 
$(this).show(); 
}); 
$("#loader").ajaxComplete(function() { 
$(this).hide(); 
}); 
$.ajax({ 
type: "GET", 
url: "Stock.ashx?u=http://money.service.msn.com/StockQuotes.aspx?symbols=msft", 
dataType: "xml", 
success: function(data) { 
var last = ""; 
var change = ""; 
var percentchange = ""; 
var volume = ""; 
var cap = ""; 
var yearhigh = ""; 
var yearlow = ""; 
$(data).find('ticker').each(function() { 
last = $(this).attr('last'); 
change = $(this).attr('change'); 
percentchange = $(this).attr('percentchange'); 
volume = $(this).attr('volume'); 
cap = $(this).attr('marketcap'); 
yearhigh = $(this).attr('yearhigh'); 
yearlow = $(this).attr('yearlow'); 
document.getElementById('con').innerHTML = '<span>name:' + last + '    high:' + volume + '    low:' + cap + '</span>'; 
}) 
} 
}); 
} 
$(window).load(getData); 
</script> 
</body> 
</html>

下面是实现的结果:
name:25.8 high:67,502,221 low:$226,107,039,514

Handler的写法基本都大同小异,因此可以写成一个通用的例子,以后如遇到在脚本中需要跨域访问资源时便可以直接使用!代码记录于此,方便查阅。

Javascript 相关文章推荐
javascript 多种搜索引擎集成的页面实现代码
Jan 02 Javascript
jquery 学习之二 属性(类)
Nov 25 Javascript
gridview生成时如何去掉style属性中的border-collapse
Sep 30 Javascript
在JavaScript中模拟类(class)及类的继承关系
May 20 Javascript
JavaScript利用fetch实现异步请求的方法实例
Jul 26 Javascript
jQuery中复合选择器简单用法示例
Mar 31 jQuery
在vue项目中使用md5加密的方法
Sep 14 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
May 09 Javascript
微信小程序动画组件使用解析,类似vue,且更强大
Aug 01 Javascript
JS apply用法总结和使用场景实例分析
Mar 14 Javascript
小程序实现简单语音聊天的示例代码
Jul 24 Javascript
JavaScript声明变量和数据类型的转换
Apr 12 Javascript
一些经常会用到的Javascript检测函数
May 31 #Javascript
jquery URL参数判断,确定菜单样式
May 31 #Javascript
javascript 全等号运算符使用说明
May 31 #Javascript
js的逻辑运算符 ||
May 31 #Javascript
避免 showModalDialog 弹出新窗体的原因分析
May 31 #Javascript
判断目标是否是window,document,和拥有tagName的Element的代码
May 31 #Javascript
js 数组的for循环到底应该怎么写?
May 31 #Javascript
You might like
域名查询代码公布
2006/10/09 PHP
几个学习PHP的网址
2006/11/25 PHP
PHP面向对象分析设计的经验原则
2008/09/20 PHP
win7下memCache的安装过程(具体操作步骤)
2013/06/28 PHP
合并ThinkPHP配置文件以消除代码冗余的实现方法
2014/07/22 PHP
PHP使用pdo实现事务处理操作示例
2018/09/05 PHP
PHP实现本地图片转base64格式并上传
2020/05/29 PHP
父窗口获取弹出子窗口文本框的值
2006/06/27 Javascript
Mootools 1.2教程 Fx.Morph、Fx选项和Fx事件
2009/09/15 Javascript
jQuery库与其他JS库冲突的解决办法
2010/02/07 Javascript
asp.net 30分钟掌握无刷新 Repeater
2011/09/16 Javascript
javascript轻松实现当鼠标移开时已弹出子菜单自动消失
2013/12/29 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
js实现具有高亮显示效果的多级菜单代码
2015/09/01 Javascript
纯js实现动态时间显示
2020/09/07 Javascript
详解在Vue中如何使用axios跨域访问数据
2017/07/07 Javascript
vue父组件中获取子组件中的数据(实例讲解)
2017/09/27 Javascript
js中document.write和document.writeln的区别
2018/03/11 Javascript
Angular使用动态加载组件方法实现Dialog的示例
2018/05/11 Javascript
12个提高JavaScript技能的概念(小结)
2019/05/09 Javascript
vue+moment实现倒计时效果
2019/08/26 Javascript
vue 需求 data中的数据之间的调用操作
2020/08/05 Javascript
深入分析在Python模块顶层运行的代码引起的一个Bug
2014/07/04 Python
python实现的jpg格式图片修复代码
2015/04/21 Python
python实现二维码扫码自动登录淘宝
2016/12/27 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
Python短信轰炸的代码
2020/03/25 Python
解决tensorflow 释放图,删除变量问题
2020/06/23 Python
台湾饭店和机票预订网站:Expedia台湾
2016/08/05 全球购物
马来西亚时装购物网站:ZALORA马来西亚
2017/03/14 全球购物
自我评价怎么写正确呢?
2013/12/02 职场文书
2014年国庆节演讲稿精选范文1500字
2014/09/25 职场文书
骨干教师个人总结
2015/02/11 职场文书
幼儿园教研工作总结2015
2015/05/12 职场文书
大学生活委员竞选稿
2015/11/21 职场文书
关于社会实践的心得体会(2016最新版)
2016/01/25 职场文书