ASP.NET пользовательская страница ошибки-сервер.GetLastError () имеет значение null


у меня есть настраиваемая страница ошибок, настроенная для моего приложения:

<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>

В Глобальном Масштабе.asax, Application_Error (), следующий код работает для получения сведений об исключении:

  Exception ex = Server.GetLastError();
  if (ex != null)
    {
        if (ex.GetBaseException() != null)
            ex = ex.GetBaseException();
    }

к тому времени, как я доберусь до своей страницы ошибок (~/errors/GeneralError.aspx.КС), сервер.GetLastError () - это null

есть ли способ я могу получить сведения об исключении на странице ошибки, а не в глобальном.асакс.в CS ?

ASP.NET 3.5 на Vista / IIS7

10 109

10 ответов:

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

в asp.net 3.5 с пакетом обновления 1 появился новый параметр redirectMode

Так что мы можем изменить customErrors добавить этот параметр:

<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />

the ResponseRewrite режим позволяет нам загружать "страницу ошибок" без перенаправления браузера, поэтому URL-адрес остается прежним, и, что важно для меня, информация об исключении не теряется.

ОК, я нашел этот пост: http://msdn.microsoft.com/en-us/library/aa479319.aspx

с этой очень наглядной диаграммой:

диаграмма http://i.msdn.microsoft.com/Aa479319.customerrors_01(Ан-нас,в MSDN.10).гиф

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

кажется, лучший способ-сделать большую часть работы в Глобальный.asax, с пользовательскими страницами ошибок, обрабатывающими полезное содержимое, а не логику.

сочетание того, что сказал Нейлитдаун и Виктор. Предпочтительный / самый простой способ-использовать ваш глобальный.Asax для хранения ошибки, а затем перенаправить на пользовательскую страницу ошибки.

глобальные.асакс:

    void Application_Error(object sender, EventArgs e) 
{
    // Code that runs when an unhandled error occurs
    Exception ex = Server.GetLastError();
    Application["TheException"] = ex; //store the error for later
    Server.ClearError(); //clear the error so we can continue onwards
    Response.Redirect("~/myErrorPage.aspx"); //direct user to error page
}

кроме того, вам нужно настроить свой web.конфигурации:

  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx">
    </customErrors>
  </system.web>

и, наконец, сделайте все, что вам нужно, за исключением того, что вы сохранили в своем страница ошибки:

protected void Page_Load(object sender, EventArgs e)
{

    // ... do stuff ...
    //we caught an exception in our Global.asax, do stuff with it.
    Exception caughtException = (Exception)Application["TheException"];
    //... do stuff ...
}

попробуйте использовать что-то вроде Server.Transfer("~/ErrorPage.aspx"); внутри Application_Error() метод глобальной.асакс.cs

затем в Page_Load() из ErrorPage.aspx.cs вы должны быть в порядке, чтобы сделать что-то вроде: Exception exception = Server.GetLastError().GetBaseException();

Server.Transfer() кажется, чтобы сохранить исключение висит вокруг.

хотя здесь есть несколько хороших ответов, я должен отметить, что не рекомендуется отображать сообщения об исключениях системы на страницах ошибок (что я предполагаю, что вы хотите сделать). Вы можете непреднамеренно раскрыть то, что вы не хотите делать, злонамеренным пользователям. Например, сообщения об исключениях Sql Server очень подробны и могут давать имя пользователя, пароль и сведения о схеме базы данных при возникновении ошибки. Эта информация не должна отображаться до конца пользователь.

одно важное соображение, которое я думаю, что все здесь отсутствует,-это сценарий балансировки нагрузки (веб-ферма). Так как сервер, который выполняет глобальный.asax может отличаться от сервера, на котором выполняется пользовательская страница ошибки, сохранение объекта исключения в приложении не является надежным.

Я все еще ищу надежное решение этой проблемы в конфигурации веб-фермы и/или хорошее объяснение от MS о том, почему вы просто не можете забрать исключение с помощью Сервер.GetLastError на пользовательской странице ошибки, как вы можете в глобальном.эйсакс application_error для перехвата.

P. S. Это небезопасно для хранения данных в коллекции приложения без блокировки, а затем разблокировки.

вот мое решение..

В Глобальном Масштабе.aspx:

void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs

        //direct user to error page 
        Server.Transfer("~/ErrorPages/Oops.aspx"); 
    }

В Упс.aspx:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadError(Server.GetLastError()); 
    }

    protected void LoadError(Exception objError)
    {
        if (objError != null)
        {
            StringBuilder lasterror = new StringBuilder();

            if (objError.Message != null)
            {
                lasterror.AppendLine("Message:");
                lasterror.AppendLine(objError.Message);
                lasterror.AppendLine();
            }

            if (objError.InnerException != null)
            {
                lasterror.AppendLine("InnerException:");
                lasterror.AppendLine(objError.InnerException.ToString());
                lasterror.AppendLine();
            }

            if (objError.Source != null)
            {
                lasterror.AppendLine("Source:");
                lasterror.AppendLine(objError.Source);
                lasterror.AppendLine();
            }

            if (objError.StackTrace != null)
            {
                lasterror.AppendLine("StackTrace:");
                lasterror.AppendLine(objError.StackTrace);
                lasterror.AppendLine();
            }

            ViewState.Add("LastError", lasterror.ToString());
        }
    }

   protected void btnReportError_Click(object sender, EventArgs e)
    {
        SendEmail();
    }

    public void SendEmail()
    {
        try
        {
            MailMessage msg = new MailMessage("webteam", "webteam");
            StringBuilder body = new StringBuilder();

            body.AppendLine("An unexcepted error has occurred.");
            body.AppendLine();

            body.AppendLine(ViewState["LastError"].ToString());

            msg.Subject = "Error";
            msg.Body = body.ToString();
            msg.IsBodyHtml = false;

            SmtpClient smtp = new SmtpClient("exchangeserver");
            smtp.Send(msg);
        }

        catch (Exception ex)
        {
            lblException.Text = ex.Message;
        }
    }

это связано с этими 2 темами ниже, я хочу получить как GetHtmlErrorMessage и сессии на странице ошибок.

сеанс равен нулю после ResponseRewrite

почему HttpContext.Сеанс null, когда redirectMode = ResponseRewrite

я попробовал и вижу решение, которое не нужно Server.Transfer() or Response.Redirect()

во-первых: удалить ResponseRewrite в сеть.конфигурации

Web.конфигурации

<customErrors defaultRedirect="errorHandler.aspx" mode="On" />

Затем Глобальной.асакс

    void Application_Error(object sender, EventArgs e)
    {
         if(Context.IsCustomErrorEnabled)
         {     
            Exception ex = Server.GetLastError();
            Application["TheException"] = ex; //store the error for later
         }
    }

затем errorHandler.aspx.cs

        protected void Page_Load(object sender, EventArgs e)
            {       
                string htmlErrorMessage = string.Empty ;
                Exception ex = (Exception)Application["TheException"];
                string yourSessionValue = HttpContext.Current.Session["YourSessionId"].ToString();

                //continue with ex to get htmlErrorMessage 
                if(ex.GetHtmlErrorMessage() != null){              
                    htmlErrorMessage = ex.GetHtmlErrorMessage();
                }   
                // continue your code
            }

ссылки

http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm

Я думаю, что у вас есть несколько вариантов здесь.

вы можете сохранить последнее исключение в сеансе и получить его со своей страницы пользовательских ошибок; или вы можете просто перенаправить на свою страницу пользовательских ошибок в событии Application_error. Если вы выберете последнее, вы хотите убедиться, что используете сервер.Метод передачи.

это сработало для меня. в MVC 5


в ~\Global.asax

void Application_Error(object sender, EventArgs e)
{
    FTools.LogException();
    Response.Redirect("/Error");
}


в ~\Controllers создать ErrorController.cs

using System.Web.Mvc;

namespace MVC_WebApp.Controllers
{
    public class ErrorController : Controller
    {
        // GET: Error
        public ActionResult Index()
        {
            return View("Error");
        }
    }
}


в ~\Models создать FunctionTools.cs

using System;
using System.Web;

namespace MVC_WebApp.Models
{
    public static class FTools
    {
        private static string _error;
        private static bool _isError;

        public static string GetLastError
        {
            get
            {
                string cashe = _error;
                HttpContext.Current.Server.ClearError();
                _error = null;
                _isError = false;
                return cashe;
            }
        }
        public static bool ThereIsError => _isError;

        public static void LogException()
        {
            Exception exc = HttpContext.Current.Server.GetLastError();
            if (exc == null) return;
            string errLog = "";
            errLog += "**********" + DateTime.Now + "**********\n";
            if (exc.InnerException != null)
            {
                errLog += "Inner Exception Type: ";
                errLog += exc.InnerException.GetType() + "\n";
                errLog += "Inner Exception: ";
                errLog += exc.InnerException.Message + "\n";
                errLog += "Inner Source: ";
                errLog += exc.InnerException.Source + "\n";
                if (exc.InnerException.StackTrace != null)
                {
                    errLog += "\nInner Stack Trace: " + "\n";
                    errLog += exc.InnerException.StackTrace + "\n";
                }
            }
            errLog += "Exception Type: ";
            errLog += exc.GetType().ToString() + "\n";
            errLog += "Exception: " + exc.Message + "\n";
            errLog += "\nStack Trace: " + "\n";
            if (exc.StackTrace != null)
            {
                errLog += exc.StackTrace + "\n";
            }
            _error = errLog;
            _isError = true;
        }
    }
}


в ~\Views Создать Папку Error и в ~\Views\Error создать Error.cshtml

@using MVC_WebApp.Models
@{
    ViewBag.Title = "Error";
    if (FTools.ThereIsError == false)
    {
        if (Server.GetLastError() != null)
        {
            FTools.LogException();
        }
    }
    if (FTools.ThereIsError == false)
    {
        <br />
        <h1>No Problem!</h1>
    }
    else
    {
        string log = FTools.GetLastError;
        <div>@Html.Raw(log.Replace("\n", "<br />"))</div>
    }
}


если вы введете этот адрес localhost/Error open page Whithout Error



а если произойдет ошибка error occurs

как может быть вместо отображения ошибок, переменная ' log ' будет храниться в базе данных


источник: Microsoft ASP.Net