现在的位置: 首页 > 综合 > 正文

.NET 中 URL重写的一部分代码

2013年06月28日 ⁄ 综合 ⁄ 共 11109字 ⁄ 字号 评论关闭

 第一次使用,代码可能不够完善,先放这,让大家给把把脉,其中混着一些静态页生成

重写HttpModel模块

using System;
using System.Web;
using System.Text.RegularExpressions;
using System.Collections;

namespace Web
{
 /// <summary>
 /// HttpModelReWriter 的摘要说明。
 /// </summary>
 public class HttpModelReWriter : IHttpModule
 {
  public HttpModelReWriter()
  {
  }

  public void Init(HttpApplication app)
  {
   //事件订阅
   app.BeginRequest += (new EventHandler(this.BeginRequest));
  }

  protected void BeginRequest(object sender, EventArgs e)
  {
   HttpApplication app = (HttpApplication)sender;
   ReWriter(app.Request.Path,app);
  }

  protected void ReWriter(string requestedPath,HttpApplication app)
  {
   //动态页面不重写
   if(requestedPath.IndexOf(".aspx") < 0)
   {
    ReWriterRules rules = ReWriterRules.GetInstance();
    foreach(DictionaryEntry dic in rules)
    {
     RuleItem rule = (RuleItem)dic.Value;
     string lookFor = "^" + RewriterHandler.ResolveUrl(app.Context.Request.ApplicationPath,rule.LookFor) + "$";
     Regex reg = new Regex(lookFor, RegexOptions.IgnoreCase);
     if (reg.IsMatch(requestedPath))
     {        
      string sendToUrl = RewriterHandler.ResolveUrl(app.Context.Request.ApplicationPath, reg.Replace(requestedPath, rule.SendTo));
      RewriterHandler.RewriteUrl(app.Context,sendToUrl,rule);
      break;
     }
    }
   }
   else
   {
    //有参数update=1,则强制更新,该方法效率不好,在此作为一种补充手段,页面更新主要靠WIN服务来完成
    if( null != app.Request.QueryString["update"] && "1" == app.Request.QueryString["update"].ToString() )
    {
     string htmlFile = URLBuild.GetStaticURL(app.Request.RawUrl.Replace("&update=1",""));

     int iResult = 0;
     try
     {
      iResult = RewriterHandler.CreateHtmlFile(app.Server.MapPath(htmlFile),app.Request.RawUrl.Replace("&update=1",""),app.Request.Url.Host);
     }
     catch(Exception ex)
     {
      app.Context.Response.Clear();
      app.Context.Response.Write(ex.Message);
      app.Context.Response.End();
      return;
     }

     app.Context.Response.Clear();
     app.Context.Response.Write(iResult);
     app.Context.Response.End();
    }
   }
  }

  public void Dispose()
  {
  }
 }
}

读配置模块(网上见很多人用序列化来读)

using System;
using System.Xml;
using System.Configuration;

namespace Web
{
 /// <summary>
 /// RewriterConfigHandle 的摘要说明。
 /// </summary>
 public class RewriterConfigHandle : IConfigurationSectionHandler
 {
  public RewriterConfigHandle()
  {
  }

  public object Create(object parent, object input, XmlNode node)
  {
   if ( "#comment" == node.Name )
    return null;

   //处理RewriterConfig
   foreach ( XmlNode xn in node.ChildNodes )
   {
    Read(xn);
   }

   return 1;
  }

  private void Read(XmlNode node)
  {
   if ( "#comment" == node.Name )
    return;

   RuleItem ri = new RuleItem();
   //处理RewriterRule
   foreach ( XmlAttribute xa in node.Attributes )
   {
    switch ( xa.Name.ToUpper() )
    {
     case "ID":
     {
      ri.ID = xa.Value;
      break;
     }
     case "LOOKFOR":
     {
      ri.LookFor = xa.Value;
      break;
     }
     case "SENDTO":
     {
      ri.SendTo = xa.Value;
      break;
     }
     case "POLICY":
     {
      if ( xa.Value.Trim() != "" )
       ri.Policy = Convert.ToInt32(xa.Value);

      break;
     }
     default:
     {
      break;
     }
    }
   }
 
   ReWriterRules rules = ReWriterRules.GetInstance();

   rules.Add(ri.ID,ri);
  }
 }
}

URL重写部分

using System;
using System.Web;
using System.Web.UI;
using System.Text.RegularExpressions;
using System.IO;
using System.Net;

namespace Web
{
 /// <summary>
 /// RewriterUtils 的摘要说明。
 /// </summary>
 public class RewriterHandler
 {
  private RewriterHandler()
  {
  }

  /// <summary>
  /// 替换~
  /// </summary>
  /// <param name="rootPath"></param>
  /// <param name="filePath"></param>
  /// <returns></returns>
  public static string ResolveUrl(string rootPath,string filePath)
  {
   if ( Regex.IsMatch(filePath,"^~",RegexOptions.IgnoreCase) )
   {
    return filePath.Replace("~",rootPath).Replace("//","/");
   }
   else
   {
    return filePath.Replace("//","/");
   }
  }

  /// <summary>
  /// URL重写加静态页生成
  /// </summary>
  /// <param name="context"></param>
  /// <param name="sendToUrl"></param>
  /// <param name="rule"></param>
  public static void RewriteUrl(HttpContext context,string sendToUrl,RuleItem rule)
  {
   string htmlRequestStr = context.Request.Path;

   if(htmlRequestStr.IndexOf(".htm") == - 1)
   {
    htmlRequestStr = Regex.IsMatch(htmlRequestStr,@"^"+context.Request.ApplicationPath + "(/?)$",RegexOptions.IgnoreCase) ? URLBuild.GetStaticURL(sendToUrl) : htmlRequestStr.TrimEnd('/') + ".htm";
   }
   else
   {
    htmlRequestStr = htmlRequestStr.Replace(".html",".htm");
   }

   string htmlFile = context.Server.MapPath(htmlRequestStr);
   int iResult = 0;

   try
   {
    //无静态页,或已过期
    if( !File.Exists(htmlFile) )
    {
     iResult = CreateHtmlFile(htmlFile,sendToUrl,context.Request.Url.Host);
    }
    else if ( rule.Policy > 0 )
    {
     FileInfo fi = new FileInfo(htmlFile);
     if(DateTime.Now > fi.CreationTime.AddMinutes(rule.Policy))
     {
      fi.Delete();
      iResult = CreateHtmlFile(htmlFile,sendToUrl,context.Request.Url.Host);
     }
    }
   }
   catch(Exception ex)
//   if ( -1 == iResult )
   {
//    context.Response.Write("服务器繁忙,请稍后再试");
    context.Response.Write(ex.Message);
    context.Response.End();
    return;
   }

   //在此可能要加实际路径参数???
   context.RewritePath(htmlRequestStr);
  }

