CustomErrors не работает при установке redirectMode = "ResponseRewrite" - PullRequest
70 голосов
/ 23 апреля 2009

На старом сайте я изменил способ работы CustomErrors, добавив redirectMode="ResponseRewrite" (новое в 3.5 SP1):

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

Дело в том, что он показывает мне общую страницу ошибки (ту, которую вы получаете, если не установить customErrors. Если я удаляю часть redirectMode="ResponseRewrite", она работает нормально.

Я уверен, что 3.5 SP1 установлен на сервере, потому что я использую ту же настройку на других сайтах, размещенных на том же сервере.

Есть идеи?

Ответы [ 9 ]

99 голосов
/ 22 сентября 2010

Важно отметить, что для любого, кто пытается сделать это в приложении MVC, ResponseRewrite использует Server.Transfer за кулисами. Следовательно, defaultRedirect должен соответствовать допустимому файлу в файловой системе. Очевидно, Server.Transfer не совместим с маршрутами MVC, поэтому, если ваша страница с ошибкой обслуживается действием контроллера, Server.Transfer будет искать / Error / Wh чем-то, не найти его в файловой системе и вернуть общий Страница ошибки 404!

46 голосов
/ 11 марта 2012

Единственный способ, который отлично сработал для меня, - отключить пользовательские ошибки и заменить страницы ошибок iis через web.config. Он отправляет правильный код состояния с ответом и имеет преимущество, что он не проходит через 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

20 голосов
/ 16 февраля 2010

Происходит то, что IIS просматривает код состояния ошибки и представляет свою страницу ошибок вместо вашей. Чтобы решить эту проблему, вам нужно установить это в коде за страницей страницы с ошибкой, чтобы IIS не делал это:

Response.TrySkipIisCustomErrors = true;

Это будет работать только в IIS7 или выше, для более ранних версий IIS вам придется поиграть с настройками страницы ошибки.

14 голосов
/ 31 марта 2015

Из-за использования 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 Development Server, 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>
9 голосов
/ 06 августа 2009

Я знаю, что этот вопрос немного устарел, но я подумал, что должен указать, что для его работы не требуется статический файл.

Я столкнулся с подобной вещью, и это просто вопрос обнаружения этой ошибки в вашем Error.aspx, в нашем случае это произошло потому, что используемая мастер-страница опиралась на часть данных сеанса, а когда был установлен ResponseRewrite, сеанс недоступно для нашей страницы Error.aspx.

Я еще не выяснил, связана ли эта недоступность сеанса с нашей конкретной конфигурацией приложения или с частью "специально разработанной" части ASP.net.

1 голос
/ 08 декабря 2014

Я создал страницу с ошибкой в ​​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

1 голос
/ 23 апреля 2009

Я обнаружил, что проблема была в Error.aspx. По-прежнему не удается найти фактическую ошибку в error.aspx, которая вызывает проблему.

Изменение страницы в статический HTML-файл решило проблему.

0 голосов
/ 22 марта 2011

Я обнаружил, что если вы используете redirectMode = "ResponseRewrite", вам нужно что-то добавить в область перезаписи файла web.config. Проблема в том, что ваш сайт не работает! Вы не можете переписать URL, так как ваш сайт не может вызвать «virtual.aspx», который обрабатывает ваше переписывание!

0 голосов
/ 13 августа 2010

В моем конкретном случае моя страница с ошибкой содержала главную страницу с пользовательским элементом управления, который пытался использовать Session. Если Session недоступен, вы получаете HttpException: «Состояние Session может использоваться только в том случае, если для enableSessionState установлено значение true, либо в файле конфигурации, либо в директиве Page». Самое простое решение - перейти на статический html, второе самое простое - использовать более простую страницу с ошибкой, самое сложное - убедиться, что ваша страница с ошибками нигде не делает никаких предположений (например, Session не будет выдавать исключение), и не может быть ошибки.

...