之前一直以为Response.Redirect (“default1.aspx”)的运行原理是这样的030003571.jpg

但经过断点测试发现不是,当程序执行到Response.Redirect (“default1.aspx”);时 下边会跳转到default1.aspx下的Page_Load()方法中。也就是说2,3根本没有运行,只有1跟4,浏览器在根据4返回的状态码来在前台地址栏显示出不同的url,说到这里了 咱们就反编译一把Response.Redirect看看里面的具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
internalvoidRedirect( string  url,  bool  endResponse,  bool  permanent)
{
     if  (url ==  null )
     {
         thrownewArgumentNullException( "url" );
     }
     if  (url.IndexOf( '\n' ) >= 0)
     {
         thrownewArgumentException(SR.GetString( "Cannot_redirect_to_newline" ));
     }
     if  ( this ._headersWritten)
     {
         thrownewHttpException(SR.GetString( "Cannot_redirect_after_headers_sent" ));
     }
     Pagepage =  this ._context.HandlerasPage;
     if  ((page !=  null ) && page.IsCallback)
     {
         thrownewApplicationException(SR.GetString( "Redirect_not_allowed_in_callback" ));
     }
     url =  this .ApplyRedirectQueryStringIfRequired(url);
     url =  this .ApplyAppPathModifier(url);
     url =  this .ConvertToFullyQualifiedRedirectUrlIfRequired(url);
     url =  this .UrlEncodeRedirect(url);
     this .Clear();
     if  (((page !=  null ) && page.IsPostBack) && (page.SmartNavigation && ( this .Request[ "__smartNavPostBack" ] ==  "true" )))
     {
         this .Write( "<BODY><ASP_SMARTNAV_RDIR url=\"" );
         this .Write(HttpUtility.HtmlEncode(url));
         this .Write( "\"></ASP_SMARTNAV_RDIR>" );
         this .Write( "</BODY>" );
     }
     else
     {
         this .StatusCode = permanent ? 0x12d : 0x12e;
         this .RedirectLocation = url;
         if  (UriUtil.IsSafeScheme(url))
         {
             url = HttpUtility.HtmlAttributeEncode(url);
         }
         else
         {
             url = HttpUtility.HtmlAttributeEncode(HttpUtility.UrlEncode(url));
         }
         this .Write( "<html><head><title>Object moved</title></head><body>\r\n" );
         this .Write( "<h2>Object moved to <a href=\""  + url +  "\">here</a>.</h2>\r\n" );
         this .Write( "</body></html>\r\n" );
     }
     this ._isRequestBeingRedirected =  true ;
     EventHandlerredirecting = Redirecting;
     if  (redirecting !=  null )
     {
         redirecting( this , EventArgs.Empty);
     }
     if  (endResponse)
     {
         this .End();
     }
}

其中由37,38行的

this .StatusCode = permanent ? 0x12d : 0x12e;
this .RedirectLocation = url;

可以看出状态码和跳转地址是在这里赋值的,我邪恶的感觉到扩展IhttpModule可以拦截http状态码,使用js代码段来实现http页面的跳转,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Web;
namespace  ClassLibrary2
{
     public  class  Class1 : System.Web.IHttpModule
     {
         public  void  Init(HttpApplication application)
         {
             application.PreSendRequestHeaders +=  new  EventHandler(application_PreSendRequestHeaders);
         }
         private  void  application_PreSendRequestHeaders( object  sender, EventArgs e)
         {
             HttpApplication Application = (HttpApplication) sender;
             HttpContext context = Application.Context;
             if  (context.Response.StatusCode == 302)
             {
                 context.Response.Write( "<script>window.open(’"  + context.Response.RedirectLocation +  "’)</script>" );
                 context.Response.StatusCode = 200;
             }
         }
     }
}
  

然后再配置一下web.config

1
2
3
4
5
6
7
8
9
10
<? xml  version = "1.0" ?>
  < configuration >
  < system.web >
  < compilation  debug = "true" />
  < authentication  mode = "Windows" />
  < httpModules >
  < add  name = "MyModule"  type = "ClassLibrary2.Class1,ClassLibrary2" ></ add >
  </ httpModules >
  </ system.web >
  </ configuration >