Colin Cochrane

Software Developer based in Victoria, BC specializing in C#, PowerShell, Web Development and DevOps.

ASP.NET Custom Errors: Preventing 302 Redirects To Custom Error Pages

 
You can download the HttpModule here.
 
Defining custom error pages is a convenient way to show users a friendly page when they encounter an HTTP error such as a 404 Not Found, or a 500 Server Error.  Unfortunately ASP.NET handles custom error pages by responding with a 302 Temporary redirect to the error page that was defined. For example, consider an example application that has IIS configured to map all requests to it, and has the following customErrors element defined in its web.config:
 
<customErrors mode="RemoteOnly" defaultRedirect="~/error.aspx">
<error statusCode="404" redirect="~/404.aspx" />
</customError>

If a user requested a page that didn't exist, then the HTTP response would look something like:

http://www.domain.com/non-existant-page.aspx --> 302 Found
http://www.domain.com/404.aspx  --> 404 Not Found
Date: Sat, 26 Jan 2008 03:08:21 GMT
Server: Microsoft-IIS/6.0
Content-Length: 24753
Content-Type: text/html; charset=utf-8
X-Powered-By: ASP.NET
 
As you can see, there is a 302 redirect that occurs to send the user to the custom error page.  This is not ideal for two reasons:

1) It's bad for SEO

When a search engine spiders crawls your site and comes across a page that doesn't exist, you want to make sure you respond with an HTTP status of 404 and send it on its way.  Otherwise you may end up with duplicate content issues or indexing problems, depending on the spider and search engine.

2) It can lead to more incorrect HTTP status responses

This ties in with the first point, but can be significantly more serious.  If the custom error page is not configured to response with the correct status code then the HTTP response could end up looking like:

http://www.domain.com/non-existant-page.aspx --> 302 Found
http://www.domain.com/404.aspx  --> 200 OK
Date: Sat, 26 Jan 2008 03:08:21 GMT
Server: Microsoft-IIS/6.0
Content-Length: 24753
Content-Type: text/html; charset=utf-8
X-Powered-By: ASP.NET
 
Which would almost guarantee that there would be duplicate content issues for the site with the search engines, as the search spiders are simply going to assume that the error page is a normal page, like any other.Furthermore it will probably cause some website and server administration headaches, as HTTP errors won't be accurately logged, making them harder to track and identify.
I tried to find a solution to this problem, but I didn't have any luck finding anything, other than people who were also looking for a way to get around it.  So I did what I usually do, and created my own solution.
 
The solution comes in the form of a small HTTP module that hooks onto the HttpContext.Error event.  When an error occurs, the module checks if the error's type is an HttpException.  If the error is an HttpException, then the following process takes place:
  1. The response headers are cleared (context.Response.ClearHeaders() )
  2. The response status code is set to match the actual HttpException.GetHttpCode() value (context.Response.StatusCode = HttpException.GetHttpCode())
  3. The customErrorsSection from the web.config is checked to see if the HTTP status code (HttpException.GetHttpCode() ) is defined.
  4. If the statusCode is defined in the customErrorsSection then the request is transferred, server-side, to the custom error page. (context.Server.Transfer(customErrorsCollection.Get(statusCode.ToString).Redirect) )
  5. If the statusCode is not defined in the customErrorsSection, then the response is flushed, immediately sending the response to the client.(context.Response.Flush() )

