Having studied the source code of the framework, I can explain why it Response.Redirect(url, true)continues to execute the code after calling in Session_Start(), but not in the normal code behind.
Response.Redirect()ultimately calls an internal overloaded method Redirect():
internal void Redirect(string url, bool endResponse, bool permanent)
{
if (endResponse)
{
this.End();
}
}
At the end of this method, if endResponsetrue, is called Response.End(). When we look at Response.End(), we see the following code:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
The method checks the status of the current context value IsInCancellablePeriod. This value is internal, but we can see it in our debugger:
If we set a breakpoint inside Session_Start()and examine the current context of the IsInCancellablePeriodinvisible member, we will see:

, , Response.Redirect() , endResponse .
ASPX- Page_Load(), - :

IsInCancellablePeriod true, Thread.CurrentThread.Abort(), Response.Redirect() .
, , :
Session ( )
Response.Redirect() Session_Start(), If...Then...Else:
If <some_condition_we_have_to_redirect_for> Then
Response.Redirect("~/Blog.aspx")
Else
End If