75

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

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

问题是:它向我显示了通用错误页面(当您未设置时获得的页面customErrors。如果我删除该redirectMode="ResponseRewrite"部分,它工作正常。

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

有任何想法吗?

4

10 回答 10

104

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

于 2010-09-22T14:28:44.460 回答
53

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

这是代码

  1. 关闭自定义错误

    <customErrors mode="Off" />
    
  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>
    

笔记。如果responsemode="file"url 是文件的直接链接,则使用

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

于 2012-03-11T17:37:42.380 回答
20

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

Response.TrySkipIisCustomErrors = true;

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

于 2010-02-16T09:26:07.130 回答
16

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

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

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

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

  • 集成管道模式下的 MVC4 (IIS Express 8)
  • 经典模式下的 MVC4(VS 开发服务器,Cassini)
  • 经典模式下的 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() {

        }


    }

}

用法

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

  <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>
于 2015-03-31T09:18:37.707 回答
10

我知道这个问题有点老了,但我想我应该指出它不需要是一个静态文件来让它工作。

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

我还没有弄清楚会话不可用是由于我们的特定应用程序配置还是 ASP.net 的“设计”部分造成的。

于 2009-08-06T00:43:21.013 回答
1

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

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

于 2009-04-23T17:09:27.880 回答
1

我在 aspx 中构建了一个错误页面,将查询传输到 ASP.NET MVC 控制器。您可以将查询重写到此 aspx 页面,它会将查询传输到您的自定义控制器。

protected void Page_Load(object sender, EventArgs e)
{
  //Get status code
  var queryStatusCode = Request.QueryString.Get("code");
  int statusCode;
  if (!int.TryParse(queryStatusCode, out statusCode))
  {
    var lastError = Server.GetLastError();
    HttpException ex = lastError as HttpException;
    statusCode = ex == null ? 500 : ex.GetHttpCode();
  }
  Response.StatusCode = statusCode;

  // Execute a route
  RouteData routeData = new RouteData();
  string controllerName = Request.QueryString.Get("controller") ?? "Errors";
  routeData.Values.Add("controller", controllerName);
  routeData.Values.Add("action", Request.QueryString.Get("action") ?? "Index");

  var requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
  IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext, controllerName);
  controller.Execute(requestContext);
}

在此处查找更多详细信息:https ://stackoverflow.com/a/27354140/143503

于 2014-12-08T08:42:09.463 回答
1

根据@Amila的帖子以及该帖子的确认和完成,我有同样的问题,我在谷歌上挖了很多,但没有机会找到正确的答案。问题是当您使用. 时ASP.Net Web Application,无论是否MVC使用旧方式都无法实现自定义错误Webform project
如果您使用的是选项ASP.Net Web Application(无论是否MVC):

在我的场景中,我只想为特定的 404 错误定义一个自定义错误,另一个错误定义与 404 错误相同:


Senario1:您的自定义页面是一个简单的HTML文件,并放置在root

<configuration>
   <system.web>
      <customErrors mode="Off" />
   </system.web>
   <system.webServer>
       <httpErrors errorMode="Custom" existingResponse="Replace">
           <remove statusCode="404" subStatusCode="-1" />
           <error statusCode="404" path="ErrorPage.html" responseMode="File" />
       </httpErrors>
   </system.webServer>
</configuration>



Senario2:您的自定义页面是一个aspx页面并放置在root

<configuration>
   <system.web>
      <customErrors mode="Off" />
   </system.web>
   <system.webServer>
       <httpErrors errorMode="Custom" existingResponse="Replace">
           <remove statusCode="404" subStatusCode="-1" />
           <error statusCode="404" path="ErrorPage" responseMode="Redirect" />
       </httpErrors>
   </system.webServer>
</configuration>

注意:由于RouteConfig.csin ,我删除了 aspx 扩展名ASP.net application,您可以根据需要使用ErrorPage.aspx它,它是可选的。


Senario3:您的自定义页面是一个aspx页面并放置在[ex: Page folder in The root (~/Page/ErrorPage.aspx)]
我注意到这里的提示是您不应该使用~/根地址;所以我只是在没有~/标记的情况下解决:

<configuration>
   <system.web>
      <customErrors mode="Off" />
   </system.web>
   <system.webServer>
       <httpErrors errorMode="Custom" existingResponse="Replace">
           <remove statusCode="404" subStatusCode="-1" />
           <error statusCode="404" path="Page/ErrorPage" responseMode="Redirect" />
       </httpErrors>
   </system.webServer>
</configuration>
于 2020-02-14T17:10:15.973 回答
0

在我的特定情况下,我的错误页面有一个母版页,其中有一个尝试使用 Session 的用户控件。如果 Session 不可用,您会收到 HttpException:“只有在 enableSessionState 设置为 true 时才能使用会话状态,无论是在配置文件中还是在 Page 指令中。” 最简单的解决方法是切换到静态 html,第二简单的解决方法是使用更简单的错误页面,最难的解决方法是确保您的错误页面在任何地方都没有做出任何假设(例如 Session 不会抛出异常)和不可能出错。

于 2010-08-13T19:04:31.273 回答
0

我发现如果您使用 redirectMode="ResponseRewrite" 那么您需要在 web.config 文件的重写区域中添加一些内容。问题是当你的网站坏了!您无法 URL 重写,因为您的站点无法调用处理您的重写的“virtual.aspx”!

于 2011-03-22T12:06:40.597 回答