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

  • 相关阅读:
    https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic net::ERR_CONNECTION_TIMED_OUT问题解决
    nginx 下使用 bootstrap 字体的问题
    php中函数preg_match或preg_match_all 第三个参数$match的解释
    thinkphp中 volist循环的 mod取值的问题
    mysql中sql注入的随笔
    修改mysql的字符集和默认存储引擎
    使用Marsedit在博客园写作
    Server Tomcat v7.0 Server at localhost failed to start.临时解决办法
    【转】Linux Mint 17.2 gedit中文乱码
    HashMap和HashSet
  • 原文地址:https://www.cnblogs.com/jaxu/p/1748676.html
Copyright © 2020-2023  润新知