locked
redirectMode="ResponseRewrite" disables HttpContext.Current.Session RRS feed

  • Question

  • User473663573 posted

    Hi,


    we render a nice error page which uses quite a lot of code in the background. I tried adding redirectMode="ResponseRewrite" to the customErrors section in the web.config, but then the framework returns null from HttpContext.Current.Session. Therefore some of our code does not work anymore. When redirectMode is not set or set to ResponseRedirect then HttpContext.Current.Session is set.

    How can we circumvent this?


    Cheers,

    Michael

    Wednesday, September 22, 2010 6:10 AM

All replies

  • User2060565753 posted

    What's happening is IIS is seing the error status code and presenting it's own error page instead of yours. To solve you need to set this in the code behind page of your error page to prevent IIS from doing this:

    Response.TrySkipIisCustomErrors = true;
    Wednesday, September 22, 2010 6:26 AM
  • User473663573 posted

    I'm still running IIS 6. Furthermore IIS does not overwrite my error page like in the problem on stackoverflow. My error page is run, but Session is null.

    Only when it tries to access HttpContext.Current.Session the error page throws an exception and then IIS renders its own error page. But this is not the problem.


    I could change the code now to remove

    HttpContext.Current.Session      and

    (HttpContext.Current.Handler as System.Web.UI.Page).Request    (I didn't write this one so don't tell me that it could be done easier ;-) )

    cause both calls return null. Now the error page doesn't throw an exception anymore and IIS renders it.

    Wednesday, September 22, 2010 7:41 AM
  • User2060565753 posted

    How the error page doesn't throw an exception anymore and IIS renders it.

    how u resolved it
     

    Wednesday, September 22, 2010 8:36 AM
  • User473663573 posted

    Like I said before. I changed the code in order to work even when those properties are null.

    <strike>Another problem/strange behavior which I saw with redirectMode="ResponseRewrite" is that IIS 6 behaves differently when I request http://mydomain/gfdgfdgfd or http://mydomain/gfdgfdgfd.aspx . The former does the ResponseRewrite. I.e. the url in the browser stays the same and the request returns 404. But the latter ignores the ResponseRewrite and still does a redirect to error.aspx?aspxerrorpath=/gfdgfdgfd.aspx . Only this second request returns the 404. It would be nicer if both act the same.</strike>

    Sorry, that was a mistake. I copied ResponseRedirect in my redirectMode again.

    Thursday, September 23, 2010 4:05 AM
  • User473663573 posted

    Unfortunately I found another problem with redirectMode="ResponseRewrite" (now that I activated it again - shame on me).

    The AquireRequestState event of my HttpApplication is not run when I request http://mydomain/foobar.aspx. But when I access http://mydomain/foobar (without the .aspx suffix), then it is called. This is probably also the reason for HttpContext.Current.Session being null. Although I can work around the latter, I do need my own Session object which is (you would not believe it) aquired in AquireRequestState.

    Thursday, September 23, 2010 10:18 AM
  • User713056278 posted

    Hi,

    Please check the links below,hope it can help you.

    http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

    http://forums.asp.net/p/1234740/2238219.aspx

    The code sample under the link.

    namespace MyModules
    {
        public class ReWriteModule : IHttpModule
        {
            private HttpApplication _context;
    
            public void Dispose()
            {
                _context.Dispose();
            }
    
            public void Init(HttpApplication context)
            {
                _context = context;
                context.AcquireRequestState += new EventHandler(Application_AcquireRequestState);
                context.BeginRequest += new EventHandler(Application_BeginRequest);
            }
    
            private void Application_BeginRequest(object sender, EventArgs e)
            {
                throw new NotImplementedException();
            }
    
            private void Application_AcquireRequestState(object sender, EventArgs e)
            {
                if (_context.Request.Path.ToString().Contains("aspx"))
                {
                    _context.Context.RewritePath("New Path");
                    _context.Session["MySession"] = "Hello";
                }
            }
        }
    }
    


     

    Monday, September 27, 2010 9:30 AM
  • User473663573 posted

    I guess you didn't understand the problem. I don't want to rewrite the url manually. The framework does that automatically because I added redirectMode="ResponseRewrite" to the customErrors as we were told by ScottGu.


    To make it simple I created a sample application to show the problem.

    As you might see from the following steps, I run this on Win2003 with IIS6 and .NET Framework 3.5 SP1 (4.0 also installed, but not used yet).


    Here are the steps to reproduce:

    - open up VS2010 and create a new ASP.NET Web Application. This already gives us a web.config, default.aspx and global.asax.

    - change the target framework to 3.5

    - add this code to default.aspx.cs:

    		protected void Page_Load(object sender, EventArgs e)
    {
    Debug.WriteLine("in default.aspx.cs");
    throw new Exception();
    }

    - add this code to global.asax.cs:

    	public class Global : System.Web.HttpApplication
    {
    void Application_BeginRequest(object sender, EventArgs e)
    Debug.WriteLine("in Application_BeginRequest"); }

    void Application_AcquireRequestState(object sender, EventArgs e)
    Debug.WriteLine("in Application_AcquireRequestState"); }

    void Application_Error(object sender, EventArgs e)
    Debug.WriteLine("in Application_Error"); }

    void Application_EndRequest(object sender, EventArgs e)
    Debug.WriteLine("in Application_EndRequest"); }
    }

    - add an error.aspx. in the aspx set EnableSessionState="True" in the Page directive and add some content so that you can see something.

    - add this code to error.aspx.cs:

    		protected void Page_Load(object sender, EventArgs e)
    {
    Debug.WriteLine("in error.aspx.cs");
    Debug.WriteLine("this implements SessionState.IRequiresSessionState: " + (this is System.Web.SessionState.IRequiresSessionState).ToString());
    try
    {
    Debug.WriteLine("Session == null: " + (Session == null).ToString());
    }
    catch(Exception ex)
    {
    Debug.WriteLine("Exception occured:");
    Debug.WriteLine(ex);
    }
    }

    - in the web.config add this line:

    		<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/error.aspx"/>

    - in IIS create a web site pointing to your diectory, set ASP.NET version to 2.0 and in custom errors let 404 point to error.aspx

    - attach your debugger to w3wp.exe and request some urls on your new web site.


    When I request error.aspx, the Output window looks like this:

    in Application_BeginRequest
    in Application_AcquireRequestState
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    Session == null: False
    in Application_EndRequest

    This is the normal flow how it should be. Now lets request default.aspx:

    in Application_BeginRequest
    in Application_AcquireRequestState
    in default.aspx.cs
    A first chance exception of type 'System.Exception' occurred in errorTest.DLL
    A first chance exception of type 'System.Web.HttpUnhandledException' occurred in System.Web.dll
    A first chance exception of type 'System.Web.HttpUnhandledException' occurred in System.Web.dll
    in Application_Error
    in Application_EndRequest
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
    Exception occured:
    System.Web.HttpException: Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the <configuration>\<system.web>\<httpModules> section in the application configuration.
       at System.Web.UI.Page.get_Session()
       at errorTest.error.Page_Load(Object sender, EventArgs e) in D:\dev\test\errorTest\errorTest\error.aspx.cs:line 19

    For the default.aspx everything is still green but after the Application_EndRequest the code in error.aspx is run without running the events BeginRequest and AcquireRequestState. Therefore the code which checks if Session is null throws an exception. And all this even though the error class implements IRequiresSessionState and the EnableSessionState attribute was added to the Page directive.

    Another request: foobar (without extension). The file does not exist and therefore IIS runs its error page for 404 which is error.aspx:

    in Application_BeginRequest
    in Application_AcquireRequestState
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    Session == null: False
    in Application_EndRequest

    Thats fine again. All events are run and Session is there. Lets request foobar.aspx:

    in Application_BeginRequest
    A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
    in Application_Error
    in Application_EndRequest
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
    Exception occured:
    System.Web.HttpException: Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the <configuration>\<system.web>\<httpModules> section in the application configuration.
       at System.Web.UI.Page.get_Session()
       at errorTest.error.Page_Load(Object sender, EventArgs e) in D:\dev\test\errorTest\errorTest\error.aspx.cs:line 19

    The application events are run for foobar.aspx but as soon as the framework sees that there is no such file, it runs error.aspx again without running the events.

    When you change your reirectMode to ResponseRedirect, then this behaves differently. A request for foobar.aspx does this:

    in Application_BeginRequest
    A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
    in Application_Error
    in Application_EndRequest
    in Application_BeginRequest
    in Application_AcquireRequestState
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    Session == null: False
    in Application_EndRequest

    So even though the events are not run seperately for error.aspx, the Session is there and can be used. Similar for a request for default.aspx:

    in Application_BeginRequest
    in Application_AcquireRequestState
    in default.aspx.cs
    A first chance exception of type 'System.Exception' occurred in errorTest.DLL
    A first chance exception of type 'System.Web.HttpUnhandledException' occurred in System.Web.dll
    A first chance exception of type 'System.Web.HttpUnhandledException' occurred in System.Web.dll
    in Application_Error
    in Application_EndRequest
    in Application_BeginRequest
    in Application_AcquireRequestState
    in error.aspx.cs
    this implements SessionState.IRequiresSessionState: True
    Session == null: False
    in Application_EndRequest


    So what I'm complaining about is that Session is available on the error page when I set redirectMode="ResponseRedirect" but it is not there and throws an exception when I use redirectMode="ResponseRewrite".

    Wednesday, September 29, 2010 4:15 AM
  • User713056278 posted

    Hi,

    So what I'm complaining about is that Session is available on the error page when I set redirectMode="ResponseRedirect" but it is not there and throws an exception when I use redirectMode="ResponseRewrite".
     

     

    As According to your steps I get that the session is available when you set redirectMode="ResponseRedirect" ,however you try to use ResponseRewrite so that the page URL didn't change.

    The issue is the session is not there and throws an exception while using redirectMode="ResponseRewrite".

    As far as I know ,IIS detects the 404 before ever calling the ASP.Net processor.  When the 404 error is detected it is not going to call the ASP.Net processor - even though you are rewriting the URL to an extension handled by aspnet_isapi.dll.  But when you use the Redirect method it probably actually issues a 302 response code and sends the browser to your 404.aspx page, thus starting the aspnet processor.Thus ,the redirectMode="ResponseRewrite" is more of just the way it works when the error encounter.

    Here are some similar threads ,hope it can give you some solutions.

    http://forums.asp.net/p/1419122/3142259.aspx

    http://forums.asp.net/p/1605868/4095407.aspx

    Wednesday, September 29, 2010 5:10 AM
  • User473663573 posted

    I uploaded my sample application. You can download it here.

    As According to your steps I get that the session is available when you set redirectMode="ResponseRedirect" ,however you try to use ResponseRewrite so that the page URL didn't change.

    The issue is the session is not there and throws an exception while using redirectMode="ResponseRewrite".

    Exactly! According to ScottGu redirectMode="ResponseRedirect" (which we had before) is not an option anymore so we changed it.

    As far as I know ,IIS detects the 404 before ever calling the ASP.Net processor.  When the 404 error is detected it is not going to call the ASP.Net processor - even though you are rewriting the URL to an extension handled by aspnet_isapi.dll. 

    IIS detects 404 only when the request does not have an extension which is mapped to aspnet_isapi.dll. In this case IIS seems to issue an request for its error page (which in our case is also error.aspx) and there everything works fine. All events are called and the session is there.

    But when you request something like foobar.aspx then IIS still calls aspnet, the events are only called for foobar.aspx until it notices that the file is not there and rewrites the url to error.aspx (according to CW2 on http://forums.asp.net/p/1419122/3142259.aspx it calls Server.Execute) and then it does not run the events again and the Session is gone.

    The same seems to happen for 500 errors. On the original request, the events are fine, but after rewriting to error.aspx the Session is not available.


    Thanks for your links. The 2nd of that indeed seems related to mine. I posted my question there too.


    Wednesday, September 29, 2010 6:33 AM