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 实现父窗口引用弹出窗口的值的脚本
Aug 07 Javascript
JavaScript获取和设置CheckBox状态的简单方法
Jul 05 Javascript
将HTML的左右尖括号等转义成实体形式的两种实现方式
May 04 Javascript
jqGrid中文文档之选项设置
Dec 02 Javascript
分享javascript计算时间差的示例代码
Mar 19 Javascript
详解angularjs 关于ui-router分层使用
Jun 12 Javascript
Angular 2父子组件数据传递之局部变量获取子组件其他成员
Jul 04 Javascript
Vue ElementUi同时校验多个表单(巧用new promise)
Jun 06 Javascript
jQuery实现的五星点评功能【案例】
Feb 18 jQuery
vue项目首屏打开速度慢的解决方法
Mar 31 Javascript
JavaScript对象原型链原理详解
Feb 05 Javascript
Vue项目vscode 安装eslint插件的方法(代码自动修复)
Apr 15 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
PHP操作mysql函数详解,mysql和php交互函数
2011/05/19 PHP
PHP函数in_array()使用详解
2014/08/20 PHP
PHP中使用php5-ffmpeg撷取视频图片实例
2015/01/07 PHP
把textarea中字符串里含有的回车换行替换成&amp;lt;br&amp;gt;的javascript代码
2007/04/20 Javascript
JavaScript 常见对象类创建代码与优缺点分析
2009/12/07 Javascript
详解BootStrap中Affix控件的使用及保持布局的美观的方法
2016/07/08 Javascript
JavaScript DOM节点操作方法总结
2016/08/23 Javascript
JS实现提交表单前的数字及邮箱校检功能
2017/11/13 Javascript
微信小程序使用map组件实现获取定位城市天气或者指定城市天气数据功能
2019/01/22 Javascript
JS module的导出和导入的实现代码
2019/02/25 Javascript
Vue实现简易计算器
2020/02/25 Javascript
微信小程序实现页面监听自定义组件的触发事件
2020/11/01 Javascript
js实现纯前端压缩图片
2020/11/16 Javascript
[01:44]剑指西雅图 展望TI之CIS战队专访
2014/06/25 DOTA
[01:01]青春无憾,一战成名——DOTA2全国高校联赛开启
2018/02/25 DOTA
[01:38]女王驾到——至宝魔廷新尊技能&特效展示
2020/06/16 DOTA
python实现百度关键词排名查询
2014/03/30 Python
python实现Decorator模式实例代码
2018/02/09 Python
python实现简易通讯录修改版
2018/03/13 Python
python3.x实现发送邮件功能
2018/05/22 Python
python按比例随机切分数据的实现
2019/07/11 Python
wxpython布局的实现方法
2019/11/01 Python
python关闭占用端口方式
2019/12/17 Python
python将dict中的unicode打印成中文实例
2020/05/11 Python
Python+pyftpdlib实现局域网文件互传
2020/08/24 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
2020/09/30 Python
Chinti & Parker官网:奢华羊绒女装和创新针织设计
2021/01/01 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
第二层交换机和路由器的区别?第三层交换机和路由器的区别?
2013/05/23 面试题
你在项目中用到了xml技术的哪些方面?如何实现的?
2014/01/26 面试题
怀念母亲教学反思
2014/04/28 职场文书
2014年教师党员自我评价范文
2014/09/22 职场文书
2017大学生寒假社会实践心得体会
2016/01/14 职场文书
Django使用channels + websocket打造在线聊天室
2021/05/20 Python
JS创建或填充任意长度数组的小技巧汇总
2021/10/24 Javascript
SpringCloud Function SpEL注入漏洞分析及环境搭建
2022/04/08 Java/Android