使用HTTP模块在ASP.NET 3.5和IIS 7中重写URL

Wal*_*art 3 iis-7 http url-rewriting httpmodule

我正在ASP.NET 3.5和IIS 7中开发一个应用程序.我编写了一个HTTP模块来执行URL重写,例如,我想将用户名重写为帐户ID"〜/ Profiles/profile.aspx?AccountID =" + account.AccountID.ToString();

见下文:

使用系统; 使用System.Collections.Generic; 使用System.Data; 使用System.Configuration; 使用System.IO; 使用System.Linq; 使用System.Web; 使用System.Web.Security; 使用System.Web.UI; 使用System.Web.UI.HtmlControls; 使用System.Web.UI.WebControls; 使用System.Web.UI.WebControls.WebParts; 使用System.Xml.Linq;

public class UrlRewrite : IHttpModule
{
    private AccountRepository _accountRepository;
    private WebContext _webContext;

    public UrlRewrite()
    {
        _accountRepository = new AccountRepository();
        _webContext = new WebContext();
    }

    public void Init(HttpApplication application)
    {
        // Register event handler.
        application.PostResolveRequestCache +=
            (new EventHandler(this.Application_OnAfterProcess));
    }

    public void Dispose()
    {
    }

    private void Application_OnAfterProcess(object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;

        string[] extensionsToExclude = { ".axd", ".jpg", ".gif", ".png", ".xml", ".config", ".css", ".js", ".htm", ".html" };
        foreach (string s in extensionsToExclude)
        {
            if (application.Request.PhysicalPath.ToLower().Contains(s))
                return;
        }

        if (!System.IO.File.Exists(application.Request.PhysicalPath))
        {
            if (application.Request.PhysicalPath.ToLower().Contains("blogs"))
            {

            }
            else if (application.Request.PhysicalPath.ToLower().Contains("forums"))
            {

            }
            else
            {

                string username = application.Request.Path.Replace("/", "");

                Account account = _accountRepository.GetAccountByUsername(username);

                if (account != null)
                {
                    string UserURL = "~/Profiles/profile.aspx?AccountID=" + account.AccountID.ToString();
                    context.Response.Redirect(UserURL);
                }
                else
                {
                    context.Response.Redirect("~/PageNotFound.aspx");
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我需要在web.config中引用这个Handler来使它工作,但我不知道我需要在web.config文件中输入什么以及在哪里.有人可以帮帮我吗.此外,是否需要任何其他配置才能使其工作?我需要配置IIS吗?

提前致谢.

问候

沃尔特

Ste*_*las 6

取决于您使用的是IIS7 Classic还是集成管道模式.使用Integrated Pipeline模式执行此操作的标准方法如下:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </modules>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

但为了安全起见,您可能希望在IIS5/6上支持IIS7 Classic/Integrated和优雅降级的组合(如果您的开发框使用不同的操作系统),Rick Strahal建议在Web配置上使用以下代码来支持和绕过IIS引发的令人讨厌的错误,如果你使它向后兼容:

<system.web>
  <httpModules>
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </httpModules>
</system.web>
<system.webServer>
  <validation validateIntegratedModeConfiguration="false"/>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </modules>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

您还会注意到runAllManagedModulesForAllRequest ="true"的添加,这是相关的,否则您的HttpModule中的代码只会在浏览器调用由.NET管理的.aspx,.ashx,.asmx等文件时执行.框架.

此外,为了实际重写url(而不是重定向用户),您需要context.RewritePath(string)在事件处理程序中使用该方法.

它的工作方式是application.Request.Path带有一个'友好'字符串,我想你在你的应用程序中看起来像这样:

http://www.domain.com/robertp

哪个被重写如下:

http://www.domain.com/Profiles/profile.aspx?AccountID=59

要做到这一点而不是使用context.Response.Redirect()你将需要使用context.RewritePath()如下:

string UserURL = "~/Profiles/profile.aspx?AccountID=" + account.AccountID.ToString();
context.RewritePath(UserURL);
Run Code Online (Sandbox Code Playgroud)

... TADA !!

这应该确保传递到服务器的URL是profiles.aspx?AccountID=59用户robertp在浏览器上获得更友好的URL .

至于配置选项,只要你坚持使用IIS7就可以使用上面的web配置设置了.当您尝试在运行IIS6或IIS5的Dev PC上进行测试时,您可能会遇到问题,这通常会围绕robertp这样一个事实:没有可识别的文件扩展名,因此除非您添加文件扩展名,否则不会执行HttpModule代码使用.NET ISAPI.

希望这很有用.