views:

2306

answers:

6

Hi,

I am using Context.RewritePath() in ASP.NET 3.5 application running on IIS7.

I am doing it in application BeginRequest event and everything works file.

Requests for /sports are correctly rewritten to default.aspx?id=1, and so on.

The problem is that in my IIS log I see GET requests for /Default.aspx?id=1 and not for /sports.

This kind of code worked perfectly under IIS6.

Using Microsoft Rewrite module is not an option, due to some business logic which has to be implemented.

Thanks.

EDIT:

It seems my handler is too early in the pipeline, but if I move the logic to a later event, than the whole rewrite thing doesn't work (it's too late, StaticFileHandler picks up my request).

I googled and googled, asked around, can't believe that nobody has this problem?

EDIT:

Yikes! Here's what I found on the IIS forum:

"This is because in integrated mode, IIS and asp.net share a common pipeline and the RewritePath is now seen by IIS, while in IIS6, it was not even seen by IIS - you can workaround this by using classic mode which would behave like IIS6."

A: 

I would (and have) just look at the System.Web.Routing assembly via Reflector. To see where to hook it up.

IIRC, you need to do it at PostMapRequestHandler and PostAcquireRequestState.

leppie
I did try that, as I wrote in my EDIT, but that event is too late in the pipeline...
muerte
I reread your updates. Is there no way you can attach an event handler somewhere in the application? I mean the request must end somewhere. My experimentation with custom rewriting also proved hard.
leppie
I tried almost all events. Either I loose logging, either the rewriting is too late, or I loose session state... :( I can't believe NOBODY had these issues?
muerte
A: 

Muerte, the correct way to do this would be to answer your own question.

You stated that this issue can be correct by placing IIS 7 into classic mode which will perform the same way as IIS 6. As long as you realize you won't benefit from the security or performance upgrades in the new IIS 7 by doing this then it seems like a reasonable answer.

Spence
I understand that I can answer my own question, but I don't consider this as an answer at all and I'm still pursuing the quest. :) I'm trying out some things, and I'll definitely add my result, either as an answer or as a final edit to my question.
muerte
+3  A: 

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

    }
}
Daniel Richardson
Does this actually work?
Dscoduc
Yes I've tested it on Vista with IIS 7 and checked that the web page saw the rewritten path but that the original path was written to the IIS log file. But I haven't done any detailed testing of what side effects doing this might have.
Daniel Richardson
+1  A: 

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.

David
+1  A: 

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.

muerte
A: 

This problem is also evident if you use the URL Mapping feature of ASP.NET 2.0. Under II7 Integrated mode. IIS log will report MyPage.aspx?id=1234 as opposed to the mapped url as it does correctly under classic mode.

Any suggestions/ideas other than running the app pool under classic mode?

ANY HELP APPRECIATED.

Jamie