Server.TransferRequest for IIS 6

2019-07-20 06:37发布

问题:

Is there a way to fake the behavior of TransferRequest in IIS 6? Specifically the ability to re-process the whole pipeline without the client having to make a new request?

I'm trying to handle a 404 error from Application_Error, do some magic to see if the URL changed (in which case I use Response.Redirect to redirect to the new URL) but if there really is a 404 I want to serve up my pretty looking 404 page which has to deal with showing some content which is part of the users session.

The problem is that if I use Server.Transfer, The request context is null at this point so my 404 page crashes. I don't want to use Request.Redirect because I want the browser URL to still be on the missing URL so the 404 status code gets interpreted properly for the missing resource.

On IIS 7 I can use TransferRequest which does exactly what I want. The browser retains the missing URL and Session context is available for the 404 page code. So is there a way to do something similar with IIS 6? (TransferRequest is only available in IIS 7 in Pipeline mode and our production servers are still on IIS 6)

回答1:

One possible solution is to make your redirect with a flag, and then make RewritePath on BeginRequest.

For example, you place this code on Global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    if (HttpContext.Current.Request.RawUrl.EndsWith("error"))
    {
        HttpContext.Current.RewritePath("404CoolPage.aspx", false);
    }


    // .... rest code   
}

and you make the redirect on your

void Application_Error(object sender, EventArgs e) 
{

    //... code

    if(System.Web.HttpContext.Current.Request.QueryString.Count > 0)        
        Response.Redirect(HttpContext.Current.Request.RawUrl + "&error");
    else
        Response.Redirect(HttpContext.Current.Request.RawUrl + "?error");   
}

This way, you make the redirect, and you keep the url as it is.

My Error Setup

By the way, I use the the Server.Transfer and Its working to me. This is my Error setup and the Transfer is done using the server, I am not sure where your page have problem with the request context

void Application_Error(object sender, EventArgs e) 
{
    // ... log the errors ...
    string cTheFile = HttpContext.Current.Request.Path;
    // in case the error is inside the 404CoolError.aspx
    // I check for not calling my self and get a dead loop.
    if(!cTheFile.EndsWith("404CoolError.aspx"))
        Server.Transfer("~/404CoolError.aspx");
}

and on web.config

<customErrors redirectMode="ResponseRewrite" ... />


回答2:

From what I gather there is no standard way to simulate TransferRequest on IIS 6 - at least not without a major rewrite of most of your code.

the only other options available (besides Transfer which you pointed out that it does not do what you need) are:

  • Excute
  • RewritePath

I would suspect that with some fiddling you could create a solution which is as close as you can get with IIS6 using Execute although I am not sure that performance will be good.

Regarding RewritePath you could start with with something like this and extend it to to do what you want:

HttpContext.Current.RewritePath(url, false);
IHttpHandler httpHandler = new YourHTTPHandler(); // use your HttpHandler !
httpHandler.ProcessRequest(HttpContext.Current);


回答3:

You could set up a custom error handler in IIS. In the web site properties page, on the custom errors tab, edit '404' and set it to '404.aspx' (or whatever). Move your 'magic' code to the 404 page. If you find a real 404, then there is no need to 'transfer' anywhere - just let your page display.