设置redirectMode ="ResponseRewrite"时,CustomErrors不起作用

Edu*_*eni 71 asp.net iis-6 custom-errors redirectmode

在旧网站中,我通过添加redirectMode="ResponseRewrite"(3.5 SP1中的新增功能)来更改CustomErrors的工作方式:

<customErrors mode="RemoteOnly" defaultRedirect="Error.aspx" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="404.aspx" />
</customErrors> 
Run Code Online (Sandbox Code Playgroud)

问题是:它向我显示了一般错误页面(当你没有设置时你得到的那个customErrors.如果我删除redirectMode="ResponseRewrite"部分,它工作正常.

我确定服务器中安装了3.5 SP1,因为我在同一服务器上托管的其他站点上使用相同的设置.

有任何想法吗?

Mic*_*ock 100

对于任何试图在幕后ResponseRewrite使用的MVC应用程序中执行此操作的人来说,这一点非常重要Server.Transfer.因此,defaultRedirect必须对应于文件系统上的合法文件.显然,Server.Transfer与MVC路由不兼容,因此,如果您的错误页面由控制器操作提供,则将Server.Transfer查找/ Error/Whatever,在文件系统上找不到它,并返回通用的404错误页面!


Ami*_*ila 49

对我来说唯一合适的方法是关闭自定义错误并通过web.config替换iis的错误页面.它使用响应发送正确的状态代码,并且具有不通过mvc的好处.

这是代码

  1. 关闭自定义错误

    <customErrors mode="Off" />
    
    Run Code Online (Sandbox Code Playgroud)
  2. 替换错误页面

    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" subStatusCode="-1" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="404" path="Error404.html" responseMode="File" />
      <error statusCode="500" path="Error.html" responseMode="File" />
    </httpErrors>
    
    Run Code Online (Sandbox Code Playgroud)

注意.使用responsemode="file"如果URL是直接链接到一个文件

信息:http://tipila.com/tips/use-custom-error-pages-aspnet-mvc

  • 我已经疯狂地试图找到处理我的应用程序错误的"正确"方法,这就是解决方案.我仍然需要处理全局中的一些错误,但这是可以的,因为我想要记录这些错误.当发生这种情况时,我正在做一个Server.Transfer到一个aspx错误页面.这个解决方案的最大部分是用户永远不知道我的处理程序是什么命名的,并且永远不会被带到他们没有请求的URL. (3认同)
  • 此解决方案远非完美,它将取代 AJAX 和 API 错误响应 http://stackoverflow.com/questions/24465261/customerrors-vs-httperrors-a-重要-design-flaw (3认同)

Mic*_*ael 20

发生了什么事情是IIS正在查看错误状态代码并显示它自己的错误页面而不是你自己的错误页面.要解决此问题,您需要在错误页面的代码隐藏页面中进行设置,以防止IIS执行此操作:

Response.TrySkipIisCustomErrors = true;
Run Code Online (Sandbox Code Playgroud)

这仅适用于IIS7或更高版本,对于早期版本的IIS,您需要使用错误页面设置.

  • 谢谢 - 如果您需要使用.aspx页面作为defaultRedirect,这是解决方案. (2认同)

Red*_*Taz 14

由于依赖Server.Transfer它,似乎内部实现ResponseRewrite与MVC不兼容.

这对我来说似乎是一个明显的功能漏洞,因此我决定使用HTTP模块重新实现此功能,以便它可以正常工作.下面的解决方案允许您通过重定向到任何有效的MVC路由(包括物理文件)来处理错误,就像您正常做的那样.

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="404.aspx" />
    <error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>
Run Code Online (Sandbox Code Playgroud)

这已经在以下平台上进行了测试;

  • 集成流水线模式下的MVC4(IIS Express 8)
  • 经典模式下的MVC4(VS开发服务器,卡西尼)
  • 经典模式下的MVC4(IIS6)

namespace Foo.Bar.Modules {

    /// <summary>
    /// Enables support for CustomErrors ResponseRewrite mode in MVC.
    /// </summary>
    public class ErrorHandler : IHttpModule {

        private HttpContext HttpContext { get { return HttpContext.Current; } }
        private CustomErrorsSection CustomErrors { get; set; }

        public void Init(HttpApplication application) {
            System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
            CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");

            application.EndRequest += Application_EndRequest;
        }

        protected void Application_EndRequest(object sender, EventArgs e) {

            // only handle rewrite mode, ignore redirect configuration (if it ain't broke don't re-implement it)
            if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) {

                int statusCode = HttpContext.Response.StatusCode;

                // if this request has thrown an exception then find the real status code
                Exception exception = HttpContext.Error;
                if (exception != null) {
                    // set default error status code for application exceptions
                    statusCode = (int)HttpStatusCode.InternalServerError;
                }

                HttpException httpException = exception as HttpException;
                if (httpException != null) {
                    statusCode = httpException.GetHttpCode();
                }

                if ((HttpStatusCode)statusCode != HttpStatusCode.OK) {

                    Dictionary<int, string> errorPaths = new Dictionary<int, string>();

                    foreach (CustomError error in CustomErrors.Errors) {
                        errorPaths.Add(error.StatusCode, error.Redirect);
                    }

                    // find a custom error path for this status code
                    if (errorPaths.Keys.Contains(statusCode)) {
                        string url = errorPaths[statusCode];

                        // avoid circular redirects
                        if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) {

                            HttpContext.Response.Clear();
                            HttpContext.Response.TrySkipIisCustomErrors = true;

                            HttpContext.Server.ClearError();

                            // do the redirect here
                            if (HttpRuntime.UsingIntegratedPipeline) {
                                HttpContext.Server.TransferRequest(url, true);
                            }
                            else {
                                HttpContext.RewritePath(url, false);

                                IHttpHandler httpHandler = new MvcHttpHandler();
                                httpHandler.ProcessRequest(HttpContext);
                            }

                            // return the original status code to the client
                            // (this won't work in integrated pipleline mode)
                            HttpContext.Response.StatusCode = statusCode;

                        }
                    }

                }

            }

        }

        public void Dispose() {

        }


    }

}
Run Code Online (Sandbox Code Playgroud)

用法

将其作为web.config中的最终HTTP模块包含在内

  <system.web>
    <httpModules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </httpModules>
  </system.web>

  <!-- IIS7+ -->
  <system.webServer>
    <modules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </modules>
  </system.webServer>
Run Code Online (Sandbox Code Playgroud)


小智 9

我知道这个问题有点陈旧,但我想我应该指出,它不需要是一个静态文件来使这个工作.

我遇到了类似的事情,这只是在你的Error.aspx中发现错误的问题,在我们的例子中,这是因为使用的主页依赖于一段会话数据,并且当设置了ResponseRewrite时,会话不可用于我们的Error.aspx页面.

我还没有确定会话的不可用性是由于我们的特定应用程序配置还是ASP.net的"按设计"部分.


Edu*_*eni 1

我发现问题出在Error.aspx中。仍然无法找到 error.aspx 中导致问题的实际错误是什么。

将页面更改为静态 html 文件解决了问题。