Here is the source code for the module.

   1: Imports System.Web
   2: Imports System.Web.Configuration
   3:  
   4: Public Class HttpErrorModule
   5:   Implements IHttpModule
   6:  
   7:   Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
   8:     'Nothing to dispose.
   9:   End Sub
  10:  
  11:   Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
  12:     AddHandler context.Error, New EventHandler(AddressOf Context_Error)
  13:   End Sub
  14:  
  15:   Private Sub Context_Error(ByVal sender As Object, ByVal e As EventArgs)
  16:     Dim context As HttpContext = CType(sender, HttpApplication).Context
  17:     If (context.Error.GetType Is GetType(HttpException)) Then
  18:       ' Get the Web application configuration.
  19:       Dim configuration As System.Configuration.Configuration = WebConfigurationManager.OpenWebConfiguration("~/web.config")
  20:  
  21:       ' Get the section.
  22:       Dim customErrorsSection As CustomErrorsSection = CType(configuration.GetSection("system.web/customErrors"), CustomErrorsSection)
  23:  
  24:       ' Get the collection
  25:       Dim customErrorsCollection As CustomErrorCollection = customErrorsSection.Errors
  26:  
  27:       Dim statusCode As Integer = CType(context.Error, HttpException).GetHttpCode
  28:  
  29:       'Clears existing response headers and sets the desired ones.
  30:       context.Response.ClearHeaders()
  31:       context.Response.StatusCode = statusCode
  32:       If (customErrorsCollection.Item(statusCode.ToString) IsNot Nothing) Then
  33:         context.Server.Transfer(customErrorsCollection.Get(statusCode.ToString).Redirect)
  34:       Else
  35:         context.Response.Flush()
  36:       End If
  37:  
  38:     End If
  39:  
  40:   End Sub
  41:  
  42: End Class

The following element also needs to be added to the httpModules element in your web.config (replace the attribute values if you aren't using the downloaded binary):

<httpModules>
<add name="HttpErrorModule" type="ColinCochrane.HttpErrorModule, ColinCochrane" />
</httpModules>

And there you go! No more 302 redirects to your custom error pages.

Comments (42) -

  • James

    1/25/2008 2:32:33 PM | Reply

    Thank you so much!  I've been bashing my head against the wall trying to figure out why one of our client's sites kept responding with all of those 302's.  I'll definitely be giving this a try.

  • Eric

    1/25/2008 3:12:34 PM | Reply

    Tried it out tonight and it worked like a charm.

    Thank you!

  • Abhiahek

    2/4/2008 9:13:18 PM | Reply

    Hi I like this Article too much , but can u provide this Article in C#, I will b too thankfull to you.

  • Sammy

    3/3/2008 5:30:55 PM | Reply

    Here is the C# translation for anyone to use

    using System.Web;
    using System.Web.Configuration;
    using System;

    public class HttpErrorModule : IHttpModule
    {

        private void Context_Error(object sender, EventArgs e)
        {
            HttpContext context = ((HttpApplication)sender).Context;
                if((object.ReferenceEquals(context.Error.GetType(),typeof(HttpException))))
                {
                // Get the Web application configuration.
                System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/web.config");
                // Get the section.
                CustomErrorsSection customErrorsSection = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");
                // Get the collection
                CustomErrorCollection customErrorsCollection = customErrorsSection.Errors;
                int statusCode = ((HttpException)context.Error).GetHttpCode();

                //Clears existing response headers and sets the desired ones.
                context.Response.ClearHeaders();
                context.Response.StatusCode = statusCode;

                if ((customErrorsCollection.Get(statusCode.ToString()) != null))
                {
                    context.Server.Transfer(customErrorsCollection.Get(statusCode.ToString()).Redirect);
                }

                else
                {
                    context.Response.Flush();
                }
            }
        }

        #region IHttpModule Members

        public void Dispose()
        {
          //Do nothing here
        }

        public void Init(HttpApplication context)
        {
            context.Error += new EventHandler(Context_Error);
        }

        #endregion
    }

  • Atif Aziz

    3/10/2008 9:33:43 AM | Reply

    Some months backs, I had a discussion about the same topic in the following thread over at the ELMAH discussion group:
    groups.google.com/.../d01b003b37b023c7

    I'm glad to see that someone has finally brought the problem to public light. I'll be sure to point to this post in the future as I hop from one ASP.NET soul to another trying to hopelessly explain how custom error handling in ASP.NET is broken.

    Apart from spiders, the 302-style custom error handling breaks any kind of client-side code that deals with parsing or downloading of web resources. Imagine using System.Net.WebClient.DownloadFile to download a ZIP file from a URL that results in an error (perhaps denial of authorization). The web site will respond with a 302 followed by 200. The ZIP will be reported to have downloaded successfully yet any decompression tool will find the archive to be corrupted. It will be corrupted because its content will reflect the customer error page. Tong I have found that the corruption scenario gets people more nervous and itching to address the issue in their sites than, say, the argument regarding search engines and SEO.

    BTW, you might want to add a check for Context.IsCustomErrorEnabled in the module. This way, it will adapt automatically between production and development environments since one tends to configure customer error pages such that they're disabled during development (to get the yellow screen of death) but enabled in production.

  • Kenpachi

    4/22/2008 6:19:56 AM | Reply

    Awesome module! I've been testing it out on my local machine and the 404 errors work flawlessly, but I can't get the 500 errors to work without redirecting. Every time I trigger an error somewhere it ignores your module and does that redirect spiel. Does anyone have a work around? Thanks!

  • Colin Cochrane

    4/25/2008 1:05:40 AM | Reply

    Kenpachi - Would you mind showing us your web.config?

  • Tommy Vallée

    5/21/2008 3:04:40 AM | Reply

    Does it work on windows 2000 server standard?

  • Brent

    5/21/2008 3:48:39 AM | Reply

    Hi,

    i'm such a newbie with this so i have a few questions :

    where do i put the DLL???
    How can i actve the httpmodule??

    In Fact, I don't know what to do with the dll Smile

    I'm running IIS 5

    Thanks Colin

  • Colin Cochrane

    5/21/2008 4:06:06 AM | Reply

    Tommy - There's no reason it shouldn't.  All that is required is ASP.NET 2.0.


    Brent - The DLL should be placed in the /bin directory of the application.  

  • Brent

    5/27/2008 2:18:35 AM | Reply

    ok and Which application are you taling about.. i'm not a pro with that.

  • Colin Cochrane

    5/29/2008 12:57:15 PM | Reply

    You'll be looking for the root directory of your website (application just means web application).

  • klint

    6/10/2008 1:39:26 AM | Reply

    I can't seem to get this to work in my VS 2008 project.  I have tried both copying the .dll to my bin directory, and have also tried putting my own .vb file in the app_code directory.  I have registered the module in the httpModules section of system.web in my web.config file, both using your line of code, and a modified line of code to match my custom .vb file (using your source code listed above).

    What could I be doing wrong?

    VS.NET 2008, 3.5, Vista, Debugging on IIS.

  • Colin Cochrane

    6/10/2008 6:29:04 AM | Reply

    @klint:

    Try setting a breakpoint at the Init() procedure in the module and see if it gets hit. If it doesn't get hit, then we'll know the module isn't being loaded properly.

  • klint

    6/10/2008 6:59:12 AM | Reply

    It does not get hit.

    I have posted a question on forums.asp.net and your feedback would be greatly appreciated.

    <system.web>
    <httpModules>
                <add name="HttpErrorModule" type="HttpErrorModule, HttpErrorModule" />
    </httpModules>
    </system.web>

    I have tried turning errors Off, On, RemoteOnly and commenting out the entire section

        <customErrors mode="Off" defaultRedirect="~/Error.aspx">
                <error statusCode="403" redirect="~/403Forbidden.aspx" />
                <error statusCode="404" redirect="~/404PageNotFound.aspx" />
        </customErrors>

    I have created HttpErrorModule.vb in the App_Code directory (code listed below)

    Imports System.Web
    Imports System.Web.Configuration


    Public Class HttpErrorModule
        Implements IHttpModule

        Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
            'Nothing to dispose.
        End Sub

        Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
            AddHandler context.Error, New EventHandler(AddressOf Context_Error)
        End Sub

    ......
    (rest of code omitted)

  • klint

    6/10/2008 8:44:30 AM | Reply

    when I add the breakpoint, and debug, instead of the red dot, I get a white dot outlined in red, with a little yellow exclamation point.

    Hovering over it, VS states:

    At HttpErrorModule.vb, line 12 character 12 (Init,line2)

    The breakpoint will not currently be hit. No symbols have been loaded for this document

  • klint

    6/10/2008 8:45:35 AM | Reply

    i thought that perhaps the HttpErrorModule is a reserved word, so I changed it to myHttpErrorModule.  Still no dice.

    It also appears the VS is not compiling .vb files into a .dll in the bin directory

  • klint

    6/10/2008 9:14:12 AM | Reply

    well, now I am convinced it is not even listening to requests.

    I added the following line to init

    Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
            <b>Throw New HttpException("Exception Occured")</b>
            AddHandler context.Error, New EventHandler(AddressOf Context_Error)
        End Sub

    When I start the debugger, it just loads the home page and does not throw the error.

    My web.config now includes this:

    <system.web>
    <httpModules>
    <add name="myHttpErrorModule" type="myHttpErrorModule" />
    </httpModules>
    </system.web>

    Did something change in IIS 7 or VS 2008 that changes the way iHTTPModules are implemented?

  • Colin Cochrane

    6/10/2008 1:15:40 PM | Reply

    Klint: Could you post the contents of your web.config?

  • klint

    6/12/2008 6:52:23 AM | Reply

    <?xml version="1.0"?>
    <!--
        Note: As an alternative to hand editing this file you can use the
        web admin tool to configure settings for your application. Use
        the Website->Asp.Net Configuration option in Visual Studio.
        A full list of settings and comments can be found in
        machine.config.comments usually located in
        \Windows\Microsoft.Net\Framework\v2.x\Config
    -->
    <configuration>
      <configSections>
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
            <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
              <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
              <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
              <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
              <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
            </sectionGroup>
          </sectionGroup>
        </sectionGroup>
      </configSections>
      <appSettings>
        <add key="smtpServerAddress" value="localhost"/>
      </appSettings>
      <connectionStrings />
      <system.web>
        <!--
                Set compilation debug="true" to insert debugging
                symbols into the compiled page. Because this
                affects performance, set this value to true only
                during development.

                Visual Basic options:
                Set strict="true" to disallow all data type conversions
                where data loss can occur.
                Set explicit="true" to force declaration of all variables.
            -->
        <compilation debug="true" strict="false" explicit="true">
          <assemblies>
            <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/></assemblies>
        </compilation>
        <pages>
          <namespaces>
            <clear/>
            <add namespace="System"/>
            <add namespace="System.Collections"/>
            <add namespace="System.Collections.Generic"/>
            <add namespace="System.Collections.Specialized"/>
            <add namespace="System.Configuration"/>
            <add namespace="System.Text"/>
            <add namespace="System.Text.RegularExpressions"/>
            <add namespace="System.Linq"/>
            <add namespace="System.Xml.Linq"/>
            <add namespace="System.Web"/>
            <add namespace="System.Web.Caching"/>
            <add namespace="System.Web.SessionState"/>
            <add namespace="System.Web.Security"/>
            <add namespace="System.Web.Profile"/>
            <add namespace="System.Web.UI"/>
            <add namespace="System.Web.UI.WebControls"/>
            <add namespace="System.Web.UI.WebControls.WebParts"/>
            <add namespace="System.Web.UI.HtmlControls"/>
          </namespaces>
          <controls>
            <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          </controls>
        </pages>
        <!--
                The <authentication> section enables configuration
                of the security authentication mode used by
                ASP.NET to identify an incoming user.
            -->
        <authentication mode="Windows"/>
        <!--
                The <customErrors> section enables configuration
                of what to do if/when an unhandled error occurs
                during the execution of a request. Specifically,
                it enables developers to configure html error pages
                to be displayed in place of a error stack trace.
        -->
        
        
            <customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx">
                <error statusCode="403" redirect="~/403Forbidden.aspx" />
                <error statusCode="404" redirect="~/404PageNotFound.aspx" />
            </customErrors>
        
        
        <httpHandlers>
          <remove verb="*" path="*.asmx"/>
          <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
        </httpHandlers>
        <httpModules>
          <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <!--<add type="YourModuleNameHere.IPBlackList, YourAssemblyNameHere" name="IPBlackList" />-->
          <!--<add name="HttpErrorModule" type="ColinCochrane.HttpErrorModule, ColinCochrane" />-->
          <add name="myHttpErrorModule" type="myHttpErrorModule" />
        </httpModules>
      </system.web>
      <system.codedom>
        <compilers>
          <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <providerOption name="CompilerVersion" value="v3.5"/>
            <providerOption name="WarnAsError" value="false"/>
          </compiler>
          <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <providerOption name="CompilerVersion" value="v3.5"/>
            <providerOption name="OptionInfer" value="true"/>
            <providerOption name="WarnAsError" value="false"/>
          </compiler>
        </compilers>
      </system.codedom>
      <!--
            The system.webServer section is required for running ASP.NET AJAX under Internet
            Information Services 7.0.  It is not necessary for previous version of IIS.
        -->
      <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <modules>
          <remove name="ScriptModule"/>
          <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </modules>
        <handlers>
          <remove name="WebServiceHandlerFactory-Integrated"/>
          <remove name="ScriptHandlerFactory"/>
          <remove name="ScriptHandlerFactoryAppServices"/>
          <remove name="ScriptResource"/>
          <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </handlers>
      </system.webServer>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

  • klint

    6/12/2008 11:34:19 PM | Reply

    Sigh. Still not working.  I figured out how to get the module to load within IIS 7, but according to fiddler, it is not sending the 404 code.

    This is in both my own code, and your module.

    Have you verified this works in IIS 7 in integrated mode?

  • Colin Cochrane

    6/13/2008 11:58:32 AM | Reply

    I've had no problems with IIS7 in integrated mode.  Is it still throwing a 302 redirect to the error page?  If not, make sure that the error pages are configured to clear the response headers and set the status code.

    eg)

    void page_load(Object sender, EventArgs e){
      Response.ClearHeaders();
      Response.StatusCode = 404;

    }

  • klint

    6/14/2008 1:50:44 AM | Reply

    Yes, it still throws a 302, and then a 200.  

    Yes, I had already added:

    Response.ClearHeaders();
    Response.StatusCode = 404;

  • Colin Cochrane

    6/14/2008 8:03:04 AM | Reply

    You said this was on your local machine?  Trying changing the customErrors mode to "On" instead of "RemoteOnly".

  • Mark

    9/3/2008 4:09:37 AM | Reply

    I have tried to use this control and have found that it does run but I show a 302 found header is received before a 200 ok header. I am using the following server setup.

    Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433

    Windows Server 2003

    Microsoft-IIS/6.0

    I have put your dll in the bin holder. I had to modify the web.config section just a little to get it to run.


    <configuration>
      <system.web>
        <httpModules>
          <add name="HttpErrorModule" type="ColinCochrane.HttpErrorModule, ColinCochrane.HttpErrorModule" />
        </httpModules>

        <customErrors mode="On">
          <error statusCode="404" redirect="/goto/404.aspx" />
        </customErrors>
      </configuration>
    </system.web>

    I am using a hosting service and do not have access to the iis control panel. Any idea if I have done something wrong?

    Thanks

  • dhaval

    9/9/2008 12:46:57 AM | Reply

    I haven't been able to get this to work.  I created a new assembly called "ctca" (company name), i have one namespace called "httpModules", and i have one class called "httpErrorModule".  The code is the exact copy of the one in this post.  Below is my web.config httpModules section:

    <httpModules>
    <add name="HttpErrorModule" type="ctca.HttpModules.HttpErrorModule,ctca" />
    </httpModules>

    <customErrors mode="Off">
      <error statusCode="500" redirect="~/errors/500.htm"/>
      <error statusCode="404" redirect="~/errors/404.htm"/>
    </customErrors>

    Also, i am using Windows 2003, with IIS 6.0, and Default Pool. If I set the mode="on" in my customErrors section it does the redirect with a 302 status code.

    Dhaval

  • Arun

    10/15/2008 8:25:51 AM | Reply

    Once I add this httpmodule in the web.config, I am getting the following error

    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.

    when I remove this line from web.config, my website works again with no problems.

    Any ideas?

    Thanks

  • Arun

    10/15/2008 8:29:10 AM | Reply

    I did not have  System.Web.SessionStateModule  in my web.config before, but i never had problems using session variables. but I am getting this error message after adding this httpmodule(<add name="HttpErrorModule" type="ColinCochrane.HttpErrorModule, ColinCochrane" />
    ) in web.config.

    After getting this error message, I added
    <add name="Session" type="System.Web.SessionState.SessionStateModule"/>   to httpmodules section in web.config.  But that does not fix the issue.

  • chitgoks

    11/2/2008 10:54:37 AM | Reply

    im doing a login module and wanted to redirect it to a 401 error page if the login is incorrect. i did try this but it still goes to a 302 then 200 after.

  • chitgoks

    11/2/2008 3:22:18 PM | Reply

    I placed my c# code in ~/App_code/com/http/error/HttpErrorModule.cs since my namespace is in com.http.error

    also placed in the web.config

    <httpModules>
          <add name="HttpErrorModule" type="com.http.error.HttpErrorModule" />
        </httpModules>

        <customErrors mode="Off" defaultRedirect="~/error_page/error.html">
          <error statusCode="404" redirect="~/page_not_found.html" />
          <error statusCode="401" redirect="~/error_page/access_denied.html" />
        </customErrors>

    and my context.Response.StatusCode = statusCode; will always output 302, then 200 still.

    these are the only things that are needed right? or am i missing something here? thank you

  • Mark

    1/5/2009 12:00:41 AM | Reply

    This is an excellent article!  I have learned a great deal from how errors are handled in ASP.NET.

    However, I'm still having an issue that may be related, that I hope someone here can help me with.  My problem is that I'm not seeing an error caught here (or anywhere else) for a 404. All I get is the stock 404 page.  I've tried virtually every possible combination of the customerrors section, to no avail.  One possible item of note, is that I am working on a frame based site (yeah I know, not my call!)

  • Michael

    1/6/2009 7:42:59 AM | Reply

    A better approach if your web hosting provider is using the latest .NET service pack (3.5 SP1, 3.0 SP2, 2.0 SP2) is to use the new redirectMode:

    msdn.microsoft.com/.../...ection.redirectmode.aspx

    <customErrors mode="RemoteOnly" defaultRedirect="~/error.aspx" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/404.aspx" />
    </customErrors>

    Another consideration is what should happen when a programming error occurs. As far as I can tell the search engine would currently index the error page for the url (with 302 and now 200) where instead you want to tell it not to index temporarily and try again later (503 seems best match). Therefore I'm putting this in Global.asax file:

    void Application_Error(object sender, EventArgs e) {
      //if error is an httpexception, the response status code will automatically be set e.g. 404
      if (Context.Error.GetType() != typeof(HttpException))
        Context.Response.StatusCode = 503;
    }

  • Colin Cochrane

    2/2/2009 1:57:00 AM | Reply

    @Michael,

    Thanks for the heads-up on that. I'll definitely be looking into that new feature.

  • Chris Haas

    4/22/2009 12:25:35 AM | Reply

    Thanks Colin, that was exactly what I was looking for! Everyone, make sure you have customErrors set to Off or RemoteOnly. This module actually takes the place of ASP.Net's error handling. It still reads the contents of the node but you need to tell ASP.Net not to handle things for you. Also, if you have IIS redirecting to the same page make sure you've added a Response.StatusCode = 404 in the Page_Load. I've gone deeper into the article along with how to add it to your App_Code here:
    blog.vendiadvertising.com/.../...)-404-errors.aspx

  • Demon

    6/2/2009 11:55:24 PM | Reply

    For me your code doesn't work on Win2003 with IIS6 server, after request to folder that back 404 error ASP.NET don't see that request at all, any work arround for that without configurating IIS6 on server.

  • al miller

    6/8/2009 2:28:17 AM | Reply

    My simple fix for asp.net 404 errors and google showing text instead of a PageNotFound.aspx page. Created an htm page with a redirect that points to the aspx and then set IIS Custom Errors for 404 to point to the htm page. Google now correctly shows the aspx page not found page.

  • Mike

    8/17/2009 4:40:37 PM | Reply

    I think there are templates specially designed for Custom error pages, not sure about blogengine though.

  • Nathan

    9/15/2009 1:46:30 PM | Reply

    One problem with the new RedirectMode setting is that it doesn't support MVC routes. Ironically, if you enable customErrors with RedirectMode="ResponseRewrite" and then set your redirect paths to a controller route (say ~/Error/NotFound) you end up getting a YSOD which informs you that you can display the error contents by turning off customErrors... Whoops!

  • John

    8/19/2011 4:29:23 AM | Reply

    Hi , thank you for letting me leaving a comment on your site ASP.NET Custom Errors: Preventing 302 Redirects To Custom Error ..., it is always nice to see that blogowners are interested in their visitors.

Loading