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 相关文章推荐
js控制input输入字符解析
Dec 27 Javascript
手机号码,密码正则验证
Sep 04 Javascript
Vue computed计算属性的使用方法
Jul 14 Javascript
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
Oct 15 Javascript
Three.js基础学习教程
Nov 16 Javascript
微信小程序slider组件使用详解
Jan 31 Javascript
深入剖析Express cookie-parser中间件实现示例
Feb 01 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
Oct 27 Javascript
jQuery实现动态操作table行
Nov 23 jQuery
antdesign-vue结合sortablejs实现两个table相互拖拽排序功能
Jan 08 Vue.js
使用vue-element-admin框架从后端动态获取菜单功能的实现
Apr 29 Vue.js
JS Canvas接口和动画效果大全
Apr 29 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 利用Mail_MimeDecode类提取邮件信息示例
2014/01/26 PHP
php定时计划任务与fsockopen持续进程实例
2014/05/23 PHP
PHP执行SQL文件并将SQL文件导入到数据库
2015/09/17 PHP
Yii中srbac权限扩展模块工作原理与用法分析
2016/07/14 PHP
php 判断页面或图片是否经过gzip压缩的方法
2017/04/05 PHP
Laravel使用swoole实现websocket主动消息推送的方法介绍
2019/10/20 PHP
Yii使用EasyWechat实现小程序获取用户的openID的方法
2020/04/29 PHP
iframe 上下滚动条如何默认在下方实现原理
2012/12/10 Javascript
解决js下referer兼容各大浏览器的方法
2014/11/03 Javascript
jQuery中on()方法用法实例
2015/01/19 Javascript
webpack分离css单独打包的方法
2018/06/12 Javascript
jQuery实现基本隐藏与显示效果的方法详解
2018/09/05 jQuery
开发一个Parcel-vue脚手架工具(详细步骤)
2018/09/22 Javascript
Vue中的methods、watch、computed的区别
2018/11/26 Javascript
JQuery Ajax执行跨域请求数据的解决方案
2018/12/10 jQuery
JS寄快递地址智能解析的实现代码
2020/07/16 Javascript
微信小程序换肤功能实现代码(思路详解)
2020/08/25 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
Python用GET方法上传文件
2015/03/10 Python
Python实现批量将word转html并将html内容发布至网站的方法
2015/07/14 Python
Django视图之ORM数据库查询操作API的实例
2017/10/27 Python
Django学习笔记之ORM基础教程
2018/03/27 Python
Flask教程之重定向与错误处理实例分析
2019/08/01 Python
Python编译成.so文件进行加密后调用的实现
2019/12/23 Python
TFRecord格式存储数据与队列读取实例
2020/01/21 Python
在python中list作函数形参,防止被实参修改的实现方法
2020/06/05 Python
Python获取android设备cpu和内存占用情况
2020/11/15 Python
conda安装tensorflow和conda常用命令小结
2021/02/20 Python
详解HTML5中表单验证的8种方法介绍
2016/12/19 HTML / CSS
最美护士演讲稿
2014/08/27 职场文书
创先争优活动心得体会
2014/09/04 职场文书
2015年大学生实习评语
2015/03/25 职场文书
《窃读记》教学反思
2016/02/18 职场文书
详解Spring事件发布与监听机制
2021/06/30 Java/Android
教你部署vue项目到docker
2022/04/05 Vue.js
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL