我们于进展Web程序支付时,为了进行搜引擎优化(SEO),往往得针对web的访问地址进行优化,如用http://localhost/Default.aspx?tab=performance修改为http://localhost/Default_performance.aspx,后一个地方能够更好地为摸引擎搜索到,从而达到了找引擎优化的目的。微软来一个开源类库URLRewriter得死有利地实现url改写,通过部署在web.config文件中之映射表将用户的恳求重定向到具体的页面中,我在“运用URLRewriter进行URL重写失效”一软遭遇详细介绍了怎样采取这类库,该类库是经过asp.net的httpmodules或httphandles来执行的,但若网站的宿主服务器不支持asp.net
httpmodules和httphandles,则该意义就失效了,这时我们得以经过global中之application_beginrequest事件来展开url重定向。本文在URLRewriter类库的功底及进行了改良,并让起了一个相对完好的解决方案。

  我们的改良是确立在URLRewriter的根底之上的,所以URLRewriter原有的东西要会因此,我们且得一直用过来,当然,不好的物一旦摒弃!

  URLRewriter的映射表是一直写以web.config文件中之,要让web.config能认识别映射表,必须在configSections节中上加section,告诉程序如何正确分析web.config中不为识别的情节,如原来URLRewriter就待在web.config中补充加<section name=”RewriterConfig”
type=”URLRewriter.Config.RewriterConfigSerializerSectionHandler,
URLRewriter”/>。我看是点子并无好,首先你得单独去编写一个类库来解析xml,并当web.config中展开布置,我们完全可以看看去就无异步。url的映射表可以单独写及一个xml文件中,当程序运行时拿xml加载到应用程序缓存中,并设置一个缓存文件指项,这样以管理员修改完映射表后即便足以立即见效。

  另外自想支持url的双向改写,即上面提到的点滴个url,当用户输入第二单url时程序会将请发送至第一只url,但浏览器被形的url不移;当用户输入第一个url时,自动跳反到第二单url,此时浏览器中展示的是次独url,但是要仍然是首先个url。听起是勿是起硌绕啊?没关系,其实也格外粗略,基本的需要就是客户原本网站受到之群页面在顾时犹牵动了重重参数,做url改写时还更换成新的url了,这时旧的url仍然可就此,客户想的便是当输入原来老的url时能半自动跳反至新的url。这个就是url的双向改写!这片种植方法得以独家通过Context.RewritePath()和Context.Response.Redirect()方法来落实,下面我们来拘禁现实的贯彻。

  首先是映射表的兑现。我当URLRewriter原有映射表的根底及开了几许改观,就是为ReWriterRule添加了一个IsDirect属性,该属性可选,默认值为False,当值为真时如果用户要的url匹配则会开展跳转,否则只是进行呼吁映射。 

<?xml version=”1.0″?>
<ReWriterConfig xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema"&gt;
  <Rules>
    <ReWriterRule>
      <LookFor>~/Default_(\w+)\.aspx</LookFor>
      <SendTo>~/Default.aspx?tab=$1</SendTo>
    </ReWriterRule>
    <ReWriterRule IsDirect=”true”>
      <LookFor>~/Default\.aspx\?tab=(\w+)</LookFor>
      <SendTo>~/Default_$1.aspx</SendTo>
    </ReWriterRule>
  </Rules>
</ReWriterConfig>

  该映射表支持正则表达式,下面是相应之实体类,用来进展反序列化。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace URLRewriterTest
{
    [Serializable]
    public class ReWriterConfig
    {
        public ReWriterRule[] Rules;
    }

    [Serializable]
    public class ReWriterRule
    {
        private bool _isRedirect = false;

        [System.Xml.Serialization.XmlAttribute(“IsDirect”)]
        public bool IsRedirect
        {
            get { return _isRedirect; }
            set { this._isRedirect = value; }
        }
        public string LookFor { get; set; }
        public string SendTo { get; set; }
    }
}

  下面这类用来抱映射表,当次第一不好运行时见面用映射表反序列化的结果放到全局应用程序缓存中。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Serialization;
using System.IO;
using System.Web.Caching;

