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 相关文章推荐
关于恒等于(===)和非恒等于(!==)
Aug 20 Javascript
jQuery 方法大全方便学习参考
Feb 25 Javascript
使用jquery.upload.js实现异步上传示例代码
Jul 29 Javascript
JavaScript创建一个object对象并操作对象属性的用法
Mar 23 Javascript
jQuery事件绑定与解除绑定实现方法
Apr 15 Javascript
javascript匀速动画和缓冲动画详解
Oct 20 Javascript
利用js获取下拉框中所选的值
Dec 01 Javascript
JS实现十字坐标跟随鼠标效果
Dec 25 Javascript
完美解决axios跨域请求出错的问题
Feb 05 Javascript
使用js在layui中实现上传图片压缩
Jun 18 Javascript
ES6中Promise的使用方法实例总结
Feb 18 Javascript
JavaScript前后端JSON使用方法教程
Nov 23 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实现的连贯操作、链式操作实例
2014/07/08 PHP
PHP简单判断字符串是否包含另一个字符串的方法
2016/03/25 PHP
如何使用PHP给图片加水印
2016/10/12 PHP
PHP实现文件上传功能实例代码
2017/05/18 PHP
js前台判断开始时间是否小于结束时间
2012/02/23 Javascript
解决ExtJS在chrome或火狐中正常显示在ie中不显示的浏览器兼容问题
2013/01/11 Javascript
AngularJs根据访问的页面动态加载Controller的解决方案
2015/02/04 Javascript
JavaScript中pop()方法的使用教程
2015/06/09 Javascript
js实现文本框支持加减运算的方法
2015/08/19 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
2015/10/08 Javascript
每天一篇javascript学习小结(基础知识)
2015/11/10 Javascript
AngularJS基础 ng-paste 指令简单示例
2016/08/02 Javascript
request请求获取参数的实现方法(post和get两种方式)
2016/09/27 Javascript
微信小程序 HTTPS报错整理常见问题及解决方案
2016/12/14 Javascript
原生JS实现日历组件的示例代码
2017/09/22 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
Angular 利用路由跳转到指定页面的指定位置方法
2018/08/31 Javascript
详解关于React-Router4.0跳转不置顶解决方案
2019/05/10 Javascript
vue实现倒计时获取验证码效果
2020/04/17 Javascript
[45:25]完美世界DOTA2联赛循环赛 PXG vs IO 第一场 11.06
2020/11/09 DOTA
[01:38]完美世界DOTA2联赛PWL S3 集锦第四期
2020/12/21 DOTA
Python使用Supervisor来管理进程的方法
2015/05/28 Python
Python提取Linux内核源代码的目录结构实现方法
2016/06/24 Python
PyQt5每天必学之带有标签的复选框
2018/04/19 Python
python多线程同步之文件读写控制
2021/02/25 Python
NumPy统计函数的实现方法
2020/01/21 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
python使用smtplib模块发送邮件
2020/12/17 Python
如何让IE9以下版本(ie6/7/8)认识html5元素
2013/04/01 HTML / CSS
amaze ui 的使用详细教程
2020/08/19 HTML / CSS
Omio法国:全欧洲低价大巴、火车和航班搜索和比价
2017/11/13 全球购物
世界闻名的衬衫制造商:Savile Row Company
2018/07/30 全球购物
驻村工作先进事迹
2014/08/14 职场文书
查摆问题自我剖析材料
2014/08/18 职场文书
群众路线党员个人剖析材料
2014/10/08 职场文书
Python基本的内置数据类型及使用方法
2022/04/13 Python