IIS7, RewritePath and IIS log files

笑着哭i 提交于 2019-12-02 21:03:32

After some research, I've finally found a solution to the problem.

I have replaced the calls to Context.RewritePath() method with the new (introduced in ASP.NET 3.5) Context.Server.TransferRequest() method.

It seems obvious now, but not event Senior Dev Engineer on IIS Core team thought of that.

I've tested it for session, authentication, postback, querystring, ... issues and found none.

Tommorow I'll deploy the change to a very hight traffic site, and we'll soon know how it actually works. :)

I'll be back with the update.

The update: the solution is still not entirely on my production servers but it's tested and it does work and as far as I can tell so far, it's a solution to my problem. If I discover anything else in production, I will post an update.

The final update: I have this solution in production for over a year and it has proven to be a good and stable solution without any problems.

You could set the path back to the original value after the request has been processed but before the IIS logging module writes the log entry.

For example, this module rewrites the path on BeginRequest and then sets it back to the original value on EndRequest. When this module is used the original path appears in the IIS log file:

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()
    {

    }
}

I've had exactly the same problem. One way around this is to use Server.Transfer instead of Context.RewritePath. Server.Transfer doesn't restart the entire page lifecycle so the original URL will still be logged. Be sure to pass "true" for the "preserveForm" parameter so that the QueryString and Form collections are available to the 2nd page.

Old question, but I found I did not encounter your problem when I did the following:

a) A rewrite rule in web.config to direct all requests to /default.aspx, eg:

    <rule name="all" patternSyntax="Wildcard" stopProcessing="true">
      <match url="*"/>
      <action type="Rewrite" url="/default.aspx"/>
    </rule>

b) Called RewritePath in the Page_PreInit event of default.aspx, to rewrite the URL and querystring as what was passed in the request (ie. the location that doesn't exist).

For example, I request "/somepage/?x=y" (which doesn't exist).

a) Web.config rule maps it to /default.aspx

b) Page_PreInit rewrites it back to "/somepage/?x=y".

The result of this, in IIS 7 (Express and production) is that the server log reflects "/somepage" for stub and "x=y" for query, and all the Request object properties reflect the requested (non-existent) URL (which is what I wanted).

The only weird effect is, in IIS Express, the log item is written twice. However this doesn't happen in production (Windows Server 2008 R2).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!