Colin Cochrane

Colin Cochrane is a 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" />

If a user requested a page that didn't exist, then the HTTP response would look something like: --> 302 Found  --> 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: --> 302 Found  --> 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
   4: Public Class HttpErrorModule
   5:   Implements IHttpModule
   7:   Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
   8:     'Nothing to dispose.
   9:   End Sub
  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
  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")
  21:       ' Get the section.
  22:       Dim customErrorsSection As CustomErrorsSection = CType(configuration.GetSection("system.web/customErrors"), CustomErrorsSection)
  24:       ' Get the collection
  25:       Dim customErrorsCollection As CustomErrorCollection = customErrorsSection.Errors
  27:       Dim statusCode As Integer = CType(context.Error, HttpException).GetHttpCode
  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
  38:     End If
  40:   End Sub
  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):

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

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

Comments (50) -

  • James

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

    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 |

    Tried it out tonight and it worked like a charm.

    Thank you!

  • Abhiahek

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

    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 |

    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;
                // 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.StatusCode = statusCode;

                if ((customErrorsCollection.Get(statusCode.ToString()) != null))


        #region IHttpModule Members

        public void Dispose()
          //Do nothing here

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


  • Atif Aziz

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

    Some months backs, I had a discussion about the same topic in the following thread over at the ELMAH discussion group:

    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 |

    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 |

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

  • Tommy Vallée

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

    Does it work on windows 2000 server standard?

  • Brent

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


    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 |

    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 |

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

  • Colin Cochrane

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

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

  • klint

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

    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 |


    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 |

    It does not get hit.

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

                <add name="HttpErrorModule" type="HttpErrorModule, HttpErrorModule" />

    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" />

    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 |

    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 |

    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 |

    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:

    <add name="myHttpErrorModule" type="myHttpErrorModule" />

    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 |

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

  • klint

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

    <?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
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
            <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
              <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
              <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
              <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
              <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <add key="smtpServerAddress" value="localhost"/>
      <connectionStrings />
                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">
            <add assembly="System.Core, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Data.DataSetExtensions, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Xml.Linq, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Windows.Forms, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Design, Version=, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/></assemblies>
            <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"/>
            <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                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" />
          <remove verb="*" path="*.asmx"/>
          <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
          <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <!--<add type="YourModuleNameHere.IPBlackList, YourAssemblyNameHere" name="IPBlackList" />-->
          <!--<add name="HttpErrorModule" type="ColinCochrane.HttpErrorModule, ColinCochrane" />-->
          <add name="myHttpErrorModule" type="myHttpErrorModule" />
          <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <providerOption name="CompilerVersion" value="v3.5"/>
            <providerOption name="WarnAsError" value="false"/>
          <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <providerOption name="CompilerVersion" value="v3.5"/>
            <providerOption name="OptionInfer" value="true"/>
            <providerOption name="WarnAsError" value="false"/>
            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.
        <validation validateIntegratedModeConfiguration="false"/>
          <remove name="ScriptModule"/>
          <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <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=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="" newVersion=""/>
            <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="" newVersion=""/>

  • klint

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

    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 |

    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.


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


  • klint

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

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

    Yes, I had already added:

    Response.StatusCode = 404;

  • Colin Cochrane

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

    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 |

    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


    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.

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

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

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


  • dhaval

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

    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:

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

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

    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.


  • Arun

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

    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?


  • Arun

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

    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 |

    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 |

    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

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

        <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" />

    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 |

    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 |

    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:

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

    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 |


    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 |

    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:

  • Demon

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

    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 |

    My simple fix for 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 |

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

  • Nathan

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

    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 |

    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.

  • Create your Online Store

    12/11/2015 3:25:53 PM |

    Spot on with this write-up, I truly think this website needs much more consideration. I’ll probably be again to read much more, thanks for that info.

  • Instagram Followers

    12/12/2015 4:26:26 PM |

    You made some decent points there. I looked on the internet for the issue and found most individuals will go along with with your website.

  • foolish

    12/22/2015 8:11:30 AM |

    There are some interesting points in time in this article but I don’t know if I see all of them center to heart. There is some validity but I will take hold opinion until I look into it further. Good article , thanks and we want more! Added to FeedBurner as well

  • foolish

    12/23/2015 2:17:00 AM |

    WONDERFUL Post.thanks for share..more wait .. …

  • Mold Inspection

    1/4/2016 9:04:00 AM |

    Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.

  • free mysql database

    1/6/2016 8:32:10 AM |

    I’d have to check with you here. Which is not something I usually do! I enjoy reading a post that will make people think. Also, thanks for allowing me to comment!

  • Coralie Sonders

    3/6/2017 2:53:17 AM |

    Hello guys! I truly love this blog! I want to share with you a new dating website like Badoo that I've found surfing around the internet, I liked it a whole lot, it is easy and simple with a very modern interface, there are users from all over the world and everything is free there may be nothing to pay for to uncover specific functions like unlimited chat etc. The website is called Weefamed.

  • Tyree Yance

    1/7/2018 12:13:38 AM |

    Follow @theworldsimages on Instagram for some awesome images.

Comments are closed