namespace URLRewriterTest
{
    public class ReWriterConfiguration
    {
        public static ReWriterConfig GetConfig(string filename)
        {
            if (HttpContext.Current.Cache[“RewriterConfig”] == null)
            {
                ReWriterConfig config = null;
                // Create an instance of the XmlSerializer specifying type and namespace.   
                XmlSerializer serializer = new XmlSerializer(typeof(ReWriterConfig));

                // A FileStream is needed to read the XML document.   
                using (Stream reader = new FileStream(filename, FileMode.Open))
                {
                    // Declare an object variable of the type to be deserialized.   
                    config = (ReWriterConfig)serializer.Deserialize(reader);
                }
                HttpContext.Current.Cache.Insert(“RewriterConfig”, config, new CacheDependency(filename));
            }
            return (ReWriterConfig)HttpContext.Current.Cache[“RewriterConfig”];     
        }
    }
}

  我们还是要原URLRewriter类库中之ReWriterUtils类中的方式,不过针对中RewriteUrl方法开展了好几粗之转移,增加了一个isRedirect参数,用来控制是实行Context.RewritePath()方法或者Context.Response.Redirect()方法,下面是源代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace URLRewriterTest
{
    public class ReWriterUtils
    {
        /// <summary>
        /// Rewrite’s a URL using <b>HttpContext.RewriteUrl()</b>.
        /// </summary>
        /// <param name=”context”>The HttpContext object to rewrite the URL to.</param>
        /// <param name=”isRedirect”>Redirect or rewrite path.</param>
        /// <param name=”sendToUrl”>The URL to rewrite to.</param>
        public static void RewriteUrl(HttpContext context, string sendToUrl, bool isRedirect)
        {
            string x, y;
            RewriteUrl(context, sendToUrl, isRedirect, out x, out y);
        }

        /// <summary>
        /// Rewrite’s a URL using <b>HttpContext.RewriteUrl()</b>.
        /// </summary>
        /// <param name=”context”>The HttpContext object to rewrite the URL to.</param>
        /// <param name=”sendToUrl”>The URL to rewrite to.</param>
        /// <param name=”isRedirect”>Redirect or rewrite path.</param>
        /// <param name=”sendToUrlLessQString”>Returns the value of sendToUrl stripped of the querystring.</param>
        /// <param name=”filePath”>Returns the physical file path to the requested page.</param>
        public static void RewriteUrl(HttpContext context, string sendToUrl, bool isRedirect, out string sendToUrlLessQString, out string filePath)
        {
            // see if we need to add any extra querystring information
            if (context.Request.QueryString.Count > 0)
            {
                if (sendToUrl.IndexOf(‘?’) != -1)
                    sendToUrl += “&” + context.Request.QueryString.ToString();
                else
                    sendToUrl += “?” + context.Request.QueryString.ToString();
            }

            // first strip the querystring, if any
            string queryString = String.Empty;
            sendToUrlLessQString = sendToUrl;
            if (sendToUrl.IndexOf(‘?’) > 0)
            {
                sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf(‘?’));
                queryString = sendToUrl.Substring(sendToUrl.IndexOf(‘?’) + 1);
            }

            // grab the file’s physical path
            filePath = string.Empty;
            filePath = context.Server.MapPath(sendToUrlLessQString);

            if (isRedirect)
            {
                // redirect the pathXML 1
                context.Response.Redirect(“~/” + sendToUrlLessQString);
            }
            else
            {
                // rewrite the pathXML 2
                context.RewritePath(“~/” + sendToUrlLessQString, String.Empty, queryString);
            }

            // NOTE!  The above RewritePath() overload is only supported in the .NET Framework 1.1
            // If you are using .NET Framework 1.0, use the below form instead:
            // context.RewritePath(sendToUrl);
        }

        /// <summary>
        /// Converts a URL into one that is usable on the requesting client.
        /// </summary>
        /// <remarks>Converts ~ to the requesting application path.  Mimics the behavior of the 
        /// <b>Control.ResolveUrl()</b> method, which is often used by control developers.</remarks>
        /// <param name=”appPath”>The application path.</param>
        /// <param name=”url”>The URL, which might contain ~.</param>
        /// <returns>A resolved URL.  If the input parameter <b>url</b> contains ~, it is replaced with the
        /// value of the <b>appPath</b> parameter.</returns>
        public static string ResolveUrl(string appPath, string url)
        {
            if (url.Length == 0 || url[0] != ‘~’)
                return url;        // there is no ~ in the first character position, just return the url
            else
            {
                if (url.Length == 1)
                    return appPath;  // there is just the ~ in the URL, return the appPath
                if (url[1] == ‘/’ || url[1] == ‘\\’)
                {
                    // url looks like ~/ or ~\
                    if (appPath.Length > 1)
                        return appPath + “/” + url.Substring(2);
                    else
                        return “/” + url.Substring(2);
                }
                else
                {
                    // url looks like ~something
                    if (appPath.Length > 1)
                        return appPath + “/” + url.Substring(1);
                    else
                        return appPath + url.Substring(1);
                }
            }
        }
    }
}

  最后便是编辑Global中的Application_BeginRequest事件了,在原来URLRewriter的基本功及有点作改。

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string requestedPath = Request.RawUrl.ToString();

    // get the configuration rules
    string filename = Context.Server.MapPath(“.”) + “//ReWriterRules.xml”;
    ReWriterConfig rules = ReWriterConfiguration.GetConfig(filename);

    // iterate through each ruleXML 3
    for (int i = 0; i < rules.Rules.Length; i++)
    {
        // get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory)
        string lookFor = “^” + ReWriterUtils.ResolveUrl(Context.Request.ApplicationPath, rules.Rules[i].LookFor) + “$”;

        // Create a regex (note that IgnoreCase is setXML 4)
        Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);

        // See if a match is found
        if (re.IsMatch(requestedPath))
        {
            // match found – do any replacement needed
            string sendToUrl = ReWriterUtils.ResolveUrl(Context.Request.ApplicationPath, re.Replace(requestedPath, rules.Rules[i].SendTo));

            // Rewrite or redirect the URL
            ReWriterUtils.RewriteUrl(Context, sendToUrl, rules.Rules[i].IsRedirect);
            break;        // exit the for loop
        }
    }
}

  好了,大功告成!使用方面的映射表,当您输入http://localhost/Default_performance.aspx常常访问正常,事实上Default_背后可以增长其它字符,这些字符都以当Default.aspx页面tab参数的值。同时,当你输入http://localhost/Default.aspx?tab=performance时页面会自动跳反到前边一个url,tab参数的价值将为看成url的平有的。

URLRewriterTest.rar下载

相关文章

网站地图xml地图