[asp.net] ASP.NET 사용자 지정 오류 페이지-Server.GetLastError ()가 null입니다.

내 응용 프로그램에 대해 사용자 지정 오류 페이지가 설정되어 있습니다.

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

Global.asax, Application_Error ()에서 다음 코드는 예외 세부 정보를 가져 오기 위해 작동합니다.

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

내 오류 페이지 (~ / errors / GeneralError.aspx.cs)에 도달 할 때까지 Server.GetLastError ()는 null입니다.

Global.asax.cs가 아닌 오류 페이지에서 예외 세부 정보를 얻을 수있는 방법이 있습니까?

Vista / IIS7의 ASP.NET 3.5



답변

내 web.config 설정을 자세히 살펴보면 이 게시물 의 의견 중 하나 가 매우 유용합니다.

asp.net 3.5 sp1에는 새로운 매개 변수 redirectMode가 있습니다.

따라서이 customErrors매개 변수를 추가 하도록 수정할 수 있습니다.

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

ResponseRewrite모드를 사용하면 브라우저를 리디렉션하지 않고«오류 페이지»를로드 할 수 있으므로 URL은 동일하게 유지되며 중요한 것은 예외 정보가 손실되지 않는다는 것입니다.


답변

좋아요,이 게시물을 찾았습니다 :
http://msdn.microsoft.com/en-us/library/aa479319.aspx

이 매우 예시적인 다이어그램으로 :

도표
(출처 : microsoft.com )

본질적으로 이러한 예외 세부 정보를 얻으려면 나중에 사용자 지정 오류 페이지에서 검색 할 수 있도록 Global.asax에 직접 저장해야합니다.

가장 좋은 방법은 Global.asax에서 대부분의 작업을 수행하는 것 같습니다. 사용자 지정 오류 페이지는 논리가 아닌 유용한 콘텐츠를 처리합니다.


답변

NailItDown과 Victor가 말한 것의 조합. 선호하는 / 가장 쉬운 방법은 Global.Asax를 사용하여 오류를 저장 한 다음 사용자 지정 오류 페이지로 리디렉션하는 것입니다.

Global.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.config 를 설정해야합니다 .

  <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()global.asax.cs 메서드

그런 다음 Page_Load()ErrorPage.aspx.cs 내에서 다음 과 같은 작업을 수행해도됩니다.Exception exception = Server.GetLastError().GetBaseException();

Server.Transfer() 예외가 계속되는 것 같습니다.


답변

여기에 몇 가지 좋은 답변이 있지만 오류 페이지에 시스템 예외 메시지를 표시하는 것은 좋지 않다는 점을 지적해야합니다 (이는 사용자가 원하는 작업입니다). 원하지 않는 것을 악의적 인 사용자에게 실수로 공개 할 수 있습니다. 예를 들어 Sql Server 예외 메시지는 매우 장황하며 오류 발생시 데이터베이스의 사용자 이름, 암호 및 스키마 정보를 제공 할 수 있습니다. 해당 정보는 최종 사용자에게 표시되지 않아야합니다.


답변

여기 내 해결책이 있습니다 ..

Global.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");
    }

Oops.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;
        }
    }


답변

여기에서 모두가 놓치고 있다고 생각하는 한 가지 중요한 고려 사항은로드 밸런싱 (웹 팜) 시나리오입니다. global.asax를 실행하는 서버는 사용자 지정 오류 페이지를 실행하는 서버와 다를 수 있으므로 Application에 예외 개체를 숨기는 것은 신뢰할 수 없습니다.

나는 여전히 웹 팜 구성 에서이 문제에 대한 신뢰할 수있는 솔루션을 찾고 있으며, 사용자 지정 오류 페이지에서 Server.GetLastError로 예외를 선택할 수없는 이유에 대한 MS의 좋은 설명을 찾고 있습니다. global.asax Application_Error에서.

PS 데이터를 먼저 잠근 다음 잠금 해제하지 않고 응용 프로그램 컬렉션에 데이터를 저장하는 것은 안전하지 않습니다.