1.定义url重写规则,很不幸的是一定要使用特定字符替代&,郁闷ing.........
<UrlReWriter enabled="true" reverse="true">
  
<url pattern="/BBS/Forum/(d+).shtml" url="/BBS/Forum.aspx?BoardID=$1" repattern="/BBS/Forum.aspx?BoardID=(d+)$" reurl="/BBS/Forum/$1.shtml" />
  
<url pattern="/BBS/Post/(d+).shtml" url="/BBS/Post.aspx?ArticleID=$1" repattern="/BBS/Post.aspx?ArticleID=(d+)$" reurl="/BBS/Post/$1.shtml"></url>
  
<url pattern="/BBS/Forum/(d+)/(d+).shtml$" url="/BBS/Forum.aspx?BoardID=$1^type=$2" repattern="/BBS/Forum.aspx?BoardID=(d+)^type=(d+)$" reurl="/BBS/Forum/$1/$2.shtml" />
</UrlReWriter>

2.定义配置文件对应实体类

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Xml;
using System.Web.Caching;

namespace DuwCompontents
{
    
/// <summary>
    
/// url重写配置节实体类
    
/// </summary>

    public class UrlReWriter
    
{
        
#region
        
private string _Pattern;
        
private string _Url;
        
private string _RePattern;
        
private string _ReUrl;
        
#endregion


        
#region

        
/// <summary>
        
/// 反向替换时url地址
        
/// </summary>

        public string ReUrl
        
{
            
get return _ReUrl; }
        }


        
/// <summary>
        
/// 反向替换时正则
        
/// </summary>

        public string Repattern
        
{
            
get return _RePattern; }
        }


        
/// <summary>
        
/// 真实url
        
/// </summary>

        public string Url
        
{
            
get return _Url; }
        }


        
/// <summary>
        
/// 正则
        
/// </summary>

        public string Pattern
        
{
            
get return _Pattern; }
        }

        
#endregion


        
#region 构造
        
public UrlReWriter(XmlNode xn) {
            _Pattern 
= xn.Attributes["pattern"].Value;
            _Url 
= xn.Attributes["url"].Value;
            _RePattern 
= xn.Attributes["repattern"].Value;
            _ReUrl 
= xn.Attributes["reurl"].Value;
        }

        
#endregion


    }

    
/// <summary>
    
/// url重写配置实体类
    
/// </summary>

    public class UrlReWriterConfig
    
{

        
#region 私有成员
        
private static string configFile = "/Configs/UrlReWriter.Config";
        
        
private List<UrlReWriter> _UrlRewriter;
        
private bool _Enabled;
        
private bool _Reverse;
        
        
#endregion


        
#region 公有属性
        
/// <summary>
        
/// 反向匹配支持?
        
/// </summary>

        public bool Reverse
        
{
            
get return _Reverse; }
        
        }

        
/// <summary>
        
/// 正向匹配支持?
        
/// </summary>

        public bool Enabled
        
{
            
get return _Enabled; }
        }


        
public List<UrlReWriter> UrlRewriters
        
{
            
get return _UrlRewriter; }
        }

        
#endregion


        
#region 单件模式
        
