65.9K
CodeProject 正在变化。 阅读更多。
Home

在不使用 ISAPI Handler 或 Wildcard Mapping 的情况下提供无扩展名 URL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (9投票s)

2007年12月29日

CPOL

4分钟阅读

viewsIcon

157944

在不使用自定义 ISAPI 处理器或 IIS 6.0 通配符映射的情况下,从 IIS 提供无扩展名 URL

问题

如果您想从 ASP.NET 2.0 提供类似以下的无扩展名 URL

  • www.store.com/books
  • www.store.com/books/asp.net2.0
  • www.forum.com/post/how-to-serve-extensionless-url

您无法做到,除非您使用某个 第三方 ISAPI 模块或使用 IIS 6.0 通配符映射功能。第三方 ISAPI 模块需要直接安装在服务器上。如果您没有专用服务器或虚拟机,无法安装 ISAPI 模块,则无法采用此方法。此外,ISAPI 模块会拦截所有请求,因此安装的模块越多,每个请求的速度就越慢。另一方面,IIS 6.0 通配符映射会使所有请求都通过 ASP.NET 2.0 ISAPI 处理器,包括带有 .gif.css.js.html 等扩展名的 URL。因此,它存在可伸缩性问题。一些独立研究表明,在使用通配符映射时,IIS 6.0 的性能会下降 30%。因此,这也不是一个好解决方案。

解决方案

这里有一个方法,可以在 IIS 6.0 中不使用 ISAPI 模块或通配符映射的情况下工作。当您请求无扩展名 URL 时,会收到 HTTP 404 页面。这意味着 IIS 接收到请求,并提供为 HTTP 404 配置的页面。通常这是一个位于 IIS 目录下的 404.html 文件。IIS 不会将请求发送到 ASP.NET 处理器,因此您无法拦截 404 请求。所以,如果您可以将所有 HTTP 404 请求转发到 ASP.NET,就可以提供此类无扩展名 URL。为了将 HTTP 404 转发到 ASP.NET ISAPI,您只需将 IIS 配置为在命中缺失的无扩展名 URL 时重定向到某个 .aspx 扩展名。

此方法的优点

  • 无需第三方 ISAPI 模块。因此没有安装问题,没有请求拦截延迟
  • 没有通配符映射,因此不会牺牲 ASP.NET 的性能

以下是在 IIS 6.0 中配置 404 重定向的方法

在 IIS 6.0 上,将 404 默认页面更改为 /404.aspx,类型更改为“URL”。在 IIS 7.0 上,将 404 默认页面更改为 /404.aspx,类型更改为“ExecuteURL”。另外,将默认错误响应更改为“自定义错误页面”。

iis7.png

当您请求“www.shop.com/products/books”之类的 URL 时,它会重定向到“www.shop.com/404.aspx?404;http://www.shop.com/products/books”。从 Global.asax BeginRequest 事件中,捕获此 URL,并检查它是否是无扩展名 URL 请求。如果是,则对该无扩展名 URL 执行 URL 重写操作。

   1: protected void Application_BeginRequest(object sender, EventArgs e)
   2: {
   3:     string url = HttpContext.Current.Request.Url.AbsolutePath;
   4:
   5:     // HTTP 404 redirection for extensionless URL or some missing file
   6:     if (url.Contains("404.aspx"))
   7:     {
   8:         // On 404 redirection, query string contains the original URL in this format:
   9:         // 404;https://:80/Http404Test/OmarALZabir
  10:
  11:         string[] urlInfo404 = Request.Url.Query.ToString().Split(';');
  12:         if (urlInfo404.Length > 1)
  13:         {
  14:             string originalUrl = urlInfo404[1];
  15:
  16:             string[] urlParts = originalUrl.Split('?');
  17:
  18:             string queryString = string.Empty;
  19:             string requestedFile = string.Empty;
  20:
  21:             if (urlParts.Length > 1)
  22:             {
  23:                 requestedFile = urlParts[0];
  24:                 queryString = urlParts[1];
  25:             }
  26:             else
  27:             {
  28:                 requestedFile = urlParts[0];
  29:             }
  30:
  31:             if( requestedFile.IndexOf('.') > 0 )
  32:             {
  33:                 // There's some extension, so this is not an extensionless URL.
  34:                 // Don't handle such URL because these are really missing files
  35:             }
  36:             else
  37:             {
  38:                 // Extensionless URL. Use your URL rewriting logic to handle such URL
  39:                 // I will just add .aspx extension to the extension less URL.
  40:                 HttpContext.Current.RewritePath(requestedFile + 
					".aspx?" + queryString);
  41:             }
  42:         }
  43:     }
  44: } 

上面的代码会查找请求但导致 HTTP 404 的虚拟目录名称,例如 /omar。从重定向的 URL 中,它会解析并找到缺失的文件夹名称。然后,它会将文件夹重写为可以处理缺失 URL 请求的 .aspx 文件扩展名。您可以执行不同的操作,例如重写到带有查询参数的 Default.aspx,重定向到另一个页面,依此类推。

我们在 Pageflakes 中使用了这种方法。您可以访问像 www.pageflakes.com/omar 这样的 URL,并让我们的主页处理该 URL。

此解决方案对搜索引擎友好,因为没有人会看到 HTTP 404。您可以使用 Fiddler 等工具进行测试,并查看缺失的 URL 请求不会产生 HTTP 404 或任何重定向。响应头将是 HTTP 200,重写后的页面内容将作为响应体出现。因此,搜索引擎优化 (SEO) 没有问题。

注意事项

缺少图形、CSS 和 JavaScript

浏览器将缺失的 URL 视为一个文件夹,因此会从此 URL 请求所有相对文件(图形、css、js)。因此,如果您的网站上有一个位于 images/test.gif 位置的图形,并且您访问 www.pageflakes.com/omar URL,则浏览器将从 www.pageflakes.com/omar/images/test.gif 位置请求该图形。

解决方案是使用 <base> 标签并指定从中获取所有相对 URL 的正确位置。例如,您可以设置 <base href="http://www.pageflakes.com/">。这将强制浏览器假设页面是从根文件夹提供的,因此会从根 URL 转换所有相对 URL。因此,图形 URL 将被转换为 www.pageflakes.com/images/test.gif,这是正确的 URL。

Postback 显示难看的 URL

另一个问题与 postback 相关。当您重写到 .aspx 页面时,form 标签将根据 .aspx 页面的路径生成,而不是 URL 重写之前的路径。例如,重写到 somepage.aspx 将呈现一个 form 标签,其中 action 属性设置为 somepage.aspx。因此,postback 会将浏览器重定向到 somepage.aspx

您可以使用 Scott Gu 在 这里 提供的解决方案。

AJAX 停止工作

当 AJAX 框架无法从正确 URL 下载,并且异步 postback 发送到与您预期不同的 URL 时,就会发生此类问题。因此,您需要使用 <base> 标签来生成 AJAX 框架需要下载的正确 URL,然后重写 form action 标签以使异步 postback 发送到正确的 URL。

© . All rights reserved.