IIS7、RewritePath 和 IIS 日志文件
Posted
技术标签:
【中文标题】IIS7、RewritePath 和 IIS 日志文件【英文标题】:IIS7, RewritePath and IIS log files 【发布时间】:2010-09-26 02:17:47 【问题描述】:我在 IIS7 上运行的 ASP.NET 3.5 应用程序中使用 Context.RewritePath()。
我在应用程序 BeginRequest 事件中执行此操作,并且一切正常文件。
对 /sports 的请求被正确地重写为 default.aspx?id=1,依此类推。
问题在于,在我的 IIS 日志中,我看到 GET 请求是针对 /Default.aspx?id=1 而不是针对 /sports。
这种代码在 IIS6 下完美运行。
由于必须实现一些业务逻辑,因此不能选择使用 Microsoft Rewrite 模块。
谢谢。
编辑:
似乎我的处理程序在管道中为时过早,但如果我将逻辑移至稍后的事件,那么整个重写操作将不起作用(为时已晚,StaticFileHandler 会接收我的请求)。
我用谷歌搜索和搜索,四处询问,不敢相信没有人有这个问题?
编辑:
哎呀!这是我在 IIS 论坛上找到的:
“这是因为在集成模式下,IIS 和 asp.net 共享一个公共管道,并且 RewritePath 现在被 IIS 看到,而在 IIS6 中,它甚至没有被 IIS 看到 - 您可以通过使用经典模式来解决这个问题会表现得像 IIS6。”
最终更新:请看my answer below,我在生产环境一年多后更新了结果。
【问题讨论】:
我会(并且已经)通过反射器查看 System.Web.Routing 程序集。看看在哪里连接它。 IIRC,您需要在 PostMapRequestHandler 和 PostAcquireRequestState 处进行。 我确实尝试过,正如我在编辑中所写的那样,但该事件在管道中为时已晚...... 我重读了您的更新。有没有办法在应用程序的某处附加事件处理程序?我的意思是请求必须在某个地方结束。我的自定义重写实验也被证明是困难的。 我尝试了几乎所有的事件。要么我失去日志记录,要么重写太晚,要么我失去会话状态...... :(我不敢相信没有人有这些问题? Muerte,正确的做法是回答你自己的问题。您说通过将 IIS 7 置于经典模式可以解决此问题,该模式的执行方式与 IIS 6 相同。只要您意识到这样做不会从新 IIS 7 中的安全性或性能升级中受益这似乎是一个合理的答案。 【参考方案1】:您可以在处理请求后但在 IIS 日志记录模块写入日志条目之前将路径设置回原始值。
例如,此模块重写BeginRequest
上的路径,然后将其设置回EndRequest
上的原始值。使用此模块时,原始路径会出现在 IIS 日志文件中:
public class RewriteModule : IHttpModule
public void Init(HttpApplication context)
context.BeginRequest += OnBeginRequest;
context.EndRequest += OnEndRequest;
static void OnBeginRequest(object sender, EventArgs e)
var app = (HttpApplication)sender;
app.Context.Items["OriginalPath"] = app.Context.Request.Path;
app.Context.RewritePath("Default.aspx?id=1");
static void OnEndRequest(object sender, EventArgs e)
var app = (HttpApplication)sender;
var originalPath = app.Context.Items["OriginalPath"] as string;
if (originalPath != null)
app.Context.RewritePath(originalPath);
public void Dispose()
【讨论】:
是的,我已经在 Vista 上使用 IIS 7 对其进行了测试,并检查了网页是否看到了重写的路径,但原始路径是否已写入 IIS 日志文件。但我还没有对这样做可能产生的副作用进行任何详细的测试。【参考方案2】:我也遇到过同样的问题。解决此问题的一种方法是使用 Server.Transfer 而不是 Context.RewritePath。 Server.Transfer 不会重新启动整个页面生命周期,因此仍会记录原始 URL。请务必为“preserveForm”参数传递“true”,以便 QueryString 和 Form 集合可用于第二页。
【讨论】:
【参考方案3】:经过一番研究,我终于找到了解决问题的方法。
我已经用新的(在 ASP.NET 3.5 中引入)Context.Server.TransferRequest() 方法替换了对 Context.RewritePath() 方法的调用。
现在看起来很明显,但 IIS 核心团队的高级开发工程师没有想到这一点。
我已经针对会话、身份验证、回发、查询字符串等问题对其进行了测试,但没有发现任何问题。
明天我会将更改部署到一个流量非常大的站点,我们很快就会知道它的实际工作原理。 :)
我会回来更新的。
更新:该解决方案仍未完全在我的生产服务器上,但它已经过测试并且确实有效,据我所知,它是我的问题的解决方案。如果我在生产中发现任何其他内容,我会发布更新。
最终更新:我在生产中使用了这个解决方案一年多了,它已被证明是一个良好且稳定的解决方案,没有任何问题。
【讨论】:
为什么看起来这么明显?【参考方案4】:老问题,但是当我执行以下操作时,我发现我没有遇到您的问题:
a) web.config 中的重写规则,用于将所有请求定向到 /default.aspx,例如:
<rule name="all" patternSyntax="Wildcard" stopProcessing="true">
<match url="*"/>
<action type="Rewrite" url="/default.aspx"/>
</rule>
b) 在 default.aspx 的 Page_PreInit
事件中调用 RewritePath,将 URL 和查询字符串重写为请求中传递的内容(即不存在的位置)。
例如,我请求“/somepage/?x=y”(不存在)。
a) Web.config 规则将其映射到 /default.aspx
b) Page_PreInit 将其重写为“/somepage/?x=y”。
这样做的结果,在 IIS 7(Express 和生产)中,服务器日志反映了存根的“/somepage”和查询的“x=y”,并且所有请求对象属性都反映了请求(不存在) URL(这是我想要的)。
唯一奇怪的效果是,在 IIS Express 中,日志项被写入了两次。但是,这不会在生产环境中发生(Windows Server 2008 R2)。
【讨论】:
以上是关于IIS7、RewritePath 和 IIS 日志文件的主要内容,如果未能解决你的问题,请参考以下文章
IIS7 的 UnauthorizedAccessException