在asp.net2.0中的urlMappings 转

来源:互联网 发布:淘宝服装修图技巧 编辑:程序博客网 时间:2024/05/02 11:03
在asp.net2.0中的urlMappings 转
2008-03-19 09:35

在asp.net2.0中的urlMappings倒是非常好用,可惜暂不支持正则表达式,

不过,好在如果用IHttpModule的话

不管什么样的请求都会先经过IHttpModule这样就为URL重写提供了一个好机会:

下面是我写的一个IHttpModule:

using System; using System.Web;

public class ReWriteModule:IHttpModule { public ReWriteModule() { }     public override string ToString()     {         return this.GetType().ToString();     }

void IHttpModule.Dispose() {    }     private static System.Xml.XmlDocument ruleDoc = null;     private static System.Xml.XmlDocument GetRuleConfig(System.Web.HttpContext app)     {         if (ruleDoc == null)         {             ruleDoc = new System.Xml.XmlDocument();             ruleDoc.Load(app.Server.MapPath("~/rule.xml"));         }         return ruleDoc;     }     public static string GetUrl(System.Web.HttpContext cxt,string path)     {                System.Xml.XmlDocument doc = GetRuleConfig(cxt);        System.Xml.XmlNodeList lst= doc.GetElementsByTagName("RewriterRule");        string pat="";        foreach (System.Xml.XmlNode nd in lst)        {            System.Xml.XmlNodeList sub = nd.ChildNodes[0].ChildNodes;            foreach(System.Xml.XmlNode chk in sub)            {                pat = "^" + chk.InnerText+"$";                System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(pat, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.IgnoreCase);                if(reg.IsMatch(path))                {                   return reg.Replace(path, nd.ChildNodes[1].InnerText);                }            }        }        return null;

    } void IHttpModule.Init(HttpApplication context) {     context.BeginRequest += delegate(object sender, EventArgs e)     {        

        System.Web.HttpContext cxt = context.Context;              if (cxt.Request.ContentType != "image/pjpeg")         {             string type = cxt.Request.ContentType.ToLower();             string path = cxt.Request.Path;             string apppath = cxt.Request.ApplicationPath;             path = path.Remove(0, apppath.Length);             path = "~" + path;                         string newUrl = GetUrl(cxt, path.TrimEnd().TrimStart());             if (newUrl != null)             {                 cxt.Response.Filter = new ResponseFilter(cxt.Response.Filter,cxt.Request.Path);                 cxt.Response.Write("请求的路径:" + path);                 cxt.Response.Write("<BR>");                 cxt.Response.Write("转向的目的URL:" + newUrl);                 cxt.Response.Write("<BR>");                 cxt.RewritePath(newUrl);                                                             }//如果要求处理所有的请求时用到             //else             //{             //    cxt.Response.Write(cxt.Request.Path + "<BR>");             //    cxt.Response.Write("你请求的资源不存在或无权访问!");             //    cxt.Response.Flush();             //    cxt.Response.End();             //}         }          };    }

}

由于一旦进行了URL重写,原先的WEBFORM中的Action会发生改变,容易造成:请求的资源不存在问题

具体怎么样?各位DX看看就清楚了!!!

所有才有了这个ResponseFilter了,实现如下,

public class ResponseFilter:System.IO.Stream {         public ResponseFilter(System.IO.Stream sink,string _str) {    _sink = sink;    //    // TODO: 在此处添加构造函数逻辑    //             this.str = _str; }     private string str = ""; private System.IO.Stream _sink; private long _position; private System.Text.Encoding end=System.Text.Encoding.GetEncoding("GB18030"); private System.Text.StringBuilder oOutput = new System.Text.StringBuilder();    // The following members of Stream must be overriden. public override bool CanRead {    get { return true; } }

public override bool CanSeek {    get { return true; } }

public override bool CanWrite {    get { return true; } }

public override long Length {    get { return 0; } }

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

public override long Seek(long offset, System.IO.SeekOrigin direction) {    return _sink.Seek(offset, direction); }

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

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

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

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

// The Write method actually does the filtering.     public override void Write(byte[] buffer, int offset, int count)     {         string szBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);         string ap="action=/"";         int pos=-1;         if ((pos=szBuffer.IndexOf(ap) )!= -1)         {             int epos = szBuffer.IndexOf("/"", pos + ap.Length+1);             if (epos != -1)             {               szBuffer= szBuffer.Remove(pos + ap.Length, epos - pos - ap.Length);             }

            szBuffer = szBuffer.Insert(pos + ap.Length, this.str);

            byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(szBuffer);             _sink.Write(data, 0, data.Length);                     }         else         {             oOutput.Append(szBuffer);         }

        //下面的这一段可以用来修改<Head></head>之间的内容;         //Regex oEndFile = new Regex("</head>", RegexOptions.IgnoreCase|RegexOptions.Compiled);         //if (oEndFile.IsMatch(szBuffer))         //{         //    //Append the last buffer of data         //    //附加上缓冲区中的最后一部分数据         //    oOutput.Append(szBuffer);         //    //Get back the complete response for the client         //    //传回完整的客户端返回数据         //    string szCompleteBuffer = oOutput.ToString().ToLower();         //    int ipos = szCompleteBuffer.IndexOf("<title>");         //    int epos = szCompleteBuffer.IndexOf("</title>",ipos+7);         //    string sp = szCompleteBuffer.Substring(ipos+7, epos - ipos );         //    szCompleteBuffer = szCompleteBuffer.Remove(ipos+7,sp.Length-7);         //    szCompleteBuffer = szCompleteBuffer.Insert(ipos + 7, "dhz");         // //   szCompleteBuffer = szCompleteBuffer.Replace(sp, "dhz");         //    //No match, so write out original data         //    //没有匹配,因此写入源代码         //    byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(szCompleteBuffer);         //    _sink.Write(data, 0, data.Length);         //}         //else         //{         //    oOutput.Append(szBuffer);         //}     } }

//////而重候规则呢则是用xml文件配置如下;

当然在web.config通过自定义配置节做也可以的

<?xml version="1.0" encoding="utf-8" ?> <Rules> <RewriterRule>     <LookFors>       <LookFor>~/(/d{4})/(/d{2})/.html</LookFor>       <LookFor>~/(/d{4})/(/d{2})/</LookFor>       <LookFor>~/(/d{4})/(/d{2})</LookFor>       <LookFor>~/(/d{4})/(/d{2})/index.html</LookFor>     </LookFors>     <SendTo>~/Pro.aspx?year=$1&amp;month=$2</SendTo> </RewriterRule> <RewriterRule>     <LookFors>       <LookFor>~/pc</LookFor>     </LookFors>     <SendTo>~/Test2.aspx</SendTo> </RewriterRule> </Rules> //这个规则写的不好,如第一个就可以用一个正则表达式来做。但是一时不知道怎么写好,好像要用到什么反捕获组的概念,正在思考这个东东!!