asp.net 2.0 中的URL重写以及urlMappings问题

  在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&month=$2</SendTo>

  </RewriterRule>

  <RewriterRule>

  <LookFors>

  <LookFor>~/pc</LookFor>

  </LookFors>

  <SendTo>~/Test2.aspx</SendTo>

  </RewriterRule>

  </Rules>

  //这个规则写的不好,如第一个就可以用一个正则表达式来做。