  /// <summary>
  /// 创建静态页,通过重发一次请求来完成,效率不高
  /// 可以重写HttpHandle,读Response流来完成
  /// </summary>
  /// <param name="htmlFile"></param>
  /// <param name="sendToUrl"></param>
  /// <param name="host"></param>
  /// <returns></returns>
  public static int CreateHtmlFile(string htmlFile,string sendToUrl,string host)
  {
   System.Text.Encoding encode = System.Text.Encoding.GetEncoding("UTF-8");

   try
   {
//    HttpWebRequest hwrq = (HttpWebRequest)HttpWebRequest.Create("http://" + host + sendToUrl);
    //中心网站服务器为内部跳转,承载的机器无法访问外网,取HOST会有问题
    HttpWebRequest hwrq = (HttpWebRequest)HttpWebRequest.Create("http://localhost" + sendToUrl);
    HttpWebResponse hwrp = (HttpWebResponse)hwrq.GetResponse();

    if( null != hwrp )
    {
     StreamReader readStream = new StreamReader( hwrp.GetResponseStream(), encode );
     string htmlFilePath = htmlFile.Substring(0,htmlFile.LastIndexOf(@"/"));

     //验证目录
     if(!Directory.Exists(htmlFilePath))
      Directory.CreateDirectory(htmlFilePath);

     FileStream fs = new FileStream(htmlFile,FileMode.Create,FileAccess.ReadWrite);
     StreamWriter sw = new StreamWriter(fs,encode);

     sw.Write(readStream.ReadToEnd());
     sw.Flush();
     fs.Flush();
     sw.Close();
     fs.Close();

     readStream.Close();
     hwrp.GetResponseStream().Close();
    }

    return 1;
   }
   catch(Exception ex)
   {
    throw ex;
    //return -1;
   }
  }
 }
}

URL重写规则实体集合类

using System;
using System.Collections;

namespace Web
{
 /// <summary>
 /// ReWriterRules 的摘要说明。
 /// </summary>
 public class ReWriterRules : IEnumerable
 {
  private static ReWriterRules helf = new ReWriterRules();
  private Hashtable htRules = null;

  private ReWriterRules()
  {
   htRules = new Hashtable();
  }

  public static ReWriterRules GetInstance()
  {
   if ( null == helf )
   {
    helf = new ReWriterRules();
   }
   
   return helf;
  }

  #region 属性

  /// <summary>
  /// 连接参数索引器
  /// </summary>
  public RuleItem this[object index]
  {
   get
   {
    if ( null == htRules || 0 == htRules.Count )
     ReadConfig();

    object o = htRules[index];
    RuleItem r = (RuleItem)o;
    return r;
   }
   set
   {
    htRules[index] = value;
   }
  }

  /// <summary>
  /// 获取参数总数
  /// </summary>
  public int Count
  {
   get
   {
    if ( null == htRules || 0 == htRules.Count )
     ReadConfig();
    
    return this.htRules.Count;
   }
  }

  #endregion

  #region 公共方法

  /// <summary>
  /// 添加新参数
  /// </summary>
  /// <param name="key"></param>
  /// <param name="value"></param>
  public void Add ( object key,object value )
  {
   if ( !ContainsParam(key) )
    this.htRules.Add(key,value);
  }

  /// <summary>
  /// 删除参数
  /// </summary>
  /// <param name="key"></param>
  public void Remove ( object key )
  {
   if ( ContainsParam(key) )
    this.htRules.Remove(key);
  }

  /// <summary>
  /// 测试是否存在特定的参数
  /// </summary>
  /// <param name="key"></param>
  /// <returns></returns>
  public bool ContainsParam(object key)
  {
   return this.htRules.ContainsKey(key);
  }

  public IEnumerator GetEnumerator()
  {
   if (Count > 0)
                return htRules.GetEnumerator();
   else
    return null;
  }

  #endregion

  private void ReadConfig()
  {
   try
   {
    System.Configuration.ConfigurationSettings.GetConfig("RewriterConfigurations");
   }
   catch(Exception ex)
   {
    throw ex;
   }
  }
 }
}

URL重写规则配置类

using System;

namespace Web
{
 /// <summary>
 /// RuleItem 的摘要说明。
 /// </summary>
 public class RuleItem
 {
  private string id = "";
  private string lookFor = "";
  private string sendTo = "";
  private int policy = 0;

  public RuleItem()
  {
  }

  public RuleItem(string id,string look,string send,int policy)
  {
   this.id = id;
   lookFor = look;
   sendTo = send;
   this.policy = policy;
  }

  #region 属性

  public string ID
  {
   get
   {
    return id;
   }
   set
   {
    id = value;
   }
  }

  public string LookFor
  {
   get
   {
    return lookFor;
   }
   set
   {
    lookFor = value;
   }
  }

  public string SendTo
  {
   get
   {
    return sendTo;
   }
   set
   {
    sendTo = value;
   }
  }

  public int Policy
  {
   get
   {
    return policy;
   }
   set
   {
    policy = value > 0 ? value : 0;
   }
  }

  #endregion
 }
}

生成静态URL类

using System;
using System.Text.RegularExpressions;

namespace Web
{
 /// <summary>
 /// 根据重写规则,反生成静态页地址,以便绑定到页面
 /// </summary>
 public class URLBuild
 {
  public URLBuild()
  {
  }

  public static string GetStaticURL(string strURL)
  {
   //如果本身就是静态URL,直接返回
   if (Regex.IsMatch(strURL,@"[/w+].htm[l?]$",RegexOptions.IgnoreCase) )
    return strURL;

   string strPath = strURL.Substring(0,strURL.IndexOf("?"));
   strPath = strPath.Substring(0,strPath.LastIndexOf("/"));
   strPath += "/Journal";

   string[] arrParam = strURL.Replace(strPath + "?","").Split('&');

   if ( arrParam == null || arrParam.Length == 0 )
    return strPath + ".htm";

   for ( int i = 0; i < arrParam.Length; i ++ )
   {
    string[] arr = arrParam[i].Split('=');
    if ( arr.Length == 2 && arr[1] != "" )
     strPath += "/" + arr[1];
   }

   return strPath + ".htm";
  }
 }
}

配置文件样式

  <configSections>
  <!-- URL重写配置节设置 -->
  <section name="RewriterConfigurations" type="Web.RewriterConfigHandle, CNKIURLReWriter"></section>
 </configSections>
  <!-- 现重写存在的小问题,图片资源路径问题 -->
  <!-- policy的值默认以分钟为单位,0 表示永不过期 -->
  <RewriterConfigurations>
   <!-- RewriterRule ID = "1" lookFor = "~(/?)" sendTo = "~/Index.aspx?NaviID=1" policy="0"/ -->
   <RewriterRule ID = "2" lookFor = "~/Journal(/?)" sendTo = "~/Index.aspx?NaviID=1" policy="1"/>
   <RewriterRule ID = "3" lookFor = "~/Journal/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Index.aspx?NaviID=$1" policy="1"/>
   <RewriterRule ID = "4" lookFor = "~/Journal/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/List.aspx?NaviID=$1&amp;ZJDM=$2"  policy="1"/>
   <RewriterRule ID = "5" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/List.aspx?NaviID=$1&amp;ZJDM=$2&amp;ZTDM=$3"  policy="1"/>
   <RewriterRule ID = "6" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&amp;ZJDM=$2&amp;ZTDM=$3&amp;PYKM=$4" policy="0"/>
   <RewriterRule ID = "7" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&amp;ZJDM=$2&amp;ZTDM=$3&amp;PYKM=$4&amp;Year=$5" policy="0"/>
   <RewriterRule ID = "8" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&amp;ZJDM=$2&amp;ZTDM=$3&amp;PYKM=$4&amp;Year=$5&amp;Issue=$6" policy="0"/>
   <RewriterRule ID = "9" lookFor = "~/SiteMap(/.htm(l?))?" sendTo = "~/SiteMap.aspx?NaviID=1" policy="1"/>
  </RewriterConfigurations>
 <system.web>
  <httpModules>
   <add name="ReWriteModule" type="Web.HttpModelReWriter, CNKIURLReWriter"/>
  </httpModules>

 

*注意:

1、因为实现可截取URL,会配置IISAPI,对于图片/样式等资源,可能会发生路径问题

2、配置IISAPI后,会发现,所有资源请求都会转向ASP.NET,无论调试还是运行起来,感觉都不太爽

解决办法:另建一个资源服务器,所有资源路径都改为网络资源连接

抱歉!评论已关闭.