JQuery Ajax通过Handler访问外部XML数据

  JQuery是一款不错的Javascript脚本框架,相信园子里的很多朋友对它都不陌生,我们在开发Web应用程序时难免会使用到Javascript脚本,而使用一款不错的脚本框架将会大大节省我们的开发时间, 并可以毫不费力地实现很多非常酷的效果。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    ' &nbsp;&nbsp;&nbsp;&nbsp;high: '    volume    ' &nbsp;&nbsp;&nbsp;&nbsp;low: '    cap    ' </span> ' ;
                    })
                }
            });
        }

        $(window).load(getData);

    
</ script >

</ body >
</ html >

   下面是实现的结果:

name:25.8    high:67,502,221    low:$226,107,039,514

  Handler的写法基本都大同小异,因此可以写成一个通用的例子,以后如遇到在脚本中需要跨域访问资源时便可以直接使用!代码记录于此,方便查阅。


更多专业前端知识,请上 【猿2048】www.mk2048.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值