k, I understand you might feel lethargic while viewing this blog of mine thinking, here again the same old crap about server.transfer and response.redirect.
Don't know how many links you would already have found if you did search on the above commands. I at least found two dozens of them.
So here I am not going to talk not about what they mean but a little weird scenario when it comes to using Request properties like Request.CurrentExecutionFilePath.
We had a customer who had written his own custom HTTP Module which intercepts request and response for Asp.Net pages.
Now, in his HTTP Module, he was trying to access the Request.CurrentExecutionFilePath property. Simple!
The problem arises when you use the above mechanisms, especially using Server.Transfer.
We know that in Response.Redirect the request flows between client and the server until we get the right path for the requested page.
Client Server
GET /redirecttransfer/default.aspx HTTP/1.1 HTTP/1.1 302 Found
Location: /redirecttransfer/Default2.aspx
GET /redirecttransfer/Default2.aspx HTTP/1.1 HTTP/1.1 302 Found
Location: /redirecttransfer/default3.aspx
GET /redirecttransfer/default3.aspx HTTP/1.1 HTTP/1.1 200 OK
So here we have a complete round trip between the server and the client. The Request will have all the information about the requested page, accordingly we should get the right value in Request.CurrentExecutionFilePath (which should be Default3.aspx here). But what happens if you try to read the same property when using Server.Transfer instead of Response.Redirect?
Let's say the request flow is: Default.aspx >>--Server.Transfer--> Default2.aspx >>--Server.Transfer--> Default3.aspx
Now in the HTTPModule under Application_EndRequest method, if we try to display the Request.CurrentExecutionFilePath property, what should we see?
Guess....should it be Default.aspx, or Default2.aspx or Default3.aspx or something else altogether.
Check it yourself, I am adding a sample HTTPModule here:
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule" }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(this.Application_BeginRequest);
application.EndRequest += new EventHandler(this.Application_EndRequest);
}
private void Application_BeginRequest(Object source, EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1><font color=red>HelloWorldModule: Beginning of Request</font></h1><hr>");
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write(context.Request.CurrentExecutionFilePath+"</br><hr><h1><font color=red>HelloWorldModule: End of Request</font></h1>");
}
public void Dispose()
{
}
}
Also let's say you have default.aspx, default2.aspx and default3.aspx as shown above in the flow diagram. We do a server.transfer from default.aspx to default2.aspx, which in turn does a server.transfer to default3.aspx page.
Here are the codes:
Default.aspx
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Request.CurrentExecutionFilePath);
Server.Transfer("Default2.aspx");
}
}
Default2.aspx
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Request.CurrentExecutionFilePath);
Server.Transfer("default3.aspx");
}
}
Default3.aspx
public partial class Default3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Request.CurrentExecutionFilePath);
}
}
You will notice that when you try to access the default.aspx page it does the server.redirect to default2.aspx which in turn again redirects to default3.aspx page and then finally the httpmodule displays the following:
Now if you notice the HTTP Module displays /Default.aspx and not /default2.aspx or /default3.aspx.
What can be the reason behind it. If you notice the Request.FilePath associated with Httpmodule is still /Default.aspx and not any of /default2.aspx or /default3.aspx page. The reason being that in addition to being faster than redirection, server.transfer preserves all of the ASP built-in objects from the original request, including form values from an HTTP post. The moment we have server.transfer in our code the currently executing request will stop and will forward the request to the new page.
The new request also gets the original response stream further ahead for processing. Hence the property Request.CurrentExecutionFilePath will be same as the executing page when accessed in one of the above page class methods, but will be equal to the original request property if accessed in an HTTP Module. You can also consider it logically, why should there be a value for Request.CurrentExecutionFilePath in an HttpModule, it is called before or after the pages have been processed. So ideally it is not in context of any specific page. Hence it will show you the original page based on the assumption that the request was sent for the same page.
Author: Saurabh Singh
Published Feb 16, 2019
Version 1.0Jawahar Ganesh S
Microsoft
Joined September 22, 2018
IIS Support Blog
Follow this blog board to get notified when there's new activity