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 相关文章推荐
jquery1.4.2 for Visual studio 2010 模板文件
Jul 14 Javascript
杨氏矩阵查找的JS代码
Mar 21 Javascript
JS判断数组中是否有重复值得三种实用方法
Aug 16 Javascript
JQuery中DOM加载与事件执行实例分析
Jun 13 Javascript
日常收集整理的JavaScript常用函数方法
Dec 10 Javascript
详解JavaScript对象类型
Jun 16 Javascript
jQuery插件ajaxFileUpload使用实例解析
Oct 19 Javascript
使用webpack3.0配置webpack-dev-server教程
May 29 Javascript
基于Vue 服务端Cookies删除的问题
Sep 21 Javascript
Vue开发之封装上传文件组件与用法示例
Apr 25 Javascript
vue实现购物车列表
Jun 30 Javascript
react中useState使用:如何实现在当前表格直接更改数据
Aug 05 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 多维数组排序实现代码
2009/08/05 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
2014/07/04 PHP
php curl请求信息和返回信息设置代码实例
2015/04/27 PHP
PHP图像识别技术原理与实现
2016/10/27 PHP
phpcms配置列表页以及获得文章发布时间
2017/07/04 PHP
dojo学习第二天 ajax异步请求之绑定列表
2011/08/29 Javascript
jquery实现简单的拖拽效果实例兼容所有主流浏览器(优化篇)
2013/06/28 Javascript
JavaScript计算字符串中每个字符出现次数的小例子
2013/07/02 Javascript
angularJS 中$attrs方法使用指南
2015/02/09 Javascript
jQuery简单设置文本框回车事件的方法
2016/08/01 Javascript
浅谈时钟的生成(js手写简洁代码)
2016/08/20 Javascript
微信小程序 教程之WXML
2016/10/18 Javascript
Javascript中的async awai的用法
2017/05/17 Javascript
JavaScript设计模式之策略模式详解
2017/06/09 Javascript
Angular整合zTree的示例代码
2018/01/24 Javascript
JS获取url参数,JS发送json格式的POST请求方法
2018/03/29 Javascript
jQuery实现侧边栏隐藏与显示的方法详解
2018/12/22 jQuery
深度了解vue.js中hooks的相关知识
2019/06/14 Javascript
vue前后分离调起微信支付
2019/07/29 Javascript
vue页面加载时的进度条功能(实例代码)
2020/01/13 Javascript
ant-design-vue按需加载的坑的解决
2020/05/14 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
详解vue中在父组件点击按钮触发子组件的事件
2020/11/13 Javascript
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
2017/06/27 Python
Python装饰器原理与用法分析
2018/04/30 Python
python实现旋转和水平翻转的方法
2018/10/25 Python
Python可变对象与不可变对象原理解析
2020/02/25 Python
解析Python 偏函数用法全方位实现
2020/06/26 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
Python request中文乱码问题解决方案
2020/09/17 Python
斯凯奇美国官网:SKECHERS美国
2016/08/20 全球购物
加拿大时尚少女服装品牌:Garage
2016/10/10 全球购物
财务会计专业推荐信
2013/11/30 职场文书
2015元旦联欢晚会结束语
2014/12/14 职场文书
学校食堂食品安全承诺书
2015/04/29 职场文书
个人求职意向书
2015/05/11 职场文书