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的写法基本都大同小异,因此可以写成一个通用的例子,以后如遇到在脚本中需要跨域访问资源时便可以直接使用!代码记录于此,方便查阅。
JQuery Ajax通过Handler访问外部XML数据的代码
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@