private static UrlReWriterConfig _Config;
        
        
static UrlReWriterConfig() {
            _Config 
= new UrlReWriterConfig();
            _Config._UrlRewriter 
= new List<UrlReWriter>();

            
string file = HttpContext.Current.Server.MapPath( configFile );
            XmlDocument xd 
= new XmlDocument();
            xd.Load(file);
            XmlElement xe 
= xd.DocumentElement;
            
bool enabled = true;
            
if (xe.Attributes["enabled"!= null)
            
{
                enabled 
= Boolean.TryParse(xe.Attributes["enabled"].Value, out enabled);
            }

            _Config._Enabled 
= enabled;

            
bool reverse = true;
            
if (xe.Attributes["reverse"!= null{
                reverse 
= Boolean.TryParse(xe.Attributes["reverse"].Value, out reverse);
            }

            _Config._Reverse 
= reverse;
          
            
foreach (XmlNode xn in xe.ChildNodes)
            
{
                
if (xn.NodeType == XmlNodeType.Element)
                
{
                    UrlReWriter re 
= new UrlReWriter(xn);
                    _Config._UrlRewriter.Add(re);
                }

            }


        }
 
        
        
/// <summary>
        
/// url重写配置实体类
        
/// </summary>
        
/// <returns></returns>

        public static UrlReWriterConfig Instance()
        
{
            
return _Config; 
        }

        
#endregion

       
    }

}



3.实现IHttpModule(不使用ajax.net(atlas)可以不用处理AjaxPageFilter相关)
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Xml;
using System.Text.RegularExpressions;

namespace DuwCompontents
{
    
public interface IRawPath
    
{
        
string GetPath();
    }

    
public class DuwHttpModule : IHttpModule, IRawPath
    
{

        
#region IRawPath 成员
        
//private string _rawPath = "";
        
//public string GetPath()
        
//{
        
//   return _rawPath;
        
//
        

        
#endregion

        
#region IHttpModule 成员

        
        
void IHttpModule.Dispose()
        
{
            
        }


        
void IHttpModule.Init(HttpApplication context)
        
{
           
            context.BeginRequest 
+= new EventHandler(context_BeginRequest);
            
//context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
        }


        
        
#endregion


        
#region 事件
        
//void context_ReleaseRequestState(object sender, EventArgs e)
        
//{
           
// HttpResponse response = HttpContext.Current.Response;

           
// if (response.ContentType == "text/plain")
           
// {
           
//     AjaxPageFilter filter = new AjaxPageFilter(response.Filter);
           
//    response.Filter = filter;
           
//     filter.RawPath = this;
           
// }
        
//}

 

        
void context_BeginRequest(object sender, EventArgs e)
        
{
            
//这儿处理url重写
            string rawUrl = HttpContext.Current.Request.RawUrl;
            
//_rawPath = rawUrl ;
            UrlReWriterConfig config = UrlReWriterConfig.Instance();
            
if (HttpContext.Current.Request.Path.EndsWith(".shtml"&& config.Enabled )
            
{
                List
<UrlReWriter> rewriters = UrlReWriterConfig.Instance().UrlRewriters;

                
foreach (UrlReWriter rewriter in rewriters)
                
{
                    
string s_url = rewriter.Url.Replace("^""&");
                   
                    Regex r 
= new Regex(rewriter.Pattern, RegexOptions.IgnoreCase);
                    
if (r.IsMatch(rawUrl))
                    
{
                        s_url 
= r.Replace(rawUrl, s_url); 
                        HttpContext.Current.RewritePath(s_url);
                        
break;
                    }


                }

            }


        }

       
      
        
#endregion


    }

}


4.配置IIS,主目录/配置,使用aspnet_isapi.dll处理.shtml.取消确认文件是否存在选择项

5,配置web.Config.支持自定义httpModule
<System.Web>
    
<httpModules>
        
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        
<!--type="完全限定名,程序集"-->
        
<add name="DuwHttpModule" type="DuwCompontents.DuwHttpModule,DuwCompontents"/>
    
</httpModules>
</System.Web>

6重写page类
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using DuwCompontents;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;

namespace DuwControls
{
    
public class DuwPage : Page
    
{


       
        
#region 事件
        
protected override void Render(HtmlTextWriter writer)
        
{
    
//替换掉form action
            config = UrlReWriterConfig.Instance();
            
if (config.Enabled) {
                
if (writer is System.Web.UI.Html32TextWriter)
                
{
                    writer 
= new FormFixerHtml32TextWriter(writer.InnerWriter);
                }

                
else
                
{
                    writer 
= new FormFixerHtmlTextWriter(writer.InnerWriter);
                }

            }

         
//如果要求支持反向匹配
            if(config.Reverse){
                FindHyperLink(Controls);
            }


            
base.Render(writer);
        }

        
#endregion


        
#region 替换所有的服务端超链接
        
private void FindHyperLink(ControlCollection controls) {
            
foreach (Control ctrl in controls) {
                
if (ctrl is HyperLink) {
                    ReplaceUrl(ctrl 
as HyperLink);
                }

                
else if (ctrl is System.Web.UI.HtmlControls.HtmlAnchor) {
                    ReplaceUrl(ctrl 
as System.Web.UI.HtmlControls.HtmlAnchor);
                }

                
else if (ctrl.Controls.Count > 0)
                
{
                    FindHyperLink(ctrl.Controls);
                }

            }

        }

        
private void ReplaceUrl(System.Web.UI.HtmlControls.HtmlAnchor hl)
        
{
            UrlReWriterConfig config 
= UrlReWriterConfig.Instance();
            List
<UrlReWriter> rewriters = UrlReWriterConfig.Instance().UrlRewriters;

            
foreach (UrlReWriter rewriter in rewriters)
            
{


                
string s_url = rewriter.Repattern.Replace("^""&");
                Regex r 
= new Regex(s_url, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                
string rawUrl = hl.HRef;
                
                rawUrl 
= Regex.Replace(rawUrl, s_url, rewriter.ReUrl);
                
if (hl.HRef != rawUrl)
                
{
                    hl.HRef 
= rawUrl;
                    
break;
                }

            
            }

        }

        
private void ReplaceUrl(HyperLink hl) {
            UrlReWriterConfig config 
= UrlReWriterConfig.Instance();
            List
<UrlReWriter> rewriters = UrlReWriterConfig.Instance().UrlRewriters;

            
foreach (UrlReWriter rewriter in rewriters)
            
{


                
string s_url = rewriter.Repattern.Replace("^""&");
                Regex r 
= new Regex(s_url, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                
string rawUrl = hl.NavigateUrl;
                
                rawUrl 
= Regex.Replace(rawUrl, s_url, rewriter.ReUrl);
                
if (hl.NavigateUrl != rawUrl)
                
{
                    hl.NavigateUrl 
= rawUrl;
                    
break;
                }

             

            }

        }

        
#endregion


        
#region 替换掉Form的action

        
#region FormFixerHtml32TextWriter
        
internal class FormFixerHtml32TextWriter : System.Web.UI.Html32TextWriter
        
{
            
private string _url; // 假的URL

            
internal FormFixerHtml32TextWriter(TextWriter writer)
                : 
base(writer)
            
{
                _url 
= HttpContext.Current.Request.RawUrl;
            }


            
public override void WriteAttribute(string name, string value, bool encode)
            
{
                
// 如果当前输出的属性为form标记的action属性,则将其值替换为重写后的虚假URL
                if (_url != null && string.Compare(name, "action"true== 0)
                
{
                    value 
= _url;
                }

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

        }

        
#endregion


        
#region FormFixerHtmlTextWriter
        
internal class FormFixerHtmlTextWriter : System.Web.UI.HtmlTextWriter
        
{
            
private string _url;
            
internal FormFixerHtmlTextWriter(TextWriter writer)
                : 
base(writer)
            
{
                _url 
= HttpContext.Current.Request.RawUrl;
            }


            
public override void WriteAttribute(string name, string value, bool encode)
            
{
                
if (_url != null && string.Compare(name, "action"true== 0)
                
{
                    value 
= _url;
                }


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

        }

        
#endregion


        
#endregion

    }

}


7继续使用页面过滤器,使支持ajax.net(atlas)
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;

namespace DuwCompontents
{
    
public class AjaxPageFilter : Stream
    
{
        IRawPath _context 
= null;
        Stream responseStream;
        
long position;
        StringBuilder responseHtml;

        
public AjaxPageFilter(Stream inputStream)
        
{
            responseStream 
= inputStream;
            responseHtml 
= new StringBuilder();
        }


        
public override bool CanRead
        
{
            
get return true; }
        }


        
public override bool CanSeek
        
{
            
get return true; }
        }


        
public override bool CanWrite
        
{
            
get return true; }
        }


        
public override void Close()
        
{
            responseStream.Close();
        }


        
public override void Flush()
        
{
            responseStream.Flush();
        }


        
public override long Length
        
{
            
get return 0; }
        }


        
public override long Position
        
{
            
get return position; }
            
set { position = value; }
        }


        
public override long Seek(long offset, SeekOrigin origin)
        
{
            
return responseStream.Seek(offset, origin);
        }


        
public override void SetLength(long length)
        
{
            responseStream.SetLength(length);
        }


        
public override int Read(byte[] buffer, int offset, int count)
        
{
            
return responseStream.Read(buffer, offset, count);
        }


        
public override void Write(byte[] buffer, int offset, int count)
        
{
            
string finalHtml = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);

            
// Transform the response
            string formAction = RawPath.GetPath();
            
if (!String.IsNullOrEmpty(formAction))
            
{
                finalHtml 
= Regex.Replace(finalHtml, "\|\d+\|formAction\|\|[^\|]+\|",
                    
"|" + formAction.Length.ToString() + "|formAction||" + formAction + "|",
                    RegexOptions.IgnoreCase);
            }


            
// Write the response
            byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);
            responseStream.Write(data, 
0, data.Length);
        }


        
public IRawPath RawPath
        
{
            
get
            
{
                
return _context;
            }

            
set
            
{
                _context 
= value;

            }

        }

    }

}


8.取消3(DuwHttpModule)中的注释,转而支持AjaxPageFilter,
至此url重写工作完成,但是反向匹配虽然可以使我们几乎不用改任何一句代码
就支持全站的url重写,却是一个很浪费资源的行为,并不建议使用
http://blog.csdn.net/baozhenliang/archive/2007/04/30/1593280.aspx
posted on 2007-06-05 01:17  mbskys  阅读(236)  评论(0)    收藏  举报