代码改变世界

折腾一个自己的UrlRewrite

2011-08-16 21:58  飞魚  阅读(2042)  评论(1编辑  收藏  举报

UrlRewrite一般都是在web.config里配置访问规则在路由到实际页面,所以先实现自定义节点信息读取,这里我定义了俩个类,贴出详细信息

namespace UrlRewrite
{
    public class UrlRewriteConfigGroup : ConfigurationSectionGroup
    {
        [ConfigurationProperty("rules")]
        public UrlRewriteConfig Rules
        {
            get
            {
                return (UrlRewriteConfig)base.Sections["rules"];
            }
        }
    }
}

  

namespace UrlRewrite
{
    public class UrlRewriteConfig : ConfigurationSection
    {
        [ConfigurationProperty("enable", DefaultValue = false)]
        public bool Enable
        {
            get
            {
                return (bool)base["enable"];
            }
        }

        [ConfigurationProperty("suffix", DefaultValue = ".html")]
        public string Suffix
        {
            get
            {
                return (string)base["suffix"];
            }
        }


        [ConfigurationProperty("", IsDefaultCollection = true)]
        public RulesElectionCollection Rules
        {
            get
            {
                return (RulesElectionCollection)base[""];
            }
        }

    }

    public class UrlRewriteConfigRule : ConfigurationElement
    {
        [ConfigurationProperty("form")]
        public string Form
        {
            get
            {
                return (string)base["form"];
            }
        }
        [ConfigurationProperty("to")]
        public string To
        {
            get
            {
                return (string)base["to"];
            }
        }
        [ConfigurationProperty("query")]
        public string Query
        {
            get
            {
                return (string)base["query"];
            }
        }
    }

    public class RulesElectionCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new UrlRewriteConfigRule();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((UrlRewriteConfigRule)element).Form;
        }
    }

    public static class UrlRewriteConfigHelp
    {
        public static bool Enabled
        {
            get
            {
                UrlRewriteConfig section
                    = ConfigurationManager.GetSection("rulesGroup/rules")
                    as UrlRewriteConfig;
                if (section == null)
                {
                    return false;
                }
                return section.Enable;
            }
        }

        public static string Suffix
        {
            get
            {
                UrlRewriteConfig section
                    = ConfigurationManager.GetSection("rulesGroup/rules")
                    as UrlRewriteConfig;
                if (section == null)
                {
                    return ".html";
                }
                return section.Suffix;
            }
        }


        public static RulesElectionCollection Rules
        {
            get
            {
                UrlRewriteConfig section
                    = ConfigurationManager.GetSection("rulesGroup/rules")
                    as UrlRewriteConfig;
                if (section == null)
                {
                    throw new System.InvalidOperationException("未能获取rulesGroup/rules");
                }
                return section.Rules;
            }
        }

        public static string RewriteBase
        {
            get
            {
                string path = HttpContext.Current.Request.ApplicationPath;
                if (!path.EndsWith("/"))
                {
                    return path + "/";
                }

                return path;
            }
        }

    }

}

  

这里定义了组,不需要的话可以把UrlRewriteConfigGroup类去掉并修改配置节点,在UrlRewriteConfig类里又定义了UrlRewriteConfigHelp帮助类获取节点信息...

然后实现IHttpModule实现重写

namespace UrlRewrite
{
    public class UrlRewrite : IHttpModule
    {

        #region IHttpModule 成员

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(Application_BeginRequest);
            //context.PreRequestHandlerExecute += new EventHandler(Application_PreRequestHandlerExecute);
        }

        void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;

            // 取得当前请求的路径
            string path = context.Request.Path;

            string suffix = String.Empty;
            if (UrlRewriteConfigHelp.Enabled)
                suffix = UrlRewriteConfigHelp.Suffix;

            // 遍历所有的映射规则,进行映射处理 
            foreach (UrlRewriteConfigRule rule in UrlRewriteConfigHelp.Rules)
            {
                Regex regex = new Regex("^" + rule.Form + suffix + "$", RegexOptions.IgnoreCase);
                Match match = regex.Match(path);
                if (match.Success)
                {
                    string trueUrl = UrlRewriteConfigHelp.RewriteBase + rule.To;

                    context.Items["OriginalUrl"] = context.Request.RawUrl;

                    if ("POST".Equals(context.Request.HttpMethod))
                        trueUrl = trueUrl.Substring(0, trueUrl.LastIndexOf("?"));
                    else
                    {
                        int count = match.Groups.Count;

                        if (count > 1 && match.Groups[1].Value != "")
                        {
                            for (int i = 1; i <= count; i++)
                            {
                                trueUrl = trueUrl.Replace("$" + i, match.Groups[i + 1].Value);
                            }
                        }
                    }

                    context.RewritePath(trueUrl);
                    return;
                }
            }

            //context.RewritePath("/error.htm");
        }

  

然后就可以访问了

这里from的action生成的是实际的地址,为了能让form生成请求的地址要重写form的action生成,这里定义了一个form.browser文件和一个FormRewriterControlAdapter类

namespace UrlRewrite
{
    public class FormRewriterControlAdapter :
        System.Web.UI.Adapters.ControlAdapter
    {
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(new RewriteFormHtmlTextWriter(writer));
        }
    }

    public class RewriteFormHtmlTextWriter : HtmlTextWriter
    {
        public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
            : base(writer)
        {
            this.InnerWriter = writer.InnerWriter;
        }

        public RewriteFormHtmlTextWriter(TextWriter writer)
            : base(writer)
        {
            this.InnerWriter = writer;
        }

        public override void WriteAttribute(string name, string value, bool fEncode)
        {
            if (name == "action")
            {
                HttpContext context = HttpContext.Current;

                if (context.Items["ActionAlreadyWritten"] == null)
                {
                    value = context.Items["OriginalUrl"] as string;
                    context.Items["ActionAlreadyWritten"] = true;
                }
            }

            base.WriteAttribute(name, value, fEncode);
        }
    }
}

  

form.browser文件代码

<!--

可在 <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers 中找到现有的浏览器定义

-->

<browsers>

  <browser refID="Default">

    <controlAdapters>

      <adapter controlType="System.Web.UI.HtmlControls.HtmlForm"

               adapterType="UrlRewrite.FormRewriterControlAdapter" />

    </controlAdapters>

  </browser>

</browsers>

整体截图

另外web.config中

<rules enable="true" suffix=".ygm">

      <add form="(/|/default|/index)" to="view/user/index.aspx"/>

      <add form="/u/user(_(\d+))*" to="view/user/user.aspx?id=$1" />

    </rules>

enable设置为true启动带后缀的访问,suffix设置后缀名,可以随便起

设置后访问截图

由于没怎么用过urlrewrite重写和.net下正则也比较生疏所以折腾下,貌似可以不用.browsers文件也可以达到form的action正确生成,望指教..

最后附上源码下载