String *I am String* (自由大过天) 路漫漫其修远兮,吾以上下而求索

(道,可道,非常道)-----天之道,利而不害。圣人之道,为而不争。信言不美,美言不信。善者不辩,辩者不善。知者不博,博者不知。

导航

简单的URL重写

Posted on 2004-11-18 08:08  goodbaby  阅读(3393)  评论(3)    收藏  举报

为了向用户提供友好的URL需要对URL进行重写,比如有一个应用被多个用户使用,象这样的URL:http://www.***.com/serverpage.aspx?UserID=***
对用户来说这样的URL看上去是不友好的,如果用户想直接查看属于他的应用,这样的URL是不好接受的,参考了一些资料,我对URL重写进行了简单
了实现。
URL重写:
1:通过ISAPI,这种方式是用c/c++与IIS交互,实现起来相对麻烦一些。
2:使用asp.net,有两种方式:1-使用HttpModule,2-使用HttpHandle,这里用前者。
有asp.net,对URL重写就不想以前的asp那么麻烦,不需要你重起IIS,也不用ISAPI与IIS底层交互。
我在我的本地机器上访问http://UrlRewrite/test.aspx?UserID=goodbaby,现在的目的是要把他变成http://localhost/Urlwrite/goodbaby,这里的
UrlRewrite是我的虚拟目录。
好了首先写一个继承至IHttpModule的类:
public class HttpModuleUR:IHttpModule
 {
  public HttpModuleUR()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }

  public virtual void Init(HttpApplication app)
  {
   //Trace.Write("Module is invoked");
   app.AuthorizeRequest += new EventHandler(this.ModuleRewriterForAuthorizeRequest);

  }

  public void Dispose()
  {
  }

  protected virtual void ModuleRewriterForAuthorizeRequest(object sender, EventArgs e)
  {
   HttpApplication app = (HttpApplication) sender;
   Rewrite(app.Request.Path, app);
  }

  protected void Rewrite(string path, HttpApplication app)
  {
            Trace.Write("hello Rewrite Path");
            //app.Context.RewritePath("~/test.aspx");
          
            Rule[] rules=UrlRewriteConfig.Instance().Rules;
   
     // app.Context.RewritePath( rules[0].Instead);
  
   for(int i=0;i<rules.Length;i++)
   {
       Regex re = new Regex(rules[i].Pattern, RegexOptions.IgnoreCase);
    if(re.IsMatch(path))
    {
     app.Context.RewritePath(Regex.Replace(path,rules[i].Pattern,rules[i].Instead));
     break;
    }
   }
  }
 }
这个类将完成URL重写,使用这个类在asp.net管道模型中截取,这里是基于表单的身份验证,那么最佳的截取位置是在AuthorizeRequest事件中,这
里一个关键的操作:RewritePath()应用上下文的这个方法完成URL重写,UrlRewriteConfig类用来保存配置信息,他从my.config中反序列化这个xml
文档,从Rules属性中获取要规则集,规则Rule有两个属性Pattern,Instead,分别代表匹配模式,和替换模式,如果虚拟路径匹配Pattern那么就用Instead
替换路径,这是真正可用URL重写的模式。UrlRewriteConfig的实现是这样的:
        [Serializable]
 public class UrlRewriteConfig
 {
  public UrlRewriteConfig()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }

  private  UrlRewriteConfig urc=null;

  public static  UrlRewriteConfig Instance()
  {
   return (UrlRewriteConfig)LoadXmlSerializedObject(typeof(UrlRewriteConfig),System.Web.HttpContext.Current.Server.MapPath("~/my.Config"));
  }

  public static object LoadXmlSerializedObject(Type type, string filepath)
  {
   FileStream filestream=null;
   try
   {
    filestream=new FileStream(filepath,FileMode.Open,FileAccess.Read);
    XmlSerializer xms=new  XmlSerializer(type);
    return xms.Deserialize(filestream);
   }
   catch(Exception e)
   {
    throw e;
   }
   finally
   {
    if(filestream!=null)
     filestream.Close();
   }
  }

  private Rule[] _Rules;
  [XmlArray("Rules")]
  public Rule[] Rules
  {
   get
   {
    return _Rules;
   }
   set
   {
    _Rules=value;
   }
  }
  }

Rule同样是一个可序列化的对象:
public class Rule
 {
  public Rule()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }

  private string _pattern;
  [XmlElement]
  public string Pattern
  {
   get {return this._pattern;}
   set {this._pattern = value;}
  }

  private string _Instead;
  [XmlElement]
  public string Instead
  {
   get {return this._Instead;}
   set {this._Instead = value;}
  }

 }
配置文件存储了规则:
<?xml version="1.0" encoding="utf-8" ?>
<UrlRewriteConfig>
<Rules>
<Rule>
<Pattern>/AspNetForums/([a-zA-Z]+)</Pattern>
<Instead>test.aspx?UserID=$1</Instead>
</Rule>
</Rules>
</UrlRewriteConfig>
接下来还需要在web.config里加上
 <httpModules>
  <add type="UrlRewriteHttpModule.HttpModuleUR,UrlRewriteHttpModule" name="gdpz"/>
  </httpModules>
把UrlRewriteHttpModule编译后放到bin/gac,见一个test.aspx好了ok.
不过这里还要处理回传,需要重写form类,不然回传后的页面仍然是test.aspx,原因是重写后
的Url会付值到Request中,那么用的浏览器仍然会是不友好的URL,同时URL的改变会使用户不安,
所以需要重写系统表单类的RenderAttrubute使他不要修改属性。
处理了回传,但是并没有实际goodbaby目录,一个办法是建立一个,但是想象一个拥有很多用户的
站点都建立一个目录,那是很dirty的,所以要使用虚拟多用户,通过架空IIS,在IIS中添加对*扩展
名的映射这样就把处理都交给了asp.net,不然会出现http 404错误,好了就这样吧。入门学习,请大家讨论指正。


参考文献: www.microsoft.com/china/libruray/webservice/asp.net/urlrewrite.aspx