Search code examples
asp.netiis-7episerver

ASP.NET 404 redirect query string missing


With the following configuration in my web.config file,

<customErrors mode="On" redirectMode="ResponseRedirect" >
    <error statusCode="404" redirect="/404" />
</customErrors>   
<httpErrors errorMode="Custom">
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="/404" responseMode="ExecuteURL" />
</httpErrors>

The 404 page works nice, but for urls that end with .aspx an redirect happens and the query string for the url is removed. If I change parameter "redirectMode" in the tag "customErrors" to "ResponseRewrite" it stops working for .aspx urls and I just get the default ASP.NET error page. How can I fix this? I need the query string on the 404 page to be able to redirect the user to the correct new url.

/Viktor


Solution

  • Ok, ended up writing my own http module for this,

        public class FileNotFoundModule : IHttpModule
    {
        private static CustomErrorsSection _configurationSection = null;
        private const string RedirectUrlFormat = "{0}?404;{1}";
    
        public void Dispose()
        {
        }
    
        public void Init(HttpApplication context)
        {
            context.Error += new EventHandler(FileNotFound_Error);
        }
    
        private void FileNotFound_Error(object sender, EventArgs e)
        {
            var context = HttpContext.Current;
            if (context != null && context.Error != null)
            {
                var error = context.Error.GetBaseException() as HttpException;
                if (error != null && error.GetHttpCode() == 404 &&
                    (ConfigurationSecion.Mode == CustomErrorsMode.On || (!context.Request.IsLocal && ConfigurationSecion.Mode == CustomErrorsMode.RemoteOnly)) &&
                    !string.IsNullOrEmpty(RedirectUrl) && !IsRedirectLoop)
                {
                    context.ClearError();
                    context.Server.TransferRequest(string.Format(FileNotFoundModule.RedirectUrlFormat, RedirectUrl, context.Request.Url));
                }
            }
        }
    
        private bool IsRedirectLoop
        {
            get
            {
                var checkUrl = string.Format(FileNotFoundModule.RedirectUrlFormat,RedirectUrl,string.Empty);
                return HttpContext.Current.Request.Url.ToString().Contains(checkUrl);
            }
        }
    
        private CustomErrorsSection ConfigurationSecion
        {
            get
            {
                if (_configurationSection == null)
                {
                    _configurationSection = (CustomErrorsSection)WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath).GetSection("system.web/customErrors");
                }
                return _configurationSection;
            }
        }
    
        private string RedirectUrl
        {
            get
            {
                foreach (CustomError error in ConfigurationSecion.Errors)
                {
                    if (error.StatusCode == 404)
                    {
                        return error.Redirect;
                    }
                }
                return string.Empty;
            }
        }
    }
    

    Works for me :)

    /